diff --git a/Sources/XMLCoder/Decoder/XMLDecoder.swift b/Sources/XMLCoder/Decoder/XMLDecoder.swift index dd0f9558..8260b938 100644 --- a/Sources/XMLCoder/Decoder/XMLDecoder.swift +++ b/Sources/XMLCoder/Decoder/XMLDecoder.swift @@ -286,7 +286,7 @@ internal class _XMLDecoder: Decoder { debugDescription: "Cannot get keyed decoding container -- found null value instead.")) } - guard let topContainer = self.storage.topContainer as? [String: Any] else { + guard let topContainer = storage.topContainer as? [String: Any] else { throw DecodingError._typeMismatch(at: codingPath, expectation: [String: Any].self, reality: storage.topContainer) } @@ -303,12 +303,10 @@ internal class _XMLDecoder: Decoder { let topContainer: [Any] - if let container = self.storage.topContainer as? [Any] { + if let container = storage.topContainer as? [Any] { topContainer = container - } else if let container = self.storage.topContainer as? [AnyHashable: Any] { - topContainer = [container] } else { - throw DecodingError._typeMismatch(at: codingPath, expectation: [Any].self, reality: storage.topContainer) + topContainer = [storage.topContainer] } return _XMLUnkeyedDecodingContainer(referencing: self, wrapping: topContainer) @@ -727,7 +725,7 @@ extension _XMLDecoder { switch options.dateDecodingStrategy { case .deferredToDate: storage.push(container: value) - defer { self.storage.popContainer() } + defer { storage.popContainer() } return try Date(from: self) case .secondsSince1970: @@ -740,9 +738,9 @@ extension _XMLDecoder { case .iso8601: if #available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *) { - let string = try self.unbox(value, as: String.self)! + let string = try unbox(value, as: String.self)! guard let date = _iso8601Formatter.date(from: string) else { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected date string to be ISO8601-formatted.")) + throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: codingPath, debugDescription: "Expected date string to be ISO8601-formatted.")) } return date @@ -760,7 +758,7 @@ extension _XMLDecoder { case let .custom(closure): storage.push(container: value) - defer { self.storage.popContainer() } + defer { storage.popContainer() } return try closure(self) } } @@ -771,7 +769,7 @@ extension _XMLDecoder { switch options.dataDecodingStrategy { case .deferredToData: storage.push(container: value) - defer { self.storage.popContainer() } + defer { storage.popContainer() } return try Data(from: self) case .base64: @@ -787,7 +785,7 @@ extension _XMLDecoder { case let .custom(closure): storage.push(container: value) - defer { self.storage.popContainer() } + defer { storage.popContainer() } return try closure(self) } } @@ -803,13 +801,13 @@ extension _XMLDecoder { internal func unbox(_ value: Any, as type: T.Type) throws -> T? { let decoded: T if type == Date.self || type == NSDate.self { - guard let date = try self.unbox(value, as: Date.self) else { return nil } + guard let date = try unbox(value, as: Date.self) else { return nil } decoded = date as! T } else if type == Data.self || type == NSData.self { - guard let data = try self.unbox(value, as: Data.self) else { return nil } + guard let data = try unbox(value, as: Data.self) else { return nil } decoded = data as! T } else if type == URL.self || type == NSURL.self { - guard let urlString = try self.unbox(value, as: String.self) else { + guard let urlString = try unbox(value, as: String.self) else { return nil } @@ -820,11 +818,11 @@ extension _XMLDecoder { decoded = (url as! T) } else if type == Decimal.self || type == NSDecimalNumber.self { - guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil } + guard let decimal = try unbox(value, as: Decimal.self) else { return nil } decoded = decimal as! T } else { storage.push(container: value) - defer { self.storage.popContainer() } + defer { storage.popContainer() } return try type.init(from: self) } diff --git a/Sources/XMLCoder/Decoder/XMLDecodingStorage.swift b/Sources/XMLCoder/Decoder/XMLDecodingStorage.swift index f274acaa..773decb1 100644 --- a/Sources/XMLCoder/Decoder/XMLDecodingStorage.swift +++ b/Sources/XMLCoder/Decoder/XMLDecodingStorage.swift @@ -15,29 +15,29 @@ internal struct _XMLDecodingStorage { /// The container stack. /// Elements may be any one of the XML types (String, [String : Any]). - internal private(set) var containers: [Any] = [] + private var containers: [Any] = [] // MARK: - Initialization /// Initializes `self` with no containers. - internal init() {} + init() {} // MARK: - Modifying the Stack - internal var count: Int { + var count: Int { return containers.count } - internal var topContainer: Any { + var topContainer: Any { precondition(!containers.isEmpty, "Empty container stack.") return containers.last! } - internal mutating func push(container: Any) { + mutating func push(container: Any) { containers.append(container) } - internal mutating func popContainer() { + mutating func popContainer() { precondition(!containers.isEmpty, "Empty container stack.") containers.removeLast() } diff --git a/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift b/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift index 7a6360e0..829e77fd 100644 --- a/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift +++ b/Sources/XMLCoder/Decoder/XMLKeyedDecodingContainer.swift @@ -8,6 +8,15 @@ import Foundation +/// Type-erased protocol helper for a metatype check in generic `decode` +/// overload. +private protocol AnyEmptySequence { + init() +} + +extension Array: AnyEmptySequence {} +extension Dictionary: AnyEmptySequence {} + // MARK: Decoding Containers internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainerProtocol { @@ -78,7 +87,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decodeNil(forKey key: Key) throws -> Bool { - if let entry = self.container[key.stringValue] { + if let entry = container[key.stringValue] { return entry is NSNull } else { return true @@ -86,7 +95,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -101,7 +110,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Int.Type, forKey key: Key) throws -> Int { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -116,7 +125,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -131,7 +140,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -146,7 +155,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -161,7 +170,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -176,7 +185,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -191,7 +200,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -206,7 +215,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -221,14 +230,14 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } decoder.codingPath.append(key) defer { self.decoder.codingPath.removeLast() } - guard let value = try self.decoder.unbox(entry, as: UInt32.self) else { + guard let value = try decoder.unbox(entry, as: UInt32.self) else { throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Expected \(type) value but found null instead.")) } @@ -236,7 +245,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -251,14 +260,14 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Float.Type, forKey key: Key) throws -> Float { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } decoder.codingPath.append(key) defer { self.decoder.codingPath.removeLast() } - guard let value = try self.decoder.unbox(entry, as: Float.self) else { + guard let value = try decoder.unbox(entry, as: Float.self) else { throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Expected \(type) value but found null instead.")) } @@ -266,7 +275,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: Double.Type, forKey key: Key) throws -> Double { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } @@ -281,14 +290,14 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: String.Type, forKey key: Key) throws -> String { - guard let entry = self.container[key.stringValue] else { + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } decoder.codingPath.append(key) defer { self.decoder.codingPath.removeLast() } - guard let value = try self.decoder.unbox(entry, as: String.self) else { + guard let value = try decoder.unbox(entry, as: String.self) else { throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Expected \(type) value but found null instead.")) } @@ -296,14 +305,18 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer } public func decode(_ type: T.Type, forKey key: Key) throws -> T { - guard let entry = self.container[key.stringValue] else { + if type is AnyEmptySequence.Type && container[key.stringValue] == nil { + return (type as! AnyEmptySequence.Type).init() as! T + } + + guard let entry = container[key.stringValue] else { throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "No value associated with key \(_errorDescription(of: key)).")) } decoder.codingPath.append(key) - defer { self.decoder.codingPath.removeLast() } + defer { decoder.codingPath.removeLast() } - guard let value = try self.decoder.unbox(entry, as: type) else { + guard let value = try decoder.unbox(entry, as: type) else { throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Expected \(type) value but found null instead.")) } @@ -312,7 +325,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer public func nestedContainer(keyedBy _: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer { decoder.codingPath.append(key) - defer { self.decoder.codingPath.removeLast() } + defer { decoder.codingPath.removeLast() } guard let value = self.container[key.stringValue] else { throw DecodingError.keyNotFound(key, @@ -330,7 +343,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { decoder.codingPath.append(key) - defer { self.decoder.codingPath.removeLast() } + defer { decoder.codingPath.removeLast() } guard let value = self.container[key.stringValue] else { throw DecodingError.keyNotFound(key, @@ -347,7 +360,7 @@ internal struct _XMLKeyedDecodingContainer: KeyedDecodingContainer private func _superDecoder(forKey key: CodingKey) throws -> Decoder { decoder.codingPath.append(key) - defer { self.decoder.codingPath.removeLast() } + defer { decoder.codingPath.removeLast() } let value: Any = container[key.stringValue] ?? NSNull() return _XMLDecoder(referencing: value, at: decoder.codingPath, options: decoder.options) diff --git a/Sources/XMLCoder/Encoder/XMLEncoder.swift b/Sources/XMLCoder/Encoder/XMLEncoder.swift index 2343539f..ab57f9d6 100644 --- a/Sources/XMLCoder/Encoder/XMLEncoder.swift +++ b/Sources/XMLCoder/Encoder/XMLEncoder.swift @@ -341,7 +341,7 @@ internal class _XMLEncoder: Encoder { // We haven't yet pushed a container at this level; do so here. topContainer = storage.pushKeyedContainer() } else { - guard let container = self.storage.containers.last as? NSMutableDictionary else { + guard let container = storage.lastContainer as? NSMutableDictionary else { preconditionFailure("Attempt to push new keyed encoding container when already previously encoded at this path.") } @@ -359,7 +359,7 @@ internal class _XMLEncoder: Encoder { // We haven't yet pushed a container at this level; do so here. topContainer = storage.pushUnkeyedContainer() } else { - guard let container = self.storage.containers.last as? NSMutableArray else { + guard let container = storage.lastContainer as? NSMutableArray else { preconditionFailure("Attempt to push new unkeyed encoding container when already previously encoded at this path.") } diff --git a/Sources/XMLCoder/Encoder/XMLEncodingStorage.swift b/Sources/XMLCoder/Encoder/XMLEncodingStorage.swift index 0998fd71..221e5c37 100644 --- a/Sources/XMLCoder/Encoder/XMLEncodingStorage.swift +++ b/Sources/XMLCoder/Encoder/XMLEncodingStorage.swift @@ -16,36 +16,40 @@ internal struct _XMLEncodingStorage { /// The container stack. /// Elements may be any one of the XML types (NSNull, NSNumber, NSString, NSArray, NSDictionary). - internal private(set) var containers: [NSObject] = [] + private var containers: [NSObject] = [] // MARK: - Initialization /// Initializes `self` with no containers. - internal init() {} + init() {} // MARK: - Modifying the Stack - internal var count: Int { + var count: Int { return containers.count } - internal mutating func pushKeyedContainer() -> NSMutableDictionary { + var lastContainer: NSObject? { + return containers.last + } + + mutating func pushKeyedContainer() -> NSMutableDictionary { let dictionary = NSMutableDictionary() containers.append(dictionary) return dictionary } - internal mutating func pushUnkeyedContainer() -> NSMutableArray { + mutating func pushUnkeyedContainer() -> NSMutableArray { let array = NSMutableArray() containers.append(array) return array } - internal mutating func push(container: NSObject) { + mutating func push(container: NSObject) { containers.append(container) } - internal mutating func popContainer() -> NSObject { + mutating func popContainer() -> NSObject { precondition(!containers.isEmpty, "Empty container stack.") return containers.popLast()! } diff --git a/Tests/XMLCoderTests/ArrayTest.swift b/Tests/XMLCoderTests/ArrayTest.swift new file mode 100644 index 00000000..847288bf --- /dev/null +++ b/Tests/XMLCoderTests/ArrayTest.swift @@ -0,0 +1,80 @@ +// +// ArrayTest.swift +// XMLCoderTests +// +// Created by Max Desiatov on 19/11/2018. +// + +import Foundation +import XCTest +@testable import XMLCoder + +private struct Container: Codable, Equatable { + let elements: [String] + + enum CodingKeys: String, CodingKey { + case elements = "element" + } +} + +class ArrayTest: XCTestCase { + func testEmpty() { + let decoder = XMLDecoder() + + do { + let xml = """ + + + +""".data(using: .utf8)! + + let container = try decoder.decode(Container.self, from: xml) + XCTAssertEqual(container.elements, []) + } catch { + XCTAssert(false, "failed to decode test xml: \(error)") + } + } + + func testSingleElement() { + let decoder = XMLDecoder() + + do { + let xml = """ + + + foo + +""".data(using: .utf8)! + + let container = try decoder.decode(Container.self, from: xml) + XCTAssertEqual(container.elements, ["foo"]) + } catch { + XCTAssert(false, "failed to decode test xml: \(error)") + } + } + + func testMultiElement() { + let decoder = XMLDecoder() + + do { + let xml = """ + + + foo + bar + +""".data(using: .utf8)! + + let container = try decoder.decode(Container.self, from: xml) + XCTAssertEqual(container.elements, ["foo", "bar"]) + } catch { + XCTAssert(false, "failed to decode test xml: \(error)") + } + } + + static var allTests = [ + ("testEmpty", testEmpty), + ("testSingleElement", testSingleElement), + ("testMultiElement", testMultiElement), + ] +} diff --git a/Tests/XMLCoderTests/DictionaryTest.swift b/Tests/XMLCoderTests/DictionaryTest.swift new file mode 100644 index 00000000..c73ba29a --- /dev/null +++ b/Tests/XMLCoderTests/DictionaryTest.swift @@ -0,0 +1,84 @@ +// +// DictionaryTest.swift +// XMLCoderTests +// +// Created by Max Desiatov on 19/11/2018. +// + +import Foundation +import XCTest +@testable import XMLCoder + +class DictionaryTest: XCTestCase { + struct Container: Codable, Equatable { + let elements: [String: Int] + + enum CodingKeys: String, CodingKey { + case elements = "element" + } + } + + func testEmpty() { + let decoder = XMLDecoder() + + do { + let xml = """ + + + +""".data(using: .utf8)! + + let container = try decoder.decode(Container.self, from: xml) + XCTAssertEqual(container.elements, [:]) + } catch { + XCTAssert(false, "failed to decode test xml: \(error)") + } + } + + func testSingleElement() { + let decoder = XMLDecoder() + + do { + let xml = """ + + + + 12 + + +""".data(using: .utf8)! + + let container = try decoder.decode(Container.self, from: xml) + XCTAssertEqual(container.elements, ["foo": 12]) + } catch { + XCTAssert(false, "failed to decode test xml: \(error)") + } + } + + func testMultiElement() { + let decoder = XMLDecoder() + + do { + let xml = """ + + + + 12 + 34 + + +""".data(using: .utf8)! + + let container = try decoder.decode(Container.self, from: xml) + XCTAssertEqual(container.elements, ["foo": 12, "bar": 34]) + } catch { + XCTAssert(false, "failed to decode test xml: \(error)") + } + } + + static var allTests = [ + ("testEmpty", testEmpty), + ("testSingleElement", testSingleElement), + ("testMultiElement", testMultiElement), + ] +} diff --git a/XMLCoder.xcodeproj/project.pbxproj b/XMLCoder.xcodeproj/project.pbxproj index fb86b3b6..ff73b003 100644 --- a/XMLCoder.xcodeproj/project.pbxproj +++ b/XMLCoder.xcodeproj/project.pbxproj @@ -26,6 +26,8 @@ BFE1C58E21A4203200EA0458 /* NoteTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE1C58D21A4203200EA0458 /* NoteTest.swift */; }; BFE1C58521A41AFB00EA0458 /* XMLUnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE1C58421A41AFA00EA0458 /* XMLUnkeyedEncodingContainer.swift */; }; BFE1C58721A41B3200EA0458 /* XMLKeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE1C58621A41B3200EA0458 /* XMLKeyedEncodingContainer.swift */; }; + BF191DEC21A55FE700EAB791 /* ArrayTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF191DEB21A55FE700EAB791 /* ArrayTest.swift */; }; + BF191DEE21A5601800EAB791 /* DictionaryTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF191DED21A5601800EAB791 /* DictionaryTest.swift */; }; BFE1C59121A4242300EA0458 /* NodeEncodingStrategyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE1C58F21A4232100EA0458 /* NodeEncodingStrategyTests.swift */; }; D15ACF3F21A2C97F003238FD /* BreakfastTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15ACF3E21A2C97F003238FD /* BreakfastTest.swift */; }; D15ACF4221A407AA003238FD /* BooksTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D15ACF3321A2C7F2003238FD /* BooksTest.swift */; }; @@ -73,6 +75,8 @@ BFE1C58D21A4203200EA0458 /* NoteTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoteTest.swift; sourceTree = ""; }; BFE1C58421A41AFA00EA0458 /* XMLUnkeyedEncodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = XMLUnkeyedEncodingContainer.swift; sourceTree = ""; tabWidth = 4; }; BFE1C58621A41B3200EA0458 /* XMLKeyedEncodingContainer.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = XMLKeyedEncodingContainer.swift; sourceTree = ""; tabWidth = 4; }; + BF191DEB21A55FE700EAB791 /* ArrayTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = ArrayTest.swift; sourceTree = ""; tabWidth = 4; }; + BF191DED21A5601800EAB791 /* DictionaryTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = DictionaryTest.swift; sourceTree = ""; tabWidth = 4; }; BFE1C58F21A4232100EA0458 /* NodeEncodingStrategyTests.swift */ = {isa = PBXFileReference; indentWidth = 4; lastKnownFileType = sourcecode.swift; path = NodeEncodingStrategyTests.swift; sourceTree = ""; tabWidth = 4; }; D15ACF3321A2C7F2003238FD /* BooksTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BooksTest.swift; sourceTree = ""; }; D15ACF3E21A2C97F003238FD /* BreakfastTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BreakfastTest.swift; sourceTree = ""; }; @@ -148,6 +152,9 @@ OBJ_24 /* XMLCoderTests */ = { isa = PBXGroup; children = ( + BF191DEB21A55FE700EAB791 /* ArrayTest.swift */, + BF191DED21A5601800EAB791 /* DictionaryTest.swift */, + OBJ_25 /* XMLCoderTests.swift */, BFE1C58F21A4232100EA0458 /* NodeEncodingStrategyTests.swift */, D15ACF3321A2C7F2003238FD /* BooksTest.swift */, OBJ_25 /* RelationshipsTest.swift */, @@ -340,12 +347,15 @@ BFE1C59121A4242300EA0458 /* NodeEncodingStrategyTests.swift in Sources */, D15ACF4221A407AA003238FD /* BooksTest.swift in Sources */, D1EB9C6B21A9802B002F2254 /* CDTest.swift in Sources */, - OBJ_41 /* RelationshipsTest.swift in Sources */, D1EB9C6021A970DC002F2254 /* PlantTest.swift in Sources */, D15ACF3F21A2C97F003238FD /* BreakfastTest.swift in Sources */, BF191DE621A467F600EAB791 /* RJITest.swift in Sources */, BFE1C58E21A4203200EA0458 /* NoteTest.swift in Sources */, D1EB9C6321A9717C002F2254 /* PlantCatalog.swift in Sources */, + OBJ_41 /* XMLCoderTests.swift in Sources */, + BF191DEE21A5601800EAB791 /* DictionaryTest.swift in Sources */, + BFE1C59121A4242300EA0458 /* NodeEncodingStrategyTests.swift in Sources */, + BF191DEC21A55FE700EAB791 /* ArrayTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };