Make coding paths non-optional

For the benefit of unkeyed containers, coding paths currently contain optional `CodingKey`s — unkeyed containers are allowed to report a `nil` key in a path. However, this is unhelpful for debugging purposes, or inspecting the coding path for context, since any unkeyed container simply reports `nil`, whether it’s at index 1 or 1000.

Now all containers are required to report a non-optional CodingKey for their segment of the coding path, and coding paths are now exposed as `[CodingKey]`.
This commit is contained in:
Itai Ferber
2017-06-30 12:43:40 -07:00
parent c063d4939f
commit e1007a2e3b
6 changed files with 310 additions and 225 deletions

View File

@@ -165,7 +165,7 @@ fileprivate class _JSONEncoder : Encoder {
fileprivate let options: JSONEncoder._Options
/// The path to the current point in encoding.
public var codingPath: [CodingKey?]
public var codingPath: [CodingKey]
/// Contextual user-provided information for use during encoding.
public var userInfo: [CodingUserInfoKey : Any] {
@@ -175,7 +175,7 @@ fileprivate class _JSONEncoder : Encoder {
// MARK: - Initialization
/// Initializes `self` with the given top-level encoder options.
fileprivate init(options: JSONEncoder._Options, codingPath: [CodingKey?] = []) {
fileprivate init(options: JSONEncoder._Options, codingPath: [CodingKey] = []) {
self.options = options
self.storage = _JSONEncodingStorage()
self.codingPath = codingPath
@@ -187,7 +187,7 @@ fileprivate class _JSONEncoder : Encoder {
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
fileprivate func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
fileprivate func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
self.codingPath.append(key)
let ret: T = try work()
self.codingPath.removeLast()
@@ -304,12 +304,12 @@ fileprivate struct _JSONKeyedEncodingContainer<K : CodingKey> : KeyedEncodingCon
private let container: NSMutableDictionary
/// The path of coding keys taken to get to this point in encoding.
private(set) public var codingPath: [CodingKey?]
private(set) public var codingPath: [CodingKey]
// MARK: - Initialization
/// Initializes `self` with the given references.
fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableDictionary) {
fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey], wrapping container: NSMutableDictionary) {
self.encoder = encoder
self.codingPath = codingPath
self.container = container
@@ -321,7 +321,7 @@ fileprivate struct _JSONKeyedEncodingContainer<K : CodingKey> : KeyedEncodingCon
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
fileprivate mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
fileprivate mutating func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
self.codingPath.append(key)
let ret: T = try work()
self.codingPath.removeLast()
@@ -384,7 +384,7 @@ fileprivate struct _JSONKeyedEncodingContainer<K : CodingKey> : KeyedEncodingCon
}
public mutating func superEncoder() -> Encoder {
return _JSONReferencingEncoder(referencing: self.encoder, at: _JSONSuperKey.super, wrapping: self.container)
return _JSONReferencingEncoder(referencing: self.encoder, at: _JSONKey.super, wrapping: self.container)
}
public mutating func superEncoder(forKey key: Key) -> Encoder {
@@ -402,12 +402,17 @@ fileprivate struct _JSONUnkeyedEncodingContainer : UnkeyedEncodingContainer {
private let container: NSMutableArray
/// The path of coding keys taken to get to this point in encoding.
private(set) public var codingPath: [CodingKey?]
private(set) public var codingPath: [CodingKey]
/// The number of elements encoded into the container.
public var count: Int {
return self.container.count
}
// MARK: - Initialization
/// Initializes `self` with the given references.
fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey?], wrapping container: NSMutableArray) {
fileprivate init(referencing encoder: _JSONEncoder, codingPath: [CodingKey], wrapping container: NSMutableArray) {
self.encoder = encoder
self.codingPath = codingPath
self.container = container
@@ -419,7 +424,7 @@ fileprivate struct _JSONUnkeyedEncodingContainer : UnkeyedEncodingContainer {
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
fileprivate mutating func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
fileprivate mutating func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
self.codingPath.append(key)
let ret: T = try work()
self.codingPath.removeLast()
@@ -444,39 +449,39 @@ fileprivate struct _JSONUnkeyedEncodingContainer : UnkeyedEncodingContainer {
public mutating func encode(_ value: Float) throws {
// Since the float may be invalid and throw, the coding path needs to contain this key.
try self.encoder.with(pushedKey: nil) {
try self.encoder.with(pushedKey: _JSONKey(index: self.count)) {
self.container.add(try self.encoder.box(value))
}
}
public mutating func encode(_ value: Double) throws {
// Since the double may be invalid and throw, the coding path needs to contain this key.
try self.encoder.with(pushedKey: nil) {
try self.encoder.with(pushedKey: _JSONKey(index: self.count)) {
self.container.add(try self.encoder.box(value))
}
}
public mutating func encode<T : Encodable>(_ value: T) throws {
try self.encoder.with(pushedKey: nil) {
try self.encoder.with(pushedKey: _JSONKey(index: self.count)) {
self.container.add(try self.encoder.box(value))
}
}
public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
let dictionary = NSMutableDictionary()
self.container.add(dictionary)
return self.with(pushedKey: _JSONKey(index: self.count)) {
let dictionary = NSMutableDictionary()
self.container.add(dictionary)
return self.with(pushedKey: nil) {
let container = _JSONKeyedEncodingContainer<NestedKey>(referencing: self.encoder, codingPath: self.codingPath, wrapping: dictionary)
return KeyedEncodingContainer(container)
}
}
public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
let array = NSMutableArray()
self.container.add(array)
return self.with(pushedKey: _JSONKey(index: self.count)) {
let array = NSMutableArray()
self.container.add(array)
return self.with(pushedKey: nil) {
return _JSONUnkeyedEncodingContainer(referencing: self.encoder, codingPath: self.codingPath, wrapping: array)
}
}
@@ -753,7 +758,7 @@ fileprivate class _JSONReferencingEncoder : _JSONEncoder {
self.reference = .array(array, index)
super.init(options: encoder.options, codingPath: encoder.codingPath)
self.codingPath.append(nil)
self.codingPath.append(_JSONKey(index: index))
}
/// Initializes `self` by referencing the given dictionary container in the given encoder.
@@ -913,7 +918,7 @@ fileprivate class _JSONDecoder : Decoder {
fileprivate let options: JSONDecoder._Options
/// The path to the current point in encoding.
private(set) public var codingPath: [CodingKey?]
private(set) public var codingPath: [CodingKey]
/// Contextual user-provided information for use during encoding.
public var userInfo: [CodingUserInfoKey : Any] {
@@ -923,7 +928,7 @@ fileprivate class _JSONDecoder : Decoder {
// MARK: - Initialization
/// Initializes `self` with the given top-level container and options.
fileprivate init(referencing container: Any, at codingPath: [CodingKey?] = [], options: JSONDecoder._Options) {
fileprivate init(referencing container: Any, at codingPath: [CodingKey] = [], options: JSONDecoder._Options) {
self.storage = _JSONDecodingStorage()
self.storage.push(container: container)
self.codingPath = codingPath
@@ -936,7 +941,7 @@ fileprivate class _JSONDecoder : Decoder {
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
fileprivate func with<T>(pushedKey key: CodingKey?, _ work: () throws -> T) rethrows -> T {
fileprivate func with<T>(pushedKey key: CodingKey, _ work: () throws -> T) rethrows -> T {
self.codingPath.append(key)
let ret: T = try work()
self.codingPath.removeLast()
@@ -1028,7 +1033,7 @@ fileprivate struct _JSONKeyedDecodingContainer<K : CodingKey> : KeyedDecodingCon
private let container: [String : Any]
/// The path of coding keys taken to get to this point in decoding.
private(set) public var codingPath: [CodingKey?]
private(set) public var codingPath: [CodingKey]
// MARK: - Initialization
@@ -1308,7 +1313,7 @@ fileprivate struct _JSONKeyedDecodingContainer<K : CodingKey> : KeyedDecodingCon
}
public func superDecoder() throws -> Decoder {
return try _superDecoder(forKey: _JSONSuperKey.super)
return try _superDecoder(forKey: _JSONKey.super)
}
public func superDecoder(forKey key: Key) throws -> Decoder {
@@ -1326,10 +1331,10 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
private let container: [Any]
/// The path of coding keys taken to get to this point in decoding.
private(set) public var codingPath: [CodingKey?]
private(set) public var codingPath: [CodingKey]
/// The index of the element we're about to decode.
private var currentIndex: Int
private(set) public var currentIndex: Int
// MARK: - Initialization
@@ -1353,7 +1358,7 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decodeNil() throws -> Bool {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(Any?.self, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
if self.container[self.currentIndex] is NSNull {
@@ -1366,12 +1371,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Bool.Type) throws -> Bool {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1381,12 +1386,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Int.Type) throws -> Int {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1396,12 +1401,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Int8.Type) throws -> Int8 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1411,12 +1416,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Int16.Type) throws -> Int16 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1426,12 +1431,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Int32.Type) throws -> Int32 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1441,12 +1446,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Int64.Type) throws -> Int64 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1456,12 +1461,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: UInt.Type) throws -> UInt {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1471,12 +1476,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: UInt8.Type) throws -> UInt8 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1486,12 +1491,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: UInt16.Type) throws -> UInt16 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1501,12 +1506,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: UInt32.Type) throws -> UInt32 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1516,12 +1521,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: UInt64.Type) throws -> UInt64 {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1531,12 +1536,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Float.Type) throws -> Float {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1546,12 +1551,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: Double.Type) throws -> Double {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1561,12 +1566,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode(_ type: String.Type) throws -> String {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1576,12 +1581,12 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
public mutating func decode<T : Decodable>(_ type: T.Type) throws -> T {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Unkeyed container is at end."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Unkeyed container is at end."))
}
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [nil], debugDescription: "Expected \(type) but found null instead."))
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
self.currentIndex += 1
@@ -1590,7 +1595,7 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
}
public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
DecodingError.Context(codingPath: self.codingPath,
@@ -1615,7 +1620,7 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
}
public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
DecodingError.Context(codingPath: self.codingPath,
@@ -1639,7 +1644,7 @@ fileprivate struct _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer {
}
public mutating func superDecoder() throws -> Decoder {
return try self.decoder.with(pushedKey: nil) {
return try self.decoder.with(pushedKey: _JSONKey(index: self.currentIndex)) {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(Decoder.self,
DecodingError.Context(codingPath: self.codingPath,
@@ -2128,11 +2133,29 @@ extension _JSONDecoder {
}
//===----------------------------------------------------------------------===//
// Shared Super Key
// Shared Key Types
//===----------------------------------------------------------------------===//
fileprivate enum _JSONSuperKey : String, CodingKey {
case `super`
fileprivate struct _JSONKey : CodingKey {
public var stringValue: String
public var intValue: Int?
public init?(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
public init?(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}
fileprivate init(index: Int) {
self.stringValue = "Index \(index)"
self.intValue = index
}
fileprivate static let `super` = _JSONKey(stringValue: "super")!
}
//===----------------------------------------------------------------------===//
@@ -2158,7 +2181,7 @@ fileprivate extension EncodingError {
/// - parameter value: The value that was invalid to encode.
/// - parameter path: The path of `CodingKey`s taken to encode this value.
/// - returns: An `EncodingError` with the appropriate path and debug description.
fileprivate static func _invalidFloatingPointValue<T : FloatingPoint>(_ value: T, at codingPath: [CodingKey?]) -> EncodingError {
fileprivate static func _invalidFloatingPointValue<T : FloatingPoint>(_ value: T, at codingPath: [CodingKey]) -> EncodingError {
let valueDescription: String
if value == T.infinity {
valueDescription = "\(T.self).infinity"