Skip to content

Commit 7bc9425

Browse files
committed
Documentation for custom encoding/decoding strategies added
1 parent c80a145 commit 7bc9425

File tree

3 files changed

+110
-31
lines changed

3 files changed

+110
-31
lines changed

README.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,10 @@ let decoder = CSVDecoder {
365365
$0.delimiters.field = "\t"
366366
$0.headerStrategy = .firstLine
367367
$0.bufferingStrategy = .keepAll
368-
}
369-
370-
decoder.decimalStrategy = .custom { (decoder) in
371-
let value = try Float(from: decoder)
372-
return Decimal(value)
368+
$0.decimalStrategy = .custom({ (decoder) in
369+
let value = try Float(from: decoder)
370+
return Decimal(value)
371+
})
373372
}
374373
```
375374
@@ -458,13 +457,12 @@ let encoder = CSVEncoder {
458457
$0.delimiters = (field: ";", row: "\r\n")
459458
$0.dateStrategy = .iso8601
460459
$0.bufferingStrategy = .sequential
461-
}
462-
463-
encoder.floatStrategy = .convert(positiveInfinity: "", negativeInfinity: "-∞", nan: "")
464-
encoder.dataStrategy = .custom { (data, encoder) in
465-
let string = customTransformation(data)
466-
var container = try encoder.singleValueContainer()
467-
try container.encode(string)
460+
$0.floatStrategy = .convert(positiveInfinity: "", negativeInfinity: "-∞", nan: "")
461+
$0.dataStrategy = .custom { (data, encoder) in
462+
let string = customTransformation(data)
463+
var container = try encoder.singleValueContainer()
464+
try container.encode(string)
465+
}
468466
}
469467
```
470468

