Skip to content

Commit fefdc45

Browse files
committed
documentation
1 parent 0d24744 commit fefdc45

2 files changed

Lines changed: 36 additions & 7 deletions

File tree

Sources/BetterCodable/DefaultCodable.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import Foundation
66
/// a reasonable default value for missing Decodable data.
77
public protocol DefaultCodableStrategy {
88
associatedtype DefaultValue: Codable
9-
9+
10+
/// The fallback value used when decoding fails
1011
static var defaultValue: DefaultValue { get }
1112
}
1213

Sources/BetterCodable/LosslessValue.swift

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ import Foundation
22

33
public typealias LosslessStringCodable = LosslessStringConvertible & Codable
44

5-
/// Provides an ordered list of types for decoding the lossless value, prioritizing the first type that successfully decodes as the produced value.
5+
/// Provides an ordered list of types for decoding the lossless value, prioritizing the first type that successfully decodes as the inferred type.
66
///
7-
/// `LosslessDecodingStrategy` provides a generic strategy type that the `LosslessValueCodable` property wrapper can use to provide
8-
/// the ordered list of decodable types in order to maximize preservation and robustness for the otherwise lossy data.
7+
/// `LosslessDecodingStrategy` provides a generic strategy that the `LosslessValueCodable` property wrapper can use to provide
8+
/// the ordered list of decodable types in order to maximize preservation for the inferred type.
99
public protocol LosslessDecodingStrategy {
1010
associatedtype Value: LosslessStringCodable
1111

12+
/// An ordered list of decodable scenarios used to infer the encoded type
1213
static var losslessDecodableTypes: [(Decoder) -> LosslessStringCodable?] { get }
1314
}
1415

@@ -69,6 +70,7 @@ extension LosslessValueCodable: Hashable where Strategy.Value: Hashable {
6970

7071
public struct LosslessDefaultStrategy<Value: LosslessStringCodable>: LosslessDecodingStrategy {
7172
public static var losslessDecodableTypes: [(Decoder) -> LosslessStringCodable?] {
73+
@inline(__always)
7274
func decode<T: LosslessStringCodable>(_: T.Type) -> (Decoder) -> LosslessStringCodable? {
7375
return { try? T.init(from: $0) }
7476
}
@@ -92,10 +94,12 @@ public struct LosslessDefaultStrategy<Value: LosslessStringCodable>: LosslessDec
9294

9395
public struct LosslessBooleanStrategy<Value: LosslessStringCodable>: LosslessDecodingStrategy {
9496
public static var losslessDecodableTypes: [(Decoder) -> LosslessStringCodable?] {
97+
@inline(__always)
9598
func decode<T: LosslessStringCodable>(_: T.Type) -> (Decoder) -> LosslessStringCodable? {
9699
return { try? T.init(from: $0) }
97100
}
98101

102+
@inline(__always)
99103
func decodeBoolFromNSNumber() -> (Decoder) -> LosslessStringCodable? {
100104
return { (try? Int.init(from: $0)).flatMap { Bool(exactly: NSNumber(value: $0)) } }
101105
}
@@ -125,15 +129,39 @@ public struct LosslessBooleanStrategy<Value: LosslessStringCodable>: LosslessDec
125129
/// This is useful when data may return unpredictable values when a consumer is expecting a certain type. For instance,
126130
/// if an API sends SKUs as either an `Int` or `String`, then a `@LosslessValue` can ensure the types are always decoded
127131
/// as `String`s.
132+
///
133+
/// ```
134+
/// struct Product: Codable {
135+
/// @LosslessValue var sku: String
136+
/// @LosslessValue var id: String
137+
/// }
138+
///
139+
/// // json: { "sku": 87, "id": 123 }
140+
/// let value = try JSONDecoder().decode(Product.self, from: json)
141+
/// // value.sku == "87"
142+
/// // value.id == "123"
143+
/// ```
128144
public typealias LosslessValue<T> = LosslessValueCodable<LosslessDefaultStrategy<T>> where T: LosslessStringCodable
129145

130146
/// Decodes Codable values into their respective preferred types.
131147
///
132148
/// `@LosslessBoolValue` attempts to decode Codable types into their respective preferred types while preserving the data.
133149
///
134150
/// - Note:
151+
/// This uses a `LosslessBooleanStrategy` in order to prioritize boolean values, and as such, some integer values will be lossy.
152+
///
153+
/// For instance, if you decode `{ "some_type": 1 }` then `some_type` will be `true` and not `1`. If you do not want this
154+
/// behavior then use `@LosslessValue` or create a custom `LosslessDecodingStrategy`.
155+
///
156+
/// ```
157+
/// struct Example: Codable {
158+
/// @LosslessBoolValue var foo: Bool
159+
/// @LosslessValue var bar: Int
160+
/// }
135161
///
136-
/// This differs from `@LosslessValue` in that it strongly prefers to keep the boolean value above all else, and some integer values will be lossy. For instance,
137-
/// if you decode `{ "some_type": 1 }` then `some_type` will be `true` and not `1`. If you do not want this behavior then stick with `@LosslessValue` or create
138-
/// your own custom `LosslessDecodingStrategy` type.
162+
/// // json: { "foo": 1, "bar": 2 }
163+
/// let value = try JSONDecoder().decode(Fixture.self, from: json)
164+
/// // value.foo == true
165+
/// // value.bar == 2
166+
/// ```
139167
public typealias LosslessBoolValue<T> = LosslessValueCodable<LosslessBooleanStrategy<T>> where T: LosslessStringCodable

0 commit comments

Comments
 (0)