Skip to content

Commit

Permalink
Improve nesting
Browse files Browse the repository at this point in the history
  • Loading branch information
pauljohanneskraft committed Apr 16, 2021
1 parent efdb898 commit 0726354
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 4 deletions.
5 changes: 4 additions & 1 deletion Sources/CodableCSV/Containers/DecodingStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ final class DecodingStorage {
guard let value = dictionary[nesting.nest(codingPath: codingPath)] else {
throw CSVCodingError.pathNotFound(codingPath)
}
if none.decodeNil(value, codingPath: codingPath) {
throw CSVCodingError.couldNotDecode(value, as: String.self)
}
return value
}

Expand All @@ -56,7 +59,7 @@ final class DecodingStorage {
func isAtEnd(codingPath: [CodingKey]) -> Bool {
let key = nesting.nest(codingPath: codingPath)
if let value = dictionary[key] {
return (try? none.decodeNil(value, codingPath: codingPath)) ?? true
return none.decodeNil(value, codingPath: codingPath)
}
return !dictionary.keys.contains(where: { $0.hasPrefix(key) })
}
Expand Down
12 changes: 12 additions & 0 deletions Sources/CodableCSV/Containers/KeyedDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ extension KeyedDecoder: KeyedDecodingContainerProtocol {
return try decoder.decode(T.self)
}

func decodeIfPresent<T: Decodable>(_ type: T.Type, forKey key: Key) throws -> T? {
do {
return try decode(T.self, forKey: key)
} catch {
if try decodeNil(forKey: key) {
return nil
} else {
throw error
}
}
}

// MARK: Methods - Containers

func nestedContainer<NestedKey: CodingKey>(keyedBy type: NestedKey.Type,
Expand Down
2 changes: 1 addition & 1 deletion Sources/CodableCSV/Options/None+Empty.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ private struct EmptyStrategy: NoneStrategy {
.init()
}

func decodeNil(_ string: String, codingPath: [CodingKey]) throws -> Bool {
func decodeNil(_ string: String, codingPath: [CodingKey]) -> Bool {
string.isEmpty
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/CodableCSV/Options/None+Null.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ private struct WordStrategy: NoneStrategy {
word
}

func decodeNil(_ string: String, codingPath: [CodingKey]) throws -> Bool {
func decodeNil(_ string: String, codingPath: [CodingKey]) -> Bool {
string == word
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/CodableCSV/Options/None.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

public protocol NoneStrategy {
func encodeNil(codingPath: [CodingKey]) throws -> String
func decodeNil(_ string: String, codingPath: [CodingKey]) throws -> Bool
func decodeNil(_ string: String, codingPath: [CodingKey]) -> Bool
}

public struct CSVNone {
Expand Down
32 changes: 32 additions & 0 deletions Tests/CodableCSVTests/CodableCSVTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,38 @@ final class CodableCSVTests: XCTestCase {
}
}

func testNesting3() {
struct InnerType: Codable, Equatable {
var name: String
}
struct OuterType: Codable, Equatable {
var age: Int
var inner: InnerType?
}
let objects = [OuterType(age: 10, inner: InnerType(name: "Paul")), OuterType(age: 12, inner: InnerType(name: "Peter")), OuterType(age: 15, inner: nil)]

let encodingExpectation = self.expectation(description: "encoder")
encodingExpectation.expectedFulfillmentCount = 2
var encoder = CSVEncoder()
encoder.register(for: InnerType.self) { inner in
encodingExpectation.fulfill()
return inner.name
}
var decoder = CSVDecoder()
decoder.register(InnerType.init)

let encoded = try! encoder.encode(objects)
wait(for: [encodingExpectation], timeout: 2)
print(String(data: encoded, encoding: .utf8) ?? "nil")
let decoded = try! decoder.decode(OuterType.self, from: encoded)
XCTAssertEqual(objects, decoded)

let o = (0..<100).flatMap { _ in objects }
measure {
measurableTest(objects: o)
}
}

func testAllPrimitives() {
struct TestType: Codable, Equatable {
var bool: Bool?
Expand Down

0 comments on commit 0726354

Please sign in to comment.