Skip to content

Commit 1f1fc42

Browse files
committed
UnkeyedEncodingContainer implemented
1 parent 6dc7b55 commit 1f1fc42

File tree

9 files changed

+412
-230
lines changed

9 files changed

+412
-230
lines changed

sources/Active/Writer/WriterStrategy.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ extension CSVWriter: Failable {
3333
public static func errorDescription(for failure: Error) -> String {
3434
switch failure {
3535
case .invalidConfiguration: return "Invalid configuration"
36-
case .invalidInput: return "Invalid Input"
36+
case .invalidInput: return "Invalid input"
3737
case .streamFailure: return "Stream failure"
38-
case .invalidOperation: return "Invalid Operation"
38+
case .invalidOperation: return "Invalid operation"
3939
}
4040
}
4141
}

sources/Codable/Decodable/Containers/DecodingKeyed.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ fileprivate extension DecodingError {
309309
codingPath: codingPath,
310310
debugDescription: "The coding key identifying a CSV row couldn't be transformed into an integer value."))
311311
}
312-
/// Error raised when a single value container is requested on an invalid coding path.
312+
/// Error raised when a keyed container is requested on an invalid coding path.
313313
/// - parameter codingPath: The full chain of containers which generated this error.
314314
static func invalidContainerRequest(codingPath: [CodingKey]) -> DecodingError {
315315
DecodingError.dataCorrupted(

sources/Codable/Decodable/Containers/DecodingUnkeyed.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ extension ShadowDecoder {
6262
}
6363

6464
extension ShadowDecoder.UnkeyedContainer {
65-
mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> where NestedKey:CodingKey {
65+
mutating func nestedContainer<NestedKey:CodingKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
6666
switch self.focus {
6767
case .file:
6868
let rowIndex = self.currentIndex
6969
var codingPath = self.decoder.codingPath; codingPath.append(CodecKey(rowIndex))
7070
let decoder = ShadowDecoder(source: self.decoder.source, codingPath: codingPath)
7171
self.currentIndex += 1
72-
return KeyedDecodingContainer(ShadowDecoder.KeyedContainer<NestedKey>(unsafeDecoder: decoder, rowIndex: rowIndex))
72+
return KeyedDecodingContainer(ShadowDecoder.KeyedContainer(unsafeDecoder: decoder, rowIndex: rowIndex))
7373
case .row: throw DecodingError.invalidContainerRequest(codingPath: self.codingPath)
7474
}
7575
}
@@ -321,7 +321,7 @@ fileprivate extension DecodingError {
321321
codingPath: codingPath,
322322
debugDescription: "The coding key identifying a CSV row couldn't be transformed into an integer value."))
323323
}
324-
/// Error raised when a single value container is requested on an invalid coding path.
324+
/// Error raised when a unkeyed container is requested on an invalid coding path.
325325
/// - parameter codingPath: The full chain of containers which generated this error.
326326
static func invalidContainerRequest(codingPath: [CodingKey]) -> DecodingError {
327327
DecodingError.dataCorrupted(

sources/Codable/Encodable/Containers/EncodingKeyed.swift

Lines changed: 122 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import Foundation
2+
13
extension ShadowEncoder {
24
/// Keyed container for the CSV shadow encoder.
35
///
@@ -24,10 +26,10 @@ extension ShadowEncoder {
2426
self.focus = .file
2527
case 1:
2628
let key = encoder.codingPath[0]
27-
let r = try key.intValue ?! DecodingError.invalidKey(forRow: key, codingPath: encoder.codingPath)
29+
let r = try key.intValue ?! CSVEncoder.Error.invalidKey(forRow: key, codingPath: encoder.codingPath)
2830
self.focus = .row(r)
2931
default:
30-
throw DecodingError.invalidContainerRequest(codingPath: encoder.codingPath)
32+
throw CSVEncoder.Error.invalidContainerRequest(codingPath: encoder.codingPath)
3133
}
3234
self.encoder = encoder
3335
}
@@ -40,19 +42,49 @@ extension ShadowEncoder {
4042

4143
extension ShadowEncoder.KeyedContainer {
4244
mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey:CodingKey {
43-
fatalError()
45+
var codingPath = self.encoder.codingPath
46+
switch self.focus {
47+
case .file:
48+
guard let rowIndex = key.intValue else { fallthrough }
49+
codingPath.append(CodecKey(rowIndex))
50+
let encoder = ShadowEncoder(sink: self.encoder.sink, codingPath: codingPath)
51+
return KeyedEncodingContainer(ShadowEncoder.KeyedContainer<NestedKey>(unsafeEncoder: encoder, rowIndex: rowIndex))
52+
case .row:
53+
let error = CSVEncoder.Error.invalidContainerRequest(codingPath: codingPath)
54+
return .init(ShadowEncoder.FailContainer<NestedKey>(error: error, encoder: self.encoder))
55+
}
4456
}
4557

4658
mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
47-
fatalError()
59+
var codingPath = self.encoder.codingPath
60+
switch self.focus {
61+
case .file:
62+
guard let rowIndex = key.intValue else { fallthrough }
63+
codingPath.append(CodecKey(rowIndex))
64+
let encoder = ShadowEncoder(sink: self.encoder.sink, codingPath: codingPath)
65+
return ShadowEncoder.UnkeyedContainer(unsafeEncoder: encoder, rowIndex: rowIndex)
66+
case .row:
67+
let error = CSVEncoder.Error.invalidContainerRequest(codingPath: codingPath)
68+
return ShadowEncoder.FailContainer<CodecKey>(error: error, encoder: self.encoder)
69+
}
4870
}
4971

50-
mutating func superEncoder() -> Encoder {
51-
fatalError()
72+
mutating func superEncoder(forKey key: Key) -> Encoder {
73+
var codingPath = self.encoder.codingPath
74+
switch self.focus {
75+
case .file: codingPath.append(CodecKey(key.intValue ?? -1))
76+
case .row: codingPath.append(CodecKey(-1))
77+
}
78+
return ShadowEncoder(sink: self.encoder.sink, codingPath: codingPath)
5279
}
5380

54-
mutating func superEncoder(forKey key: Key) -> Encoder {
55-
fatalError()
81+
mutating func superEncoder() -> Encoder {
82+
var codingPath: [CodingKey] = self.codingPath
83+
switch self.focus {
84+
case .file: codingPath.append(CodecKey(0))
85+
case .row: codingPath.append(CodecKey(-1))
86+
}
87+
return ShadowEncoder(sink: self.encoder.sink, codingPath: codingPath)
5688
}
5789
}
5890

@@ -126,72 +158,72 @@ extension ShadowEncoder.KeyedContainer {
126158
}
127159
}
128160

129-
extension ShadowEncoder.KeyedContainer {
130-
mutating func encodeIfPresent(_ value: String?, forKey key: Key) throws {
131-
fatalError()
132-
}
133-
134-
mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
135-
fatalError()
136-
}
137-
138-
mutating func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
139-
fatalError()
140-
}
141-
142-
mutating func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
143-
fatalError()
144-
}
145-
146-
mutating func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
147-
fatalError()
148-
}
149-
150-
mutating func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
151-
fatalError()
152-
}
153-
154-
mutating func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
155-
fatalError()
156-
}
157-
158-
mutating func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
159-
fatalError()
160-
}
161-
162-
mutating func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
163-
fatalError()
164-
}
165-
166-
mutating func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
167-
fatalError()
168-
}
169-
170-
mutating func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
171-
fatalError()
172-
}
173-
174-
mutating func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
175-
fatalError()
176-
}
177-
178-
mutating func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
179-
fatalError()
180-
}
181-
182-
mutating func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
183-
fatalError()
184-
}
185-
186-
mutating func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T:Encodable {
187-
fatalError()
188-
}
189-
}
161+
//extension ShadowEncoder.KeyedContainer {
162+
// mutating func encodeIfPresent(_ value: String?, forKey key: Key) throws {
163+
// fatalError()
164+
// }
165+
//
166+
// mutating func encodeIfPresent(_ value: Bool?, forKey key: Key) throws {
167+
// fatalError()
168+
// }
169+
//
170+
// mutating func encodeIfPresent(_ value: Double?, forKey key: Key) throws {
171+
// fatalError()
172+
// }
173+
//
174+
// mutating func encodeIfPresent(_ value: Float?, forKey key: Key) throws {
175+
// fatalError()
176+
// }
177+
//
178+
// mutating func encodeIfPresent(_ value: Int?, forKey key: Key) throws {
179+
// fatalError()
180+
// }
181+
//
182+
// mutating func encodeIfPresent(_ value: Int8?, forKey key: Key) throws {
183+
// fatalError()
184+
// }
185+
//
186+
// mutating func encodeIfPresent(_ value: Int16?, forKey key: Key) throws {
187+
// fatalError()
188+
// }
189+
//
190+
// mutating func encodeIfPresent(_ value: Int32?, forKey key: Key) throws {
191+
// fatalError()
192+
// }
193+
//
194+
// mutating func encodeIfPresent(_ value: Int64?, forKey key: Key) throws {
195+
// fatalError()
196+
// }
197+
//
198+
// mutating func encodeIfPresent(_ value: UInt?, forKey key: Key) throws {
199+
// fatalError()
200+
// }
201+
//
202+
// mutating func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws {
203+
// fatalError()
204+
// }
205+
//
206+
// mutating func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws {
207+
// fatalError()
208+
// }
209+
//
210+
// mutating func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws {
211+
// fatalError()
212+
// }
213+
//
214+
// mutating func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws {
215+
// fatalError()
216+
// }
217+
//
218+
// mutating func encodeIfPresent<T>(_ value: T?, forKey key: Key) throws where T:Encodable {
219+
// fatalError()
220+
// }
221+
//}
190222

191223
// MARK: -
192224

193225
extension ShadowEncoder.KeyedContainer {
194-
/// CSV unkeyed container focus (i.e. where the container is able to operate on).
226+
/// CSV keyed container focus (i.e. where the container is able to operate on).
195227
private enum Focus {
196228
/// The container represents the whole CSV file and each encoding operation writes a row/record.
197229
case file
@@ -200,26 +232,28 @@ extension ShadowEncoder.KeyedContainer {
200232
}
201233
}
202234

203-
fileprivate extension DecodingError {
235+
fileprivate extension CSVEncoder.Error {
204236
/// Error raised when a coding key representing a row within the CSV file cannot be transformed into an integer value.
205237
/// - parameter codingPath: The whole coding path, including the invalid row key.
206-
static func invalidKey(forRow key: CodingKey, codingPath: [CodingKey]) -> DecodingError {
207-
DecodingError.keyNotFound(key, .init(
208-
codingPath: codingPath,
209-
debugDescription: "The coding key identifying a CSV row couldn't be transformed into an integer value."))
238+
static func invalidKey(forRow key: CodingKey, codingPath: [CodingKey]) -> CSVError<CSVEncoder> {
239+
.init(.invalidPath,
240+
reason: "The coding key identifying a CSV row couldn't be transformed into an integer value.",
241+
help: "The provided coding key identifying a CSV row must implement `intValue`.",
242+
userInfo: ["Coding path": codingPath])
210243
}
211-
/// Error raised when a single value container is requested on an invalid coding path.
244+
/// Error raised when a keyed value container is requested on an invalid coding path.
212245
/// - parameter codingPath: The full chain of containers which generated this error.
213-
static func invalidContainerRequest(codingPath: [CodingKey]) -> DecodingError {
214-
DecodingError.dataCorrupted(
215-
Context(codingPath: codingPath,
216-
debugDescription: "CSV doesn't support more than two nested decoding container.")
217-
)
218-
}
219-
// /// Error raised when a value is decoded, but a container was expected by the decoder.
220-
// static func invalidNestedRequired(codingPath: [CodingKey]) -> DecodingError {
221-
// DecodingError.dataCorrupted(.init(
222-
// codingPath: codingPath,
223-
// debugDescription: "A nested container is needed to decode CSV row values"))
224-
// }
246+
static func invalidContainerRequest(codingPath: [CodingKey]) -> CSVError<CSVEncoder> {
247+
.init(.invalidPath,
248+
reason: "CSV doesn't support more than two nested encoding container.",
249+
help: "Don't ask for a keyed encoding container on this coding path.",
250+
userInfo: ["Coding path": codingPath])
251+
}
252+
/// Error raised when a value is encoded, but a container was expected by the encoder.
253+
static func invalidNestedRequired(codingPath: [CodingKey]) -> CSVError<CSVEncoder> {
254+
.init(.invalidPath,
255+
reason: "A nested container is needed to encode at this coding path.",
256+
help: "Request a nested container instead of trying to decode a value directly.",
257+
userInfo: ["Coding path": codingPath])
258+
}
225259
}

0 commit comments

Comments
 (0)