sources/declarative/decodable/DecoderConfiguration.swift

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ extension Strategy {
4949
/// An empty string can be both the absence of characters between field delimiters and an empty escaped field (e.g. `""`).
5050
case empty
5151
/// Decodes the `nil` as a custom value decoded by the given closure.
52+
///
53+
/// Custom `nil` decoding adheres to the same behavior as a custom `Decodable` type. For example:
54+
///
55+
/// let decoder = CSVDecoder()
56+
/// decoder.nilStrategy = .custom({
57+
/// let container = try $0.singleValueContainer()
58+
/// let string = try container.decode(String.self)
59+
/// return string == "-"
60+
/// })
61+
///
5262
/// - parameter decoding: Function receiving the CSV decoder used to parse a custom `nil` value.
5363
/// - parameter decoder: The decoder on which to fetch a single value container to obtain the underlying `String` value.
5464
/// - returns: Boolean indicating whether the encountered value was a `nil` representation. If the value is not supported, return `false`.
@@ -65,11 +75,22 @@ extension Strategy {
6575
///
6676
/// The value: `True`, `TRUE`, `TruE` or `YES`are accepted.
6777
case insensitive
68-
/// Decodes the `Bool` from an underlying `0`/`1`
78+
/// Decodes the `Bool` from an underlying `0` or `1`
6979
case numeric
70-
/// Decodes the `Bool` as a custom value decoded by the given closure.
80+
/// Decodes the `Bool` as a custom value decoded by the given closure. If the closure fails to decode a value from the given decoder, the error will be bubled up.
81+
///
82+
/// Custom `Bool` decoding adheres to the same behavior as a custom `Decodable` type. For example:
83+
///
84+
/// let decoder = CSVDecoder()
85+
/// decoder.boolStrategy = .custom({
86+
/// let container = try $0.singleValueContainer()
87+
/// switch try container.decode(String.self) {
88+
/// case "si": return true
89+
/// case "no": return false
90+
/// default: throw CSVError<CSVDecoder>(...)
91+
/// }
92+
/// })
7193
///
72-
/// If the closure fails to decode a value from the given decoder, the error will be bubled up.
7394
/// - parameter decoding: Function receiving the CSV decoder used to parse a custom `Bool` value.
7495
/// - parameter decoder: The decoder on which to fetch a single value container to obtain the underlying `String` value.
7596
/// - returns: Boolean value decoded from the underlying storage.
@@ -80,9 +101,16 @@ extension Strategy {
80101
public enum DecimalDecoding {
81102
/// The locale used to interpret the number (specifically `decimalSeparator`).
82103
case locale(Locale? = nil)
83-
/// Decode the `Decimal` as a custom value decoded by the given closure.
104+
/// Decode the `Decimal` as a custom value decoded by the given closure. If the closure fails to decode a value from the given decoder, the error will be bubled up.
105+
///
106+
/// Custom `Decimal` decoding adheres to the same behavior as a custom `Decodable` type. For example:
107+
///
108+
/// let decoder = CSVDecoder()
109+
/// decoder.decimalStrategy = .custom({
110+
/// let value = try Float(from: decoder)
111+
/// return Decimal(value)
112+
/// })
84113
///
85-
/// If the closure fails to decode a value from the given decoder, the error will be bubled up.
86114
/// - parameter decoding: Function receiving the CSV decoder used to parse a custom `Decimal` value.
87115
/// - parameter decoder: The decoder on which to fetch a single value container to obtain the underlying `String` value.
88116
/// - returns: `Decimal` value decoded from the underlying storage.
@@ -101,9 +129,17 @@ extension Strategy {
101129
case iso8601
102130
/// Decode the `Date` as a string parsed by the given formatter.
103131
case formatted(DateFormatter)
104-
/// Decode the `Date` as a custom value decoded by the given closure.
132+
/// Decode the `Date` as a custom value decoded by the given closure. If the closure fails to decode a value from the given decoder, the error will be bubled up.
133+
///
134+
/// Custom `Date` decoding adheres to the same behavior as a custom `Decodable` type. For example:
135+
///
136+
/// let decoder = CSVDecoder()
137+
/// decoder.dateStrategy = .custom({
138+
/// let container = try $0.singleValueContainer()
139+
/// let string = try container.decode(String.self)
140+
/// // Now returns the date represented by the custom string or throw an error if the string cannot be converted to a date.
141+
/// })
105142
///
106-
/// If the closure fails to decode a value from the given decoder, the error will be bubled up.
107143
/// - parameter decoding: Function receiving the CSV decoder used to parse a custom `Date` value.
108144
/// - parameter decoder: The decoder on which to fetch a single value container to obtain the underlying `String` value.
109145
/// - returns: `Date` value decoded from the underlying storage.
@@ -116,9 +152,17 @@ extension Strategy {
116152
case deferredToData
117153
/// Decode the `Data` from a Base64-encoded string.
118154
case base64
119-
/// Decode the `Data` as a custom value decoded by the given closure.
155+
/// Decode the `Data` as a custom value decoded by the given closure. If the closure fails to decode a value from the given decoder, the error will be bubled up.
156+
///
157+
/// Custom `Data` decoding adheres to the same behavior as a custom `Decodable` type. For example:
158+
///
159+
/// let decoder = CSVDecoder()
160+
/// decoder.dataStrategy = .custom({
161+
/// let container = try $0.singleValueContainer()
162+
/// let string = try container.decode(String.self)
163+
/// // Now returns the data represented by the custom string or throw an error if the string cannot be converted to a data.
164+
/// })
120165
///
121-
/// If the closure fails to decode a value from the given decoder, the error will be bubled up.
122166
/// - parameter decoding: Function receiving the CSV decoder used to parse a custom `Data` value.
123167
/// - parameter decoder: The decoder on which to fetch a single value container to obtain the underlying `String` value.
124168
/// - returns: `Data` value decoded from the underlying storage.

sources/declarative/encodable/EncoderConfiguration.swift

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,16 @@ extension Strategy {
4646
public enum NilEncoding {
4747
/// `nil` is encoded as an empty string.
4848
case empty
49-
/// Encode `nil` as a custom value encoded by the given closure.
49+
/// Encode `nil` as a custom value encoded by the given closure. If the closure fails to encode a value into the given encoder, the error will be bubled up.
50+
///
51+
/// Custom `nil` encoding adheres to the same behavior as a custom `Encodable` type. For example:
52+
///
53+
/// let encoder = CSVEncoder()
54+
/// encoder.nilStrategy = .custom({
55+
/// var container = try $0.singleValueContainer()
56+
/// try container.encode("-")
57+
/// })
5058
///
51-
/// If the closure fails to encode a value into the given encoder, the error will be bubled up.
5259
/// - parameter encoding: Function receiving the encoder instance to encode `nil`.
5360
/// - parameter encoder: The encoder on which to encode a custom `nil` representation.
5461
case custom(_ encoding: (_ encoder: Encoder) throws -> Void)
@@ -60,9 +67,16 @@ extension Strategy {
6067
case deferredToString
6168
/// Encode the `Bool` as `0` or `1`
6269
case numeric
63-
/// Encode the `Bool` as a custom value encoded by the given closure.
70+
/// Encode the `Bool` as a custom value encoded by the given closure. If the closure fails to encode a value into the given encoder, the error will be bubled up.
71+
///
72+
/// Custom `Bool` encoding adheres to the same behavior as a custom `Encodable` type. For example:
73+
///
74+
/// let encoder = CSVEncoder()
75+
/// encoder.boolStrategy = .custom({
76+
/// var container = try $1.singleValueContainer()
77+
/// try container.encode($0 ? "si" : "no")
78+
/// })
6479
///
65-
/// If the closure fails to encode a value into the given encoder, the error will be bubled up.
6680
/// - parameter encoding: Function receiving the necessary instances to encode a custom `Decimal` value.
6781
/// - parameter value: The value to be encoded.
6882
/// - parameter encoder: The encoder on which to generate a single value container.
@@ -74,9 +88,16 @@ extension Strategy {
7488
/// The locale used to write the number (specifically the `decimalSeparator` property).
7589
/// - parameter locale: The locale used to encode a `Decimal` value into a `String` value. If `nil`, the current user's locale will be used.
7690
case locale(_ locale: Locale? = nil)
77-
/// Encode the `Decimal` as a custom value encoded by the given closure.
91+
/// Encode the `Decimal` as a custom value encoded by the given closure. If the closure fails to encode a value into the given encoder, the error will be bubled up.
92+
///
93+
/// Custom `Decimal` encoding adheres to the same behavior as a custom `Encodable` type. For example:
94+
///
95+
/// let encoder = CSVEncoder()
96+
/// encoder.decimalStrategy = .custom({
97+
/// var container = try $1.singleValueContainer()
98+
/// try container.encode($0.description)
99+
/// })
78100
///
79-
/// If the closure fails to encode a value into the given encoder, the error will be bubled up.
80101
/// - parameter encoding: Function receiving the necessary instances to encode a custom `Decimal` value.
81102
/// - parameter value: The value to be encoded.
82103
/// - parameter encoder: The encoder on which to generate a single value container.
@@ -96,9 +117,17 @@ extension Strategy {
96117
/// Encode the `Date` as a string formatted by the given formatter.
97118
/// - parameter formatter: The date formatter used to encode a `Date` value into a `String`.
98119
case formatted(_ formatter: DateFormatter)
99-
/// Formats dates by calling a user-defined function.
120+
/// Formats dates by calling a user-defined function. If the closure fails to encode a value into the given encoder, the error will be bubled up.
121+
///
122+
/// Custom `Date` encoding adheres to the same behavior as a custom `Encodable` type. For example:
123+
///
124+
/// let encoder = CSVEncoder()
125+
/// encoder.dateStrategy = .custom({
126+
/// var container = try $1.singleValueContainer()
127+
/// let customRepresentation: String = // transform Date $0 into a String or throw if the date cannot be converted.
128+
/// try container.encode(customRepresentation)
129+
/// })
100130
///
101-
/// If the closure fails to encode a value into the given encoder, the error will be bubled up.
102131
/// - parameter encoding: Function receiving the necessary instances to encode a custom `Date` value.
103132
/// - parameter value: The value to be encoded.
104133
/// - parameter encoder: The encoder on which to generate a single value container.
@@ -111,9 +140,17 @@ extension Strategy {
111140
case deferredToData
112141
/// Encoded the `Data` as a Base64-encoded string.
113142
case base64
114-
/// Formats data blobs by calling a user defined function.
143+
/// Formats data blobs by calling a user defined function. If the closure fails to encode a value into the given encoder, the encoder will encode an empty automatic container in its place.
144+
///
145+
/// Custom `Data` encoding adheres to the same behavior as a custom `Encodable` type. For example:
146+
///
147+
/// let encoder = CSVEncoder()
148+
/// encoder.dataStrategy = .custom({
149+
/// var container = try $1.singleValueContainer()
150+
/// let customRepresentation: String = // transform Data $0 into a String or throw if the data cannot be converted.
151+
/// try container.encode(customRepresentation)
152+
/// })
115153
///
116-
/// If the closure fails to encode a value into the given encoder, the encoder will encode an empty automatic container in its place.
117154
/// - parameter encoding: Function receiving the necessary instances to encode a custom `Data` value.
118155
/// - parameter value: The value to be encoded.
119156
/// - parameter encoder: The encoder on which to generate a single value container.

0 commit comments

Comments
 (0)