From 4f7415edaa43ef24aecfa10bc3141cae48cc690a Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sat, 11 May 2019 21:14:27 +0100 Subject: [PATCH 1/5] Always encode empty elements as KeyedBox --- .../XMLCoder/Auxiliaries/Box/KeyedBox.swift | 2 +- .../XMLCoder/Auxiliaries/Box/NullBox.swift | 32 ------------------ .../XMLCoder/Auxiliaries/KeyedStorage.swift | 14 +------- .../Auxiliaries/XMLCoderElement.swift | 2 +- .../Decoder/DecodingErrorExtension.swift | 2 -- .../Decoder/XMLDecoderImplementation.swift | 10 +++--- .../Decoder/XMLKeyedDecodingContainer.swift | 2 +- .../Encoder/XMLEncoderImplementation.swift | 4 +-- .../Encoder/XMLKeyedEncodingContainer.swift | 2 +- .../Auxiliary/XMLElementTests.swift | 2 +- Tests/XMLCoderTests/Box/KeyedBoxTests.swift | 6 ++-- Tests/XMLCoderTests/Box/NullBoxTests.swift | 31 ----------------- Tests/XMLCoderTests/Box/SharedBoxTests.swift | 8 ++--- Tests/XMLCoderTests/Box/UnkeyedBoxTests.swift | 12 ++++--- Tests/XMLCoderTests/Minimal/KeyedTests.swift | 33 +++++++++++++++++++ XMLCoder.xcodeproj/project.pbxproj | 10 +----- ...76E090BF-7AFE-4988-A06A-3C423396A4A4.plist | 2 +- 17 files changed, 61 insertions(+), 113 deletions(-) delete mode 100644 Sources/XMLCoder/Auxiliaries/Box/NullBox.swift delete mode 100644 Tests/XMLCoderTests/Box/NullBoxTests.swift diff --git a/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift b/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift index dce3a1e9..3f6b5bf9 100644 --- a/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift +++ b/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift @@ -7,7 +7,7 @@ struct KeyedBox { typealias Key = String - typealias Attribute = SimpleBox + typealias Attribute = Box typealias Element = Box typealias Attributes = KeyedStorage diff --git a/Sources/XMLCoder/Auxiliaries/Box/NullBox.swift b/Sources/XMLCoder/Auxiliaries/Box/NullBox.swift deleted file mode 100644 index ecec12ca..00000000 --- a/Sources/XMLCoder/Auxiliaries/Box/NullBox.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// NullBox.swift -// XMLCoder -// -// Created by Vincent Esche on 12/17/18. -// - -struct NullBox {} - -extension NullBox: Box { - var isNull: Bool { - return true - } - - func xmlString() -> String? { - return nil - } -} - -extension NullBox: SimpleBox {} - -extension NullBox: Equatable { - static func ==(_: NullBox, _: NullBox) -> Bool { - return true - } -} - -extension NullBox: CustomStringConvertible { - var description: String { - return "null" - } -} diff --git a/Sources/XMLCoder/Auxiliaries/KeyedStorage.swift b/Sources/XMLCoder/Auxiliaries/KeyedStorage.swift index 9ae780eb..2f314aac 100644 --- a/Sources/XMLCoder/Auxiliaries/KeyedStorage.swift +++ b/Sources/XMLCoder/Auxiliaries/KeyedStorage.swift @@ -115,18 +115,6 @@ private extension KeyedStorage where Key == String, Value == Box { self[key] = content } } - - mutating func mergeNull(at key: String) { - switch self[key] { - case var unkeyedBox as UnkeyedBox: - unkeyedBox.append(NullBox()) - self[key] = unkeyedBox - case let box?: - self[key] = UnkeyedBox([box, NullBox()]) - default: - self[key] = NullBox() - } - } } extension KeyedStorage where Key == String, Value == Box { @@ -141,7 +129,7 @@ extension KeyedStorage where Key == String, Value == Box { } else if let value = element.value { result.merge(value: value, at: element.key) } else { - result.mergeNull(at: element.key) + result.mergeElementsAttributes(from: element) } return result diff --git a/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift b/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift index 766adb3a..3622a53f 100644 --- a/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift +++ b/Sources/XMLCoder/Auxiliaries/XMLCoderElement.swift @@ -48,7 +48,7 @@ struct XMLCoderElement: Equatable { func transformToBoxTree() -> KeyedBox { let attributes = KeyedStorage(self.attributes.map { key, value in - (key: key, value: StringBox(value) as SimpleBox) + (key: key, value: StringBox(value) as Box) }) let storage = KeyedStorage() var elements = self.elements.reduce(storage) { $0.merge(element: $1) } diff --git a/Sources/XMLCoder/Decoder/DecodingErrorExtension.swift b/Sources/XMLCoder/Decoder/DecodingErrorExtension.swift index a6f32681..9354a6b7 100644 --- a/Sources/XMLCoder/Decoder/DecodingErrorExtension.swift +++ b/Sources/XMLCoder/Decoder/DecodingErrorExtension.swift @@ -31,8 +31,6 @@ extension DecodingError { /// - precondition: `value` is one of the types below. static func _typeDescription(of box: Box) -> String { switch box { - case is NullBox: - return "a null value" case is BoolBox: return "a boolean value" case is DecimalBox: diff --git a/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift b/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift index d6212eb3..d7b4e6b9 100644 --- a/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift +++ b/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift @@ -149,14 +149,12 @@ extension XMLDecoderImplementation { guard let value = keyedBox.withShared({ $0.elements["value"] as? B }) else { - fallthrough + throw DecodingError.valueNotFound(valueType, DecodingError.Context( + codingPath: codingPath, + debugDescription: "Expected \(valueType) but found empty element instead." + )) } return value - case is NullBox: - throw DecodingError.valueNotFound(valueType, DecodingError.Context( - codingPath: codingPath, - debugDescription: "Expected \(valueType) but found null instead." - )) case let keyedBox as KeyedBox: guard let value = keyedBox.elements["value"] as? B diff --git a/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift b/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift index 797afaf3..4a394de0 100644 --- a/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift +++ b/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift @@ -397,7 +397,7 @@ extension XMLKeyedDecodingContainer { keyedBox.attributes[key.stringValue] } - let box: Box = elementOrNil ?? attributeOrNil ?? NullBox() + let box: Box = elementOrNil ?? attributeOrNil ?? KeyedBox() return XMLDecoderImplementation( referencing: box, options: decoder.options, diff --git a/Sources/XMLCoder/Encoder/XMLEncoderImplementation.swift b/Sources/XMLCoder/Encoder/XMLEncoderImplementation.swift index e0e710ee..7c0ef0bf 100644 --- a/Sources/XMLCoder/Encoder/XMLEncoderImplementation.swift +++ b/Sources/XMLCoder/Encoder/XMLEncoderImplementation.swift @@ -105,8 +105,8 @@ class XMLEncoderImplementation: Encoder { extension XMLEncoderImplementation { /// Returns the given value boxed in a container appropriate for pushing onto the container stack. - func box() -> SimpleBox { - return NullBox() + func box() -> Box { + return KeyedBox() } func box(_ value: Bool) -> SimpleBox { diff --git a/Sources/XMLCoder/Encoder/XMLKeyedEncodingContainer.swift b/Sources/XMLCoder/Encoder/XMLKeyedEncodingContainer.swift index f0e0a3b0..7ec99c52 100644 --- a/Sources/XMLCoder/Encoder/XMLKeyedEncodingContainer.swift +++ b/Sources/XMLCoder/Encoder/XMLKeyedEncodingContainer.swift @@ -65,7 +65,7 @@ struct XMLKeyedEncodingContainer: KeyedEncodingContainerProtocol { public mutating func encodeNil(forKey key: Key) throws { container.withShared { container in - container.elements[_converted(key).stringValue] = NullBox() + container.elements[_converted(key).stringValue] = KeyedBox() } } diff --git a/Tests/XMLCoderTests/Auxiliary/XMLElementTests.swift b/Tests/XMLCoderTests/Auxiliary/XMLElementTests.swift index 55b9e9db..ebd2f388 100644 --- a/Tests/XMLCoderTests/Auxiliary/XMLElementTests.swift +++ b/Tests/XMLCoderTests/Auxiliary/XMLElementTests.swift @@ -30,7 +30,7 @@ class XMLElementTests: XCTestCase { func testInitKeyed() { let keyed = XMLCoderElement(key: "foo", box: KeyedBox( elements: [] as [(String, Box)], - attributes: [("baz", NullBox()), ("blee", IntBox(42))] as [(String, SimpleBox)] + attributes: [("baz", KeyedBox()), ("blee", IntBox(42))] as [(String, Box)] )) XCTAssertEqual(keyed.key, "foo") diff --git a/Tests/XMLCoderTests/Box/KeyedBoxTests.swift b/Tests/XMLCoderTests/Box/KeyedBoxTests.swift index f97470b0..2552fb4a 100644 --- a/Tests/XMLCoderTests/Box/KeyedBoxTests.swift +++ b/Tests/XMLCoderTests/Box/KeyedBoxTests.swift @@ -57,8 +57,10 @@ class KeyedBoxTests: XCTestCase { elements: elements, attributes: [("baz", StringBox("blee"))] ) - box.elements["bar"] = NullBox() + box.elements["bar"] = KeyedBox() XCTAssertEqual(box.elements.count, 3) - XCTAssertEqual(box.elements["bar"] as? NullBox, NullBox()) + let barBox = box.elements["bar"] as? KeyedBox + XCTAssertEqual(barBox?.elements.isEmpty, true) + XCTAssertEqual(barBox?.attributes.isEmpty, true) } } diff --git a/Tests/XMLCoderTests/Box/NullBoxTests.swift b/Tests/XMLCoderTests/Box/NullBoxTests.swift deleted file mode 100644 index a504fcdb..00000000 --- a/Tests/XMLCoderTests/Box/NullBoxTests.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// NullBoxTests.swift -// XMLCoderTests -// -// Created by Vincent Esche on 12/18/18. -// - -import XCTest -@testable import XMLCoder - -class NullBoxTests: XCTestCase { - typealias Boxed = NullBox - - let box = Boxed() - - func testIsNull() { - XCTAssertEqual(box.isNull, true) - } - - func testXMLString() { - XCTAssertEqual(box.xmlString(), nil) - } - - func testEqual() { - XCTAssertEqual(box, Boxed()) - } - - func testDescription() { - XCTAssertEqual(box.description, "null") - } -} diff --git a/Tests/XMLCoderTests/Box/SharedBoxTests.swift b/Tests/XMLCoderTests/Box/SharedBoxTests.swift index 748e0a2c..49580764 100644 --- a/Tests/XMLCoderTests/Box/SharedBoxTests.swift +++ b/Tests/XMLCoderTests/Box/SharedBoxTests.swift @@ -22,10 +22,6 @@ class SharedBoxTests: XCTestCase { } func testXMLString() { - let nullBox = NullBox() - let sharedNullBox = SharedBox(nullBox) - XCTAssertEqual(sharedNullBox.xmlString(), nullBox.xmlString()) - let boolBox = BoolBox(false) let sharedBoolBox = SharedBox(boolBox) XCTAssertEqual(sharedBoolBox.xmlString(), boolBox.xmlString()) @@ -47,14 +43,14 @@ class SharedBoxTests: XCTestCase { XCTAssertEqual(sharedBoxAlias.withShared { $0.count }, 0) sharedBox.withShared { unkeyedBox in - unkeyedBox.append(NullBox()) + unkeyedBox.append(KeyedBox()) } XCTAssertEqual(sharedBox.withShared { $0.count }, 1) XCTAssertEqual(sharedBoxAlias.withShared { $0.count }, 1) sharedBoxAlias.withShared { unkeyedBox in - unkeyedBox.append(NullBox()) + unkeyedBox.append(KeyedBox()) } XCTAssertEqual(sharedBox.withShared { $0.count }, 2) diff --git a/Tests/XMLCoderTests/Box/UnkeyedBoxTests.swift b/Tests/XMLCoderTests/Box/UnkeyedBoxTests.swift index a47196be..7fa8a38c 100644 --- a/Tests/XMLCoderTests/Box/UnkeyedBoxTests.swift +++ b/Tests/XMLCoderTests/Box/UnkeyedBoxTests.swift @@ -42,19 +42,23 @@ class UnkeyedBoxTests: XCTestCase { func testSubscript() { var box = Boxed([StringBox("foo"), IntBox(42)]) - box[0] = NullBox() + box[0] = KeyedBox() XCTAssertEqual(box.count, 2) - XCTAssertEqual(box[0] as? NullBox, NullBox()) + let box0 = box[0] as? KeyedBox + XCTAssertEqual(box0?.elements.isEmpty, true) + XCTAssertEqual(box0?.attributes.isEmpty, true) XCTAssertEqual(box[1] as? IntBox, IntBox(42)) } func testInsertAt() { var box = Boxed([StringBox("foo"), IntBox(42)]) - box.insert(NullBox(), at: 1) + box.insert(KeyedBox(), at: 1) XCTAssertEqual(box.count, 3) + let box1 = box[1] as? KeyedBox XCTAssertEqual(box[0] as? StringBox, StringBox("foo")) - XCTAssertEqual(box[1] as? NullBox, NullBox()) + XCTAssertEqual(box1?.elements.isEmpty, true) + XCTAssertEqual(box1?.attributes.isEmpty, true) XCTAssertEqual(box[2] as? IntBox, IntBox(42)) } } diff --git a/Tests/XMLCoderTests/Minimal/KeyedTests.swift b/Tests/XMLCoderTests/Minimal/KeyedTests.swift index 9fd9e1e0..8022b18a 100644 --- a/Tests/XMLCoderTests/Minimal/KeyedTests.swift +++ b/Tests/XMLCoderTests/Minimal/KeyedTests.swift @@ -13,6 +13,15 @@ class KeyedTests: XCTestCase { let value: [String: Int] } + struct OptionalProperties: Codable, Equatable { + struct Item: Codable, Equatable { + let optionalInt: Int? + let optionalString: String? + } + + let item: [Item] + } + struct ContainerCamelCase: Codable, Equatable { let valUe: [String: Int] let testAttribute: String @@ -33,6 +42,30 @@ class KeyedTests: XCTestCase { } } + func testEmptyOptionalProperties() throws { + do { + let decoder = XMLDecoder() + + let xmlString = "" + let xmlData = xmlString.data(using: .utf8)! + + let decoded = try decoder.decode( + OptionalProperties.self, + from: xmlData + ) + + XCTAssertEqual(decoded.item.count, 2) + XCTAssertNotNil(decoded.item.first) + XCTAssertNil(decoded.item.first?.optionalString) + XCTAssertNil(decoded.item.first?.optionalInt) + XCTAssertNotNil(decoded.item.last) + XCTAssertNil(decoded.item.last?.optionalString) + XCTAssertNil(decoded.item.last?.optionalInt) + } catch { + print(error) + } + } + func testEmpty() throws { let decoder = XMLDecoder() diff --git a/XMLCoder.xcodeproj/project.pbxproj b/XMLCoder.xcodeproj/project.pbxproj index a2a4412b..b620269c 100644 --- a/XMLCoder.xcodeproj/project.pbxproj +++ b/XMLCoder.xcodeproj/project.pbxproj @@ -44,7 +44,6 @@ BF63EF6B21D10284001D38C5 /* XMLElementTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF63EF6A21D10284001D38C5 /* XMLElementTests.swift */; }; BF8171D021D3B1BD00901EB0 /* DecodingContainerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8171CF21D3B1BD00901EB0 /* DecodingContainerTests.swift */; }; BF8171F221D3D03E00901EB0 /* SharedBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8171F121D3D03E00901EB0 /* SharedBoxTests.swift */; }; - BF9457A821CBB498005ACFDE /* NullBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF94579E21CBB497005ACFDE /* NullBox.swift */; }; BF9457A921CBB498005ACFDE /* KeyedBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF94579F21CBB497005ACFDE /* KeyedBox.swift */; }; BF9457AA21CBB498005ACFDE /* UnkeyedBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457A021CBB497005ACFDE /* UnkeyedBox.swift */; }; BF9457AB21CBB498005ACFDE /* DecimalBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457A121CBB497005ACFDE /* DecimalBox.swift */; }; @@ -60,7 +59,6 @@ BF9457C821CBB516005ACFDE /* BoolBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457BE21CBB516005ACFDE /* BoolBoxTests.swift */; }; BF9457C921CBB516005ACFDE /* KeyedBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457BF21CBB516005ACFDE /* KeyedBoxTests.swift */; }; BF9457CB21CBB516005ACFDE /* DecimalBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457C121CBB516005ACFDE /* DecimalBoxTests.swift */; }; - BF9457CC21CBB516005ACFDE /* NullBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457C221CBB516005ACFDE /* NullBoxTests.swift */; }; BF9457CD21CBB516005ACFDE /* FloatBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457C321CBB516005ACFDE /* FloatBoxTests.swift */; }; BF9457CE21CBB516005ACFDE /* StringBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457C421CBB516005ACFDE /* StringBoxTests.swift */; }; BF9457CF21CBB516005ACFDE /* IntBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9457C521CBB516005ACFDE /* IntBoxTests.swift */; }; @@ -163,7 +161,6 @@ BF63EF6A21D10284001D38C5 /* XMLElementTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XMLElementTests.swift; sourceTree = ""; }; BF8171CF21D3B1BD00901EB0 /* DecodingContainerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodingContainerTests.swift; sourceTree = ""; }; BF8171F121D3D03E00901EB0 /* SharedBoxTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedBoxTests.swift; sourceTree = ""; }; - BF94579E21CBB497005ACFDE /* NullBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NullBox.swift; sourceTree = ""; }; BF94579F21CBB497005ACFDE /* KeyedBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyedBox.swift; sourceTree = ""; }; BF9457A021CBB497005ACFDE /* UnkeyedBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnkeyedBox.swift; sourceTree = ""; }; BF9457A121CBB497005ACFDE /* DecimalBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecimalBox.swift; sourceTree = ""; }; @@ -179,7 +176,6 @@ BF9457BE21CBB516005ACFDE /* BoolBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoolBoxTests.swift; sourceTree = ""; }; BF9457BF21CBB516005ACFDE /* KeyedBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyedBoxTests.swift; sourceTree = ""; }; BF9457C121CBB516005ACFDE /* DecimalBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DecimalBoxTests.swift; sourceTree = ""; }; - BF9457C221CBB516005ACFDE /* NullBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NullBoxTests.swift; sourceTree = ""; }; BF9457C321CBB516005ACFDE /* FloatBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatBoxTests.swift; sourceTree = ""; }; BF9457C421CBB516005ACFDE /* StringBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringBoxTests.swift; sourceTree = ""; }; BF9457C521CBB516005ACFDE /* IntBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntBoxTests.swift; sourceTree = ""; }; @@ -281,7 +277,6 @@ isa = PBXGroup; children = ( BF9457A421CBB497005ACFDE /* Box.swift */, - BF94579E21CBB497005ACFDE /* NullBox.swift */, BF9457A321CBB497005ACFDE /* BoolBox.swift */, BF9457D421CBB59D005ACFDE /* IntBox.swift */, BF9457D221CBB59D005ACFDE /* UIntBox.swift */, @@ -317,7 +312,6 @@ BF9457BD21CBB516005ACFDE /* Box */ = { isa = PBXGroup; children = ( - BF9457C221CBB516005ACFDE /* NullBoxTests.swift */, BF9457BE21CBB516005ACFDE /* BoolBoxTests.swift */, BF9457C521CBB516005ACFDE /* IntBoxTests.swift */, BF9457C621CBB516005ACFDE /* UIntBoxTests.swift */, @@ -579,7 +573,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + shellScript = "#if which swiftlint >/dev/null; then\n# swiftlint\n#else\n# echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\n#fi\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -626,7 +620,6 @@ BF9457AA21CBB498005ACFDE /* UnkeyedBox.swift in Sources */, BF9457AF21CBB498005ACFDE /* StringBox.swift in Sources */, OBJ_58 /* XMLUnkeyedEncodingContainer.swift in Sources */, - BF9457A821CBB498005ACFDE /* NullBox.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -666,7 +659,6 @@ OBJ_81 /* BreakfastTest.swift in Sources */, OBJ_82 /* CDCatalog.swift in Sources */, BF63EF0021CCDED2001D38C5 /* XMLStackParserTests.swift in Sources */, - BF9457CC21CBB516005ACFDE /* NullBoxTests.swift in Sources */, BF63EF1E21CEC99B001D38C5 /* BenchmarkTests.swift in Sources */, BF9457CF21CBB516005ACFDE /* IntBoxTests.swift in Sources */, BF9457E021CBB68A005ACFDE /* DataBoxTests.swift in Sources */, diff --git a/XMLCoder.xcodeproj/xcshareddata/xcbaselines/XMLCoder::XMLCoderTests.xcbaseline/76E090BF-7AFE-4988-A06A-3C423396A4A4.plist b/XMLCoder.xcodeproj/xcshareddata/xcbaselines/XMLCoder::XMLCoderTests.xcbaseline/76E090BF-7AFE-4988-A06A-3C423396A4A4.plist index bc1ddc1c..b7550628 100644 --- a/XMLCoder.xcodeproj/xcshareddata/xcbaselines/XMLCoder::XMLCoderTests.xcbaseline/76E090BF-7AFE-4988-A06A-3C423396A4A4.plist +++ b/XMLCoder.xcodeproj/xcshareddata/xcbaselines/XMLCoder::XMLCoderTests.xcbaseline/76E090BF-7AFE-4988-A06A-3C423396A4A4.plist @@ -91,7 +91,7 @@ com.apple.XCTPerformanceMetric_WallClockTime baselineAverage - 0.0093493 + 0.0316 baselineIntegrationDisplayName Local Baseline From befe13531ba35112bb1ffbbf0a2627140aee55cb Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 12 May 2019 18:10:59 +0100 Subject: [PATCH 2/5] Fix remaining tests --- Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift | 2 +- .../XMLCoder/Decoder/XMLDecoderImplementation.swift | 11 ----------- Tests/XMLCoderTests/Box/KeyedBoxTests.swift | 2 +- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift b/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift index 3f6b5bf9..791d4651 100644 --- a/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift +++ b/Sources/XMLCoder/Auxiliaries/Box/KeyedBox.swift @@ -36,7 +36,7 @@ extension KeyedBox { extension KeyedBox: Box { var isNull: Bool { - return false + return elements.isEmpty && attributes.isEmpty } func xmlString() -> String? { diff --git a/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift b/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift index d7b4e6b9..a360ec64 100644 --- a/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift +++ b/Sources/XMLCoder/Decoder/XMLDecoderImplementation.swift @@ -76,17 +76,6 @@ class XMLDecoderImplementation: Decoder { let topContainer = try self.topContainer() switch topContainer { - case _ where topContainer.isNull: - throw DecodingError.valueNotFound( - KeyedDecodingContainer.self, - DecodingError.Context( - codingPath: codingPath, - debugDescription: - """ - Cannot get keyed decoding container -- found null box instead. - """ - ) - ) case let string as StringBox: return KeyedDecodingContainer(XMLKeyedDecodingContainer( referencing: self, diff --git a/Tests/XMLCoderTests/Box/KeyedBoxTests.swift b/Tests/XMLCoderTests/Box/KeyedBoxTests.swift index 2552fb4a..354e6192 100644 --- a/Tests/XMLCoderTests/Box/KeyedBoxTests.swift +++ b/Tests/XMLCoderTests/Box/KeyedBoxTests.swift @@ -18,7 +18,7 @@ class KeyedBoxTests: XCTestCase { func testIsNull() { let box = Boxed() - XCTAssertEqual(box.isNull, false) + XCTAssertEqual(box.isNull, true) } func testUnbox() { From c05ee09a576ab54160ccd6e27a7024a88d4c742f Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Sun, 12 May 2019 19:21:59 +0100 Subject: [PATCH 3/5] Add BorderTest with a snippet failing in CoreXLSX --- Tests/XMLCoderTests/BorderTest.swift | 57 ++++++++++++++++++++++++++++ XMLCoder.xcodeproj/project.pbxproj | 4 ++ 2 files changed, 61 insertions(+) create mode 100644 Tests/XMLCoderTests/BorderTest.swift diff --git a/Tests/XMLCoderTests/BorderTest.swift b/Tests/XMLCoderTests/BorderTest.swift new file mode 100644 index 00000000..699fa5a4 --- /dev/null +++ b/Tests/XMLCoderTests/BorderTest.swift @@ -0,0 +1,57 @@ +// +// BorderTest.swift +// XMLCoderTests +// +// Created by Max Desiatov on 12/05/2019. +// + +import XCTest +@testable import XMLCoder + +private let xml = """ + + + +""".data(using: .utf8)! + +struct Borders: Codable, Equatable { + let items: [Border] + let count: Int + + enum CodingKeys: String, CodingKey { + case items = "border" + case count + } +} + +public struct Border: Codable, Equatable { + struct Value: Codable, Equatable { + let style: String? + } + + let left: Value? + let right: Value? + let top: Value? + let bottom: Value? + let diagonal: Value? + let horizontal: Value? + let vertical: Value? + + init() { + left = nil + right = nil + top = nil + bottom = nil + diagonal = nil + horizontal = nil + vertical = nil + } +} + +final class BorderTest: XCTestCase { + func testSingleEmpty() throws { + let result = try XMLDecoder().decode(Borders.self, from: xml) + XCTAssertEqual(result.count, 1) + XCTAssertEqual(result.items[0], Border()) + } +} diff --git a/XMLCoder.xcodeproj/project.pbxproj b/XMLCoder.xcodeproj/project.pbxproj index b620269c..814900ee 100644 --- a/XMLCoder.xcodeproj/project.pbxproj +++ b/XMLCoder.xcodeproj/project.pbxproj @@ -87,6 +87,7 @@ D158F12F2229892C0032B449 /* DynamicNodeDecoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D158F12E2229892C0032B449 /* DynamicNodeDecoding.swift */; }; D162674321F9B2AF0056D1D8 /* OptionalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D162674121F9B2850056D1D8 /* OptionalTests.swift */; }; D1761D1F2247F04500F53CEF /* DynamicNodeDecodingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1761D1E2247F04500F53CEF /* DynamicNodeDecodingTest.swift */; }; + D186C4BF2288926E0031F5C7 /* BorderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D186C4BE2288926E0031F5C7 /* BorderTest.swift */; }; D1A3D4AD227AD9BF00F28969 /* KeyDecodingStrategyTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1A3D4AB227AD9BC00F28969 /* KeyDecodingStrategyTest.swift */; }; D1AC9466224E3E63004AB49B /* AttributedEnumIntrinsicTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1AC9464224E3E1F004AB49B /* AttributedEnumIntrinsicTest.swift */; }; D1CB1EF521EA9599009CAF02 /* RJITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_37 /* RJITest.swift */; }; @@ -207,6 +208,7 @@ D158F12E2229892C0032B449 /* DynamicNodeDecoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicNodeDecoding.swift; sourceTree = ""; }; D162674121F9B2850056D1D8 /* OptionalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalTests.swift; sourceTree = ""; }; D1761D1E2247F04500F53CEF /* DynamicNodeDecodingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicNodeDecodingTest.swift; sourceTree = ""; }; + D186C4BE2288926E0031F5C7 /* BorderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BorderTest.swift; sourceTree = ""; }; D1A3D4AB227AD9BC00F28969 /* KeyDecodingStrategyTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyDecodingStrategyTest.swift; sourceTree = ""; }; D1AC9464224E3E1F004AB49B /* AttributedEnumIntrinsicTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedEnumIntrinsicTest.swift; sourceTree = ""; }; D1CFC8222226AFB400B03222 /* NamespaceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NamespaceTest.swift; sourceTree = ""; }; @@ -405,6 +407,7 @@ D14D8A8521F1D6B300B0D31A /* SingleChildTests.swift */, D11815BF227788BA008836E4 /* SpacePreserveTest.swift */, D1A3D4AB227AD9BC00F28969 /* KeyDecodingStrategyTest.swift */, + D186C4BE2288926E0031F5C7 /* BorderTest.swift */, ); name = XMLCoderTests; path = Tests/XMLCoderTests; @@ -660,6 +663,7 @@ OBJ_82 /* CDCatalog.swift in Sources */, BF63EF0021CCDED2001D38C5 /* XMLStackParserTests.swift in Sources */, BF63EF1E21CEC99B001D38C5 /* BenchmarkTests.swift in Sources */, + D186C4BF2288926E0031F5C7 /* BorderTest.swift in Sources */, BF9457CF21CBB516005ACFDE /* IntBoxTests.swift in Sources */, BF9457E021CBB68A005ACFDE /* DataBoxTests.swift in Sources */, D162674321F9B2AF0056D1D8 /* OptionalTests.swift in Sources */, From aaf74f8b776917583248256d43255a081148dd58 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Wed, 22 May 2019 11:42:46 +0100 Subject: [PATCH 4/5] Simplify test code in BoxTreeTests --- Tests/XMLCoderTests/Minimal/BoxTreeTests.swift | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Tests/XMLCoderTests/Minimal/BoxTreeTests.swift b/Tests/XMLCoderTests/Minimal/BoxTreeTests.swift index 7daa6e21..e93313ed 100644 --- a/Tests/XMLCoderTests/Minimal/BoxTreeTests.swift +++ b/Tests/XMLCoderTests/Minimal/BoxTreeTests.swift @@ -31,16 +31,6 @@ class BoxTreeTests: XCTestCase { let boxTree = root.transformToBoxTree() - guard let foo = boxTree.elements["foo"] as? UnkeyedBox else { - XCTAssert( - false, - """ - flattened.elements["foo"] is not an UnkeyedBox - """ - ) - return - } - - XCTAssertEqual(foo.count, 2) + XCTAssertEqual(boxTree.elements["foo"].count, 2) } } From 45da9e461bebcf336a9e4a162044970ce1cb98c0 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Fri, 24 May 2019 10:09:48 +0100 Subject: [PATCH 5/5] Make AnyOptional public --- Sources/XMLCoder/Auxiliaries/Metatypes.swift | 4 ++-- Tests/XMLCoderTests/BorderTest.swift | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/XMLCoder/Auxiliaries/Metatypes.swift b/Sources/XMLCoder/Auxiliaries/Metatypes.swift index 0774db8c..69cc98bd 100644 --- a/Sources/XMLCoder/Auxiliaries/Metatypes.swift +++ b/Sources/XMLCoder/Auxiliaries/Metatypes.swift @@ -17,12 +17,12 @@ extension Dictionary: AnySequence {} /// Type-erased protocol helper for a metatype check in generic `decode` /// overload. -protocol AnyOptional { +public protocol AnyOptional { init() } extension Optional: AnyOptional { - init() { + public init() { self = nil } } diff --git a/Tests/XMLCoderTests/BorderTest.swift b/Tests/XMLCoderTests/BorderTest.swift index 699fa5a4..e3f43d71 100644 --- a/Tests/XMLCoderTests/BorderTest.swift +++ b/Tests/XMLCoderTests/BorderTest.swift @@ -24,7 +24,7 @@ struct Borders: Codable, Equatable { } } -public struct Border: Codable, Equatable { +struct Border: Codable, Equatable, AnyOptional { struct Value: Codable, Equatable { let style: String? }