Merge remote-tracking branch 'origin/master' into swift-4.0-branch
diff --git a/Foundation/Codable.swift b/Foundation/Codable.swift
index 06bdc21..7334b24 100644
--- a/Foundation/Codable.swift
+++ b/Foundation/Codable.swift
@@ -8,64 +8,6 @@
//
//===----------------------------------------------------------------------===//
-// Errors
-//===----------------------------------------------------------------------===//
-
-// Adding the following extensions to EncodingError and DecodingError allows them to bridge to NSErrors implicitly.
-
-fileprivate let NSCodingPathErrorKey = "NSCodingPath"
-fileprivate let NSDebugDescriptionErrorKey = "NSDebugDescription"
-
-extension EncodingError : CustomNSError {
- public static var errorDomain: String = NSCocoaErrorDomain
-
- public var errorCode: Int {
- switch self {
- case .invalidValue(_, _): return CocoaError.coderInvalidValue.rawValue
- }
- }
-
- public var errorUserInfo: [String : Any] {
- let context: Context
- switch self {
- case .invalidValue(_, let c): context = c
- }
-
- return [NSCodingPathErrorKey: context.codingPath,
- NSDebugDescriptionErrorKey: context.debugDescription]
- }
-}
-
-extension DecodingError : CustomNSError {
- public static var errorDomain: String = NSCocoaErrorDomain
-
- public var errorCode: Int {
- switch self {
- case .valueNotFound(_, _): fallthrough
- case .keyNotFound(_, _):
- return CocoaError.coderValueNotFound.rawValue
-
- case .typeMismatch(_, _): fallthrough
- case .dataCorrupted(_):
- return CocoaError.coderReadCorrupt.rawValue
- }
- }
-
- public var errorUserInfo: [String : Any] {
- let context: Context
- switch self {
- case .typeMismatch(_, let c): context = c
- case .valueNotFound(_, let c): context = c
- case .keyNotFound(_, let c): context = c
- case .dataCorrupted(let c): context = c
- }
-
- return [NSCodingPathErrorKey: context.codingPath,
- NSDebugDescriptionErrorKey: context.debugDescription]
- }
-}
-
-//===----------------------------------------------------------------------===//
// Error Utilities
//===----------------------------------------------------------------------===//
diff --git a/Foundation/JSONEncoder.swift b/Foundation/JSONEncoder.swift
index c6f09e0..2313440 100644
--- a/Foundation/JSONEncoder.swift
+++ b/Foundation/JSONEncoder.swift
@@ -1,11 +1,14 @@
+//===----------------------------------------------------------------------===//
+//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
-// See http://swift.org/LICENSE.txt for license information
-// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
+//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// JSON Encoder
@@ -138,7 +141,7 @@
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: [], debugDescription: "Top-level \(T.self) encoded as string JSON fragment."))
}
- var writingOptions = JSONSerialization.WritingOptions(rawValue: self.outputFormatting.rawValue)
+ let writingOptions = JSONSerialization.WritingOptions(rawValue: self.outputFormatting.rawValue)
return try JSONSerialization.data(withJSONObject: topLevel, options: writingOptions)
}
}
@@ -149,23 +152,23 @@
// MARK: Properties
/// The encoder's storage.
- var storage: _JSONEncodingStorage
+ fileprivate var storage: _JSONEncodingStorage
/// Options set on the top-level encoder.
- let options: JSONEncoder._Options
+ fileprivate let options: JSONEncoder._Options
/// The path to the current point in encoding.
- var codingPath: [CodingKey?]
+ public var codingPath: [CodingKey?]
/// Contextual user-provided information for use during encoding.
- var userInfo: [CodingUserInfoKey : Any] {
+ public var userInfo: [CodingUserInfoKey : Any] {
return self.options.userInfo
}
// MARK: - Initialization
/// Initializes `self` with the given top-level encoder options.
- init(options: JSONEncoder._Options, codingPath: [CodingKey?] = []) {
+ fileprivate init(options: JSONEncoder._Options, codingPath: [CodingKey?] = []) {
self.options = options
self.storage = _JSONEncodingStorage()
self.codingPath = codingPath
@@ -177,7 +180,7 @@
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
- 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()
@@ -187,7 +190,7 @@
/// Returns whether a new element can be encoded at this coding path.
///
/// `true` if an element has not yet been encoded at this coding path; `false` otherwise.
- var canEncodeNewElement: Bool {
+ fileprivate var canEncodeNewValue: Bool {
// Every time a new value gets encoded, the key it's encoded for is pushed onto the coding path (even if it's a nil key from an unkeyed container).
// At the same time, every time a container is requested, a new value gets pushed onto the storage stack.
// If there are more values on the storage stack than on the coding path, it means the value is requesting more than one container, which violates the precondition.
@@ -197,39 +200,43 @@
return self.storage.count == self.codingPath.count
}
- /// Asserts that a new container can be requested at this coding path.
- /// `preconditionFailure()`s if one cannot be requested.
- func assertCanRequestNewContainer() {
- guard self.canEncodeNewElement else {
- let previousContainerType: String
- if self.storage.containers.last is NSDictionary {
- previousContainerType = "keyed"
- } else if self.storage.containers.last is NSArray {
- previousContainerType = "unkeyed"
- } else {
- previousContainerType = "single value"
+ // MARK: - Encoder Methods
+ public func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
+ // If an existing keyed container was already requested, return that one.
+ let topContainer: NSMutableDictionary
+ if self.canEncodeNewValue {
+ // We haven't yet pushed a container at this level; do so here.
+ topContainer = self.storage.pushKeyedContainer()
+ } else {
+ guard let container = self.storage.containers.last as? NSMutableDictionary else {
+ preconditionFailure("Attempt to push new keyed encoding container when already previously encoded at this path.")
}
- preconditionFailure("Attempt to encode with new container when already encoded with \(previousContainerType) container.")
+ topContainer = container
}
- }
- // MARK: - Encoder Methods
- func container<Key>(keyedBy: Key.Type) -> KeyedEncodingContainer<Key> {
- assertCanRequestNewContainer()
- let topContainer = self.storage.pushKeyedContainer()
let container = _JSONKeyedEncodingContainer<Key>(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
return KeyedEncodingContainer(container)
}
- func unkeyedContainer() -> UnkeyedEncodingContainer {
- assertCanRequestNewContainer()
- let topContainer = self.storage.pushUnkeyedContainer()
+ public func unkeyedContainer() -> UnkeyedEncodingContainer {
+ // If an existing unkeyed container was already requested, return that one.
+ let topContainer: NSMutableArray
+ if self.canEncodeNewValue {
+ // We haven't yet pushed a container at this level; do so here.
+ topContainer = self.storage.pushUnkeyedContainer()
+ } else {
+ guard let container = self.storage.containers.last as? NSMutableArray else {
+ preconditionFailure("Attempt to push new unkeyed encoding container when already previously encoded at this path.")
+ }
+
+ topContainer = container
+ }
+
return _JSONUnkeyedEncodingContainer(referencing: self, codingPath: self.codingPath, wrapping: topContainer)
}
- func singleValueContainer() -> SingleValueEncodingContainer {
- assertCanRequestNewContainer()
+ public func singleValueContainer() -> SingleValueEncodingContainer {
return self
}
}
@@ -241,36 +248,36 @@
/// The container stack.
/// Elements may be any one of the JSON types (NSNull, NSNumber, NSString, NSArray, NSDictionary).
- private(set) var containers: [NSObject] = []
+ private(set) fileprivate var containers: [NSObject] = []
// MARK: - Initialization
/// Initializes `self` with no containers.
- init() {}
+ fileprivate init() {}
// MARK: - Modifying the Stack
- var count: Int {
+ fileprivate var count: Int {
return self.containers.count
}
- mutating func pushKeyedContainer() -> NSMutableDictionary {
+ fileprivate mutating func pushKeyedContainer() -> NSMutableDictionary {
let dictionary = NSMutableDictionary()
self.containers.append(dictionary)
return dictionary
}
- mutating func pushUnkeyedContainer() -> NSMutableArray {
+ fileprivate mutating func pushUnkeyedContainer() -> NSMutableArray {
let array = NSMutableArray()
self.containers.append(array)
return array
}
- mutating func push(container: NSObject) {
+ fileprivate mutating func push(container: NSObject) {
self.containers.append(container)
}
- mutating func popContainer() -> NSObject {
+ fileprivate mutating func popContainer() -> NSObject {
precondition(self.containers.count > 0, "Empty container stack.")
return self.containers.popLast()!
}
@@ -284,18 +291,18 @@
// MARK: Properties
/// A reference to the encoder we're writing to.
- let encoder: _JSONEncoder
+ private let encoder: _JSONEncoder
/// A reference to the container we're writing to.
- let container: NSMutableDictionary
+ private let container: NSMutableDictionary
/// The path of coding keys taken to get to this point in encoding.
- var codingPath: [CodingKey?]
+ private(set) public var codingPath: [CodingKey?]
// MARK: - Initialization
/// Initializes `self` with the given references.
- 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
@@ -307,7 +314,7 @@
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
- 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()
@@ -316,40 +323,41 @@
// MARK: - KeyedEncodingContainerProtocol Methods
- mutating func encode(_ value: Bool, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: Int, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: Int8, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: Int16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: Int32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: Int64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: UInt, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: UInt8, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encodeNil(forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = NSNull() }
+ public mutating func encode(_ value: Bool, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: Int, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: Int8, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: Int16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: Int32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: Int64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: UInt, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: UInt8, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: UInt16, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: UInt32, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: UInt64, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
+ public mutating func encode(_ value: String, forKey key: Key) throws { self.container[key.stringValue._bridgeToObjectiveC()] = self.encoder.box(value) }
- mutating func encode(_ value: Float, forKey key: Key) throws {
+ public mutating func encode(_ value: Float, forKey key: Key) throws {
// Since the float may be invalid and throw, the coding path needs to contain this key.
try self.encoder.with(pushedKey: key) {
self.container[key.stringValue._bridgeToObjectiveC()] = try self.encoder.box(value)
}
}
- mutating func encode(_ value: Double, forKey key: Key) throws {
+ public mutating func encode(_ value: Double, forKey key: Key) throws {
// Since the double may be invalid and throw, the coding path needs to contain this key.
try self.encoder.with(pushedKey: key) {
self.container[key.stringValue._bridgeToObjectiveC()] = try self.encoder.box(value)
}
}
- mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
+ public mutating func encode<T : Encodable>(_ value: T, forKey key: Key) throws {
try self.encoder.with(pushedKey: key) {
self.container[key.stringValue._bridgeToObjectiveC()] = try self.encoder.box(value)
}
}
- mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
+ public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> {
let dictionary = NSMutableDictionary()
self.container[key.stringValue._bridgeToObjectiveC()] = dictionary
@@ -359,7 +367,7 @@
}
}
- mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
+ public mutating func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
let array = NSMutableArray()
self.container[key.stringValue._bridgeToObjectiveC()] = array
@@ -368,11 +376,11 @@
}
}
- mutating func superEncoder() -> Encoder {
+ public mutating func superEncoder() -> Encoder {
return _JSONReferencingEncoder(referencing: self.encoder, at: _JSONSuperKey.super, wrapping: self.container)
}
- mutating func superEncoder(forKey key: Key) -> Encoder {
+ public mutating func superEncoder(forKey key: Key) -> Encoder {
return _JSONReferencingEncoder(referencing: self.encoder, at: key, wrapping: self.container)
}
}
@@ -381,18 +389,18 @@
// MARK: Properties
/// A reference to the encoder we're writing to.
- let encoder: _JSONEncoder
+ private let encoder: _JSONEncoder
/// A reference to the container we're writing to.
- let container: NSMutableArray
+ private let container: NSMutableArray
/// The path of coding keys taken to get to this point in encoding.
- var codingPath: [CodingKey?]
+ private(set) public var codingPath: [CodingKey?]
// MARK: - Initialization
/// Initializes `self` with the given references.
- 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
@@ -404,7 +412,7 @@
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
- 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()
@@ -413,40 +421,41 @@
// MARK: - UnkeyedEncodingContainer Methods
- mutating func encode(_ value: Bool) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: Int) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: Int8) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: Int16) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: Int32) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: Int64) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: UInt) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: UInt8) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encodeNil() throws { self.container.add(NSNull()) }
+ public mutating func encode(_ value: Bool) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: Int) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: Int8) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: Int16) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: Int32) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: Int64) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: UInt) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: UInt8) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: UInt16) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: UInt32) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: UInt64) throws { self.container.add(self.encoder.box(value)) }
+ public mutating func encode(_ value: String) throws { self.container.add(self.encoder.box(value)) }
- mutating func encode(_ value: Float) throws {
+ 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) {
self.container.add(try self.encoder.box(value))
}
}
- mutating func encode(_ value: Double) throws {
+ 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) {
self.container.add(try self.encoder.box(value))
}
}
- mutating func encode<T : Encodable>(_ value: T) throws {
+ public mutating func encode<T : Encodable>(_ value: T) throws {
try self.encoder.with(pushedKey: nil) {
self.container.add(try self.encoder.box(value))
}
}
- mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
+ public mutating func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> {
let dictionary = NSMutableDictionary()
self.container.add(dictionary)
@@ -456,7 +465,7 @@
}
}
- mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
+ public mutating func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {
let array = NSMutableArray()
self.container.add(array)
@@ -465,112 +474,95 @@
}
}
- mutating func superEncoder() -> Encoder {
+ public mutating func superEncoder() -> Encoder {
return _JSONReferencingEncoder(referencing: self.encoder, at: self.container.count, wrapping: self.container)
}
}
extension _JSONEncoder : SingleValueEncodingContainer {
- // MARK: - Utility Methods
-
- /// Asserts that a single value can be encoded at the current coding path (i.e. that one has not already been encoded through this container).
- /// `preconditionFailure()`s if one cannot be encoded.
- ///
- /// This is similar to assertCanRequestNewContainer above.
- func assertCanEncodeSingleValue() {
- guard self.canEncodeNewElement else {
- let previousContainerType: String
- if self.storage.containers.last is NSDictionary {
- previousContainerType = "keyed"
- } else if self.storage.containers.last is NSArray {
- previousContainerType = "unkeyed"
- } else {
- preconditionFailure("Attempt to encode multiple values in a single value container.")
- }
-
- preconditionFailure("Attempt to encode with new container when already encoded with \(previousContainerType) container.")
- }
- }
-
// MARK: - SingleValueEncodingContainer Methods
- func encodeNil() throws {
- assertCanEncodeSingleValue()
+ fileprivate func assertCanEncodeNewValue() {
+ precondition(self.canEncodeNewValue, "Attempt to encode value through single value container when previously value already encoded.")
+ }
+
+ public func encodeNil() throws {
+ assertCanEncodeNewValue()
self.storage.push(container: NSNull())
}
- func encode(_ value: Bool) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Bool) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: Int) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Int) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: Int8) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Int8) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: Int16) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Int16) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: Int32) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Int32) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: Int64) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Int64) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: UInt) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: UInt) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: UInt8) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: UInt8) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: UInt16) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: UInt16) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: UInt32) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: UInt32) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: UInt64) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: UInt64) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: String) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: String) throws {
+ assertCanEncodeNewValue()
self.storage.push(container: box(value))
}
- func encode(_ value: Float) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Float) throws {
+ assertCanEncodeNewValue()
try self.storage.push(container: box(value))
}
- func encode(_ value: Double) throws {
- assertCanEncodeSingleValue()
+ public func encode(_ value: Double) throws {
+ assertCanEncodeNewValue()
try self.storage.push(container: box(value))
}
- func encode<T : Encodable>(_ value: T) throws {
- assertCanEncodeSingleValue()
+ public func encode<T : Encodable>(_ value: T) throws {
+ assertCanEncodeNewValue()
try self.storage.push(container: box(value))
}
}
@@ -597,7 +589,7 @@
guard case let .convertToString(positiveInfinity: posInfString,
negativeInfinity: negInfString,
nan: nanString) = self.options.nonConformingFloatEncodingStrategy else {
- throw EncodingError._invalidFloatingPointValue(float, at: codingPath)
+ throw EncodingError._invalidFloatingPointValue(float, at: codingPath)
}
if float == Float.infinity {
@@ -617,7 +609,7 @@
guard case let .convertToString(positiveInfinity: posInfString,
negativeInfinity: negInfString,
nan: nanString) = self.options.nonConformingFloatEncodingStrategy else {
- throw EncodingError._invalidFloatingPointValue(double, at: codingPath)
+ throw EncodingError._invalidFloatingPointValue(double, at: codingPath)
}
if double == Double.infinity {
@@ -698,6 +690,11 @@
} else if T.self == URL.self {
// Encode URLs as single strings.
return self.box((value as! URL).absoluteString)
+ } else if T.self == Decimal.self {
+ // On Darwin we get ((value as! Decimal) as NSDecimalNumber) since JSONSerialization can consume NSDecimalNumber values.
+ // FIXME: Attempt to create a Decimal value if JSONSerialization on Linux consume one.
+ let doubleValue = (value as! Decimal).doubleValue
+ return try self.box(doubleValue)
}
// The value should request a container from the _JSONEncoder.
@@ -722,7 +719,7 @@
// MARK: Reference types.
/// The type of container we're referencing.
- enum Reference {
+ private enum Reference {
/// Referencing a specific index in an array container.
case array(NSMutableArray, Int)
@@ -733,15 +730,15 @@
// MARK: - Properties
/// The encoder we're referencing.
- let encoder: _JSONEncoder
+ fileprivate let encoder: _JSONEncoder
/// The container reference itself.
- let reference: Reference
+ private let reference: Reference
// MARK: - Initialization
/// Initializes `self` by referencing the given array container in the given encoder.
- init(referencing encoder: _JSONEncoder, at index: Int, wrapping array: NSMutableArray) {
+ fileprivate init(referencing encoder: _JSONEncoder, at index: Int, wrapping array: NSMutableArray) {
self.encoder = encoder
self.reference = .array(array, index)
super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -750,7 +747,7 @@
}
/// Initializes `self` by referencing the given dictionary container in the given encoder.
- init(referencing encoder: _JSONEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
+ fileprivate init(referencing encoder: _JSONEncoder, at key: CodingKey, wrapping dictionary: NSMutableDictionary) {
self.encoder = encoder
self.reference = .dictionary(dictionary, key.stringValue)
super.init(options: encoder.options, codingPath: encoder.codingPath)
@@ -760,7 +757,7 @@
// MARK: - Coding Path Operations
- override var canEncodeNewElement: Bool {
+ fileprivate override var canEncodeNewValue: Bool {
// With a regular encoder, the storage and coding path grow together.
// A referencing encoder, however, inherits its parents coding path, as well as the key it was created for.
// We have to take this into account.
@@ -891,23 +888,23 @@
// MARK: Properties
/// The decoder's storage.
- var storage: _JSONDecodingStorage
+ fileprivate var storage: _JSONDecodingStorage
/// Options set on the top-level decoder.
- let options: JSONDecoder._Options
+ fileprivate let options: JSONDecoder._Options
/// The path to the current point in encoding.
- var codingPath: [CodingKey?]
+ private(set) public var codingPath: [CodingKey?]
/// Contextual user-provided information for use during encoding.
- var userInfo: [CodingUserInfoKey : Any] {
+ public var userInfo: [CodingUserInfoKey : Any] {
return self.options.userInfo
}
// MARK: - Initialization
/// Initializes `self` with the given top-level container and options.
- 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
@@ -920,7 +917,7 @@
///
/// - parameter key: The key to push. May be nil for unkeyed containers.
/// - parameter work: The work to perform with the key in the path.
- 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()
@@ -929,7 +926,7 @@
// MARK: - Decoder Methods
- func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
+ public func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
guard !(self.storage.topContainer is NSNull) else {
throw DecodingError.valueNotFound(KeyedDecodingContainer<Key>.self,
DecodingError.Context(codingPath: self.codingPath,
@@ -944,7 +941,7 @@
return KeyedDecodingContainer(container)
}
- func unkeyedContainer() throws -> UnkeyedDecodingContainer {
+ public func unkeyedContainer() throws -> UnkeyedDecodingContainer {
guard !(self.storage.topContainer is NSNull) else {
throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
DecodingError.Context(codingPath: self.codingPath,
@@ -958,7 +955,7 @@
return _JSONUnkeyedDecodingContainer(referencing: self, wrapping: topContainer)
}
- func singleValueContainer() throws -> SingleValueDecodingContainer {
+ public func singleValueContainer() throws -> SingleValueDecodingContainer {
return self
}
}
@@ -970,29 +967,29 @@
/// The container stack.
/// Elements may be any one of the JSON types (NSNull, NSNumber, String, Array, [String : Any]).
- private(set) var containers: [Any] = []
+ private(set) fileprivate var containers: [Any] = []
// MARK: - Initialization
/// Initializes `self` with no containers.
- init() {}
+ fileprivate init() {}
// MARK: - Modifying the Stack
- var count: Int {
+ fileprivate var count: Int {
return self.containers.count
}
- var topContainer: Any {
+ fileprivate var topContainer: Any {
precondition(self.containers.count > 0, "Empty container stack.")
return self.containers.last!
}
- mutating func push(container: Any) {
+ fileprivate mutating func push(container: Any) {
self.containers.append(container)
}
- mutating func popContainer() {
+ fileprivate mutating func popContainer() {
precondition(self.containers.count > 0, "Empty container stack.")
self.containers.removeLast()
}
@@ -1006,18 +1003,18 @@
// MARK: Properties
/// A reference to the decoder we're reading from.
- let decoder: _JSONDecoder
+ private let decoder: _JSONDecoder
/// A reference to the container we're reading from.
- let container: [String : Any]
+ private let container: [String : Any]
/// The path of coding keys taken to get to this point in decoding.
- var codingPath: [CodingKey?]
+ private(set) public var codingPath: [CodingKey?]
// MARK: - Initialization
/// Initializes `self` by referencing the given decoder and container.
- init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
+ fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [String : Any]) {
self.decoder = decoder
self.container = container
self.codingPath = decoder.codingPath
@@ -1025,111 +1022,233 @@
// MARK: - KeyedDecodingContainerProtocol Methods
- var allKeys: [Key] {
+ public var allKeys: [Key] {
return self.container.keys.flatMap { Key(stringValue: $0) }
}
- func contains(_ key: Key) -> Bool {
+ public func contains(_ key: Key) -> Bool {
return self.container[key.stringValue] != nil
}
- func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? {
+ public func decodeNil(forKey key: Key) throws -> Bool {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
+ return entry is NSNull
+ }
+
+ public func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Bool.self)
+ guard let value = try self.decoder.unbox(entry, as: Bool.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? {
+ public func decode(_ type: Int.Type, forKey key: Key) throws -> Int {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Int.self)
+ guard let value = try self.decoder.unbox(entry, as: Int.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? {
+ public func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Int8.self)
+ guard let value = try self.decoder.unbox(entry, as: Int8.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? {
+ public func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Int16.self)
+ guard let value = try self.decoder.unbox(entry, as: Int16.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? {
+ public func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Int32.self)
+ guard let value = try self.decoder.unbox(entry, as: Int32.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? {
+ public func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Int64.self)
+ guard let value = try self.decoder.unbox(entry, as: Int64.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? {
+ public func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: UInt.self)
+ guard let value = try self.decoder.unbox(entry, as: UInt.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? {
+ public func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: UInt8.self)
+ guard let value = try self.decoder.unbox(entry, as: UInt8.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? {
+ public func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: UInt16.self)
+ guard let value = try self.decoder.unbox(entry, as: UInt16.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? {
+ public func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: UInt32.self)
+ guard let value = try self.decoder.unbox(entry, as: UInt32.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? {
+ public func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: UInt64.self)
+ guard let value = try self.decoder.unbox(entry, as: UInt64.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? {
+ public func decode(_ type: Float.Type, forKey key: Key) throws -> Float {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Float.self)
+ guard let value = try self.decoder.unbox(entry, as: Float.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? {
+ public func decode(_ type: Double.Type, forKey key: Key) throws -> Double {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Double.self)
+ guard let value = try self.decoder.unbox(entry, as: Double.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? {
+ public func decode(_ type: String.Type, forKey key: Key) throws -> String {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: String.self)
+ guard let value = try self.decoder.unbox(entry, as: String.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent(_ type: Data.Type, forKey key: Key) throws -> Data? {
+ public func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T {
+ guard let entry = self.container[key.stringValue] else {
+ throw DecodingError.keyNotFound(key, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "No value associated with key \(key) (\"\(key.stringValue)\")."))
+ }
+
return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: Data.self)
+ guard let value = try self.decoder.unbox(entry, as: T.self) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
+ }
+
+ return value
}
}
- func decodeIfPresent<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T? {
- return try self.decoder.with(pushedKey: key) {
- return try self.decoder.unbox(self.container[key.stringValue], as: T.self)
- }
- }
-
- func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
+ public func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> {
return try self.decoder.with(pushedKey: key) {
guard let value = self.container[key.stringValue] else {
throw DecodingError.keyNotFound(key,
@@ -1146,7 +1265,7 @@
}
}
- func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
+ public func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
return try self.decoder.with(pushedKey: key) {
guard let value = self.container[key.stringValue] else {
throw DecodingError.keyNotFound(key,
@@ -1162,23 +1281,18 @@
}
}
- func _superDecoder(forKey key: CodingKey) throws -> Decoder {
- return try self.decoder.with(pushedKey: key) {
- guard let value = self.container[key.stringValue] else {
- throw DecodingError.keyNotFound(key,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Cannot get superDecoder() -- no value found for key \"\(key.stringValue)\""))
- }
-
+ private func _superDecoder(forKey key: CodingKey) throws -> Decoder {
+ return self.decoder.with(pushedKey: key) {
+ let value: Any = self.container[key.stringValue] ?? NSNull()
return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
}
}
- func superDecoder() throws -> Decoder {
+ public func superDecoder() throws -> Decoder {
return try _superDecoder(forKey: _JSONSuperKey.super)
}
- func superDecoder(forKey key: Key) throws -> Decoder {
+ public func superDecoder(forKey key: Key) throws -> Decoder {
return try _superDecoder(forKey: key)
}
}
@@ -1187,21 +1301,21 @@
// MARK: Properties
/// A reference to the decoder we're reading from.
- let decoder: _JSONDecoder
+ private let decoder: _JSONDecoder
/// A reference to the container we're reading from.
- let container: [Any]
+ private let container: [Any]
/// The path of coding keys taken to get to this point in decoding.
- var codingPath: [CodingKey?]
+ private(set) public var codingPath: [CodingKey?]
/// The index of the element we're about to decode.
- var currentIndex: Int
+ private var currentIndex: Int
// MARK: - Initialization
/// Initializes `self` by referencing the given decoder and container.
- init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
+ fileprivate init(referencing decoder: _JSONDecoder, wrapping container: [Any]) {
self.decoder = decoder
self.container = container
self.codingPath = decoder.codingPath
@@ -1210,175 +1324,253 @@
// MARK: - UnkeyedDecodingContainer Methods
- var count: Int? {
+ public var count: Int? {
return self.container.count
}
- var isAtEnd: Bool {
+ public var isAtEnd: Bool {
return self.currentIndex >= self.count!
}
- mutating func decodeIfPresent(_ type: Bool.Type) throws -> Bool? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
+
+ if self.container[self.currentIndex] is NSNull {
+ self.currentIndex += 1
+ return true
+ } else {
+ return false
+ }
+ }
+
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Bool.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Int.Type) throws -> Int? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Int8.Type) throws -> Int8? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int8.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Int16.Type) throws -> Int16? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int16.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Int32.Type) throws -> Int32? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int32.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Int64.Type) throws -> Int64? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Int64.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: UInt.Type) throws -> UInt? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: UInt8.Type) throws -> UInt8? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt8.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: UInt16.Type) throws -> UInt16? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt16.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: UInt32.Type) throws -> UInt32? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt32.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: UInt64.Type) throws -> UInt64? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: UInt64.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Float.Type) throws -> Float? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Float.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Double.Type) throws -> Double? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Double.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: String.Type) throws -> String? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: String.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent(_ type: Data.Type) throws -> Data? {
- guard !self.isAtEnd else { return nil }
+ 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."))
+ }
return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: Data.self)
+ 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."))
+ }
+
self.currentIndex += 1
return decoded
}
}
- mutating func decodeIfPresent<T : Decodable>(_ type: T.Type) throws -> T? {
- guard !self.isAtEnd else { return nil }
-
- return try self.decoder.with(pushedKey: nil) {
- let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self)
- self.currentIndex += 1
- return decoded
- }
- }
-
- mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
+ public mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
return try self.decoder.with(pushedKey: nil) {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(KeyedDecodingContainer<NestedKey>.self,
@@ -1403,7 +1595,7 @@
}
}
- mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
+ public mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
return try self.decoder.with(pushedKey: nil) {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(UnkeyedDecodingContainer.self,
@@ -1427,7 +1619,7 @@
}
}
- mutating func superDecoder() throws -> Decoder {
+ public mutating func superDecoder() throws -> Decoder {
return try self.decoder.with(pushedKey: nil) {
guard !self.isAtEnd else {
throw DecodingError.valueNotFound(Decoder.self,
@@ -1436,12 +1628,6 @@
}
let value = self.container[self.currentIndex]
- guard !(value is NSNull) else {
- throw DecodingError.valueNotFound(Decoder.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Cannot get superDecoder() -- found null value instead."))
- }
-
self.currentIndex += 1
return _JSONDecoder(referencing: value, at: self.decoder.codingPath, options: self.decoder.options)
}
@@ -1451,159 +1637,89 @@
extension _JSONDecoder : SingleValueDecodingContainer {
// MARK: SingleValueDecodingContainer Methods
- func decodeNil() -> Bool {
+ private func expectNonNull<T>(_ type: T.Type) throws {
+ guard !self.decodeNil() else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.codingPath, debugDescription: "Expected \(type) but found null value instead."))
+ }
+ }
+
+ public func decodeNil() -> Bool {
return self.storage.topContainer is NSNull
}
- // These all unwrap the result, since we couldn't have gotten a single value container if the topContainer was null.
- func decode(_ type: Bool.Type) throws -> Bool {
- guard let value = try self.unbox(self.storage.topContainer, as: Bool.self) else {
- throw DecodingError.valueNotFound(Bool.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Bool but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Bool.Type) throws -> Bool {
+ try expectNonNull(Bool.self)
+ return try self.unbox(self.storage.topContainer, as: Bool.self)!
}
- func decode(_ type: Int.Type) throws -> Int {
- guard let value = try self.unbox(self.storage.topContainer, as: Int.self) else {
- throw DecodingError.valueNotFound(Int.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Int but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Int.Type) throws -> Int {
+ try expectNonNull(Int.self)
+ return try self.unbox(self.storage.topContainer, as: Int.self)!
}
- func decode(_ type: Int8.Type) throws -> Int8 {
- guard let value = try self.unbox(self.storage.topContainer, as: Int8.self) else {
- throw DecodingError.valueNotFound(Int8.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Int8 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Int8.Type) throws -> Int8 {
+ try expectNonNull(Int8.self)
+ return try self.unbox(self.storage.topContainer, as: Int8.self)!
}
- func decode(_ type: Int16.Type) throws -> Int16 {
- guard let value = try self.unbox(self.storage.topContainer, as: Int16.self) else {
- throw DecodingError.valueNotFound(Int16.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Int16 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Int16.Type) throws -> Int16 {
+ try expectNonNull(Int16.self)
+ return try self.unbox(self.storage.topContainer, as: Int16.self)!
}
- func decode(_ type: Int32.Type) throws -> Int32 {
- guard let value = try self.unbox(self.storage.topContainer, as: Int32.self) else {
- throw DecodingError.valueNotFound(Int32.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Int32 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Int32.Type) throws -> Int32 {
+ try expectNonNull(Int32.self)
+ return try self.unbox(self.storage.topContainer, as: Int32.self)!
}
- func decode(_ type: Int64.Type) throws -> Int64 {
- guard let value = try self.unbox(self.storage.topContainer, as: Int64.self) else {
- throw DecodingError.valueNotFound(Int64.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Int64 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Int64.Type) throws -> Int64 {
+ try expectNonNull(Int64.self)
+ return try self.unbox(self.storage.topContainer, as: Int64.self)!
}
- func decode(_ type: UInt.Type) throws -> UInt {
- guard let value = try self.unbox(self.storage.topContainer, as: UInt.self) else {
- throw DecodingError.valueNotFound(UInt.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected UInt but found null value instead."))
- }
-
- return value
+ public func decode(_ type: UInt.Type) throws -> UInt {
+ try expectNonNull(UInt.self)
+ return try self.unbox(self.storage.topContainer, as: UInt.self)!
}
- func decode(_ type: UInt8.Type) throws -> UInt8 {
- guard let value = try self.unbox(self.storage.topContainer, as: UInt8.self) else {
- throw DecodingError.valueNotFound(UInt8.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected UInt8 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: UInt8.Type) throws -> UInt8 {
+ try expectNonNull(UInt8.self)
+ return try self.unbox(self.storage.topContainer, as: UInt8.self)!
}
- func decode(_ type: UInt16.Type) throws -> UInt16 {
- guard let value = try self.unbox(self.storage.topContainer, as: UInt16.self) else {
- throw DecodingError.valueNotFound(UInt16.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected UInt16 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: UInt16.Type) throws -> UInt16 {
+ try expectNonNull(UInt16.self)
+ return try self.unbox(self.storage.topContainer, as: UInt16.self)!
}
- func decode(_ type: UInt32.Type) throws -> UInt32 {
- guard let value = try self.unbox(self.storage.topContainer, as: UInt32.self) else {
- throw DecodingError.valueNotFound(UInt32.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected UInt32 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: UInt32.Type) throws -> UInt32 {
+ try expectNonNull(UInt32.self)
+ return try self.unbox(self.storage.topContainer, as: UInt32.self)!
}
- func decode(_ type: UInt64.Type) throws -> UInt64 {
- guard let value = try self.unbox(self.storage.topContainer, as: UInt64.self) else {
- throw DecodingError.valueNotFound(UInt64.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected UInt64 but found null value instead."))
- }
-
- return value
+ public func decode(_ type: UInt64.Type) throws -> UInt64 {
+ try expectNonNull(UInt64.self)
+ return try self.unbox(self.storage.topContainer, as: UInt64.self)!
}
- func decode(_ type: Float.Type) throws -> Float {
- guard let value = try self.unbox(self.storage.topContainer, as: Float.self) else {
- throw DecodingError.valueNotFound(Float.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Float but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Float.Type) throws -> Float {
+ try expectNonNull(Float.self)
+ return try self.unbox(self.storage.topContainer, as: Float.self)!
}
- func decode(_ type: Double.Type) throws -> Double {
- guard let value = try self.unbox(self.storage.topContainer, as: Double.self) else {
- throw DecodingError.valueNotFound(Double.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected Double but found null value instead."))
- }
-
- return value
+ public func decode(_ type: Double.Type) throws -> Double {
+ try expectNonNull(Double.self)
+ return try self.unbox(self.storage.topContainer, as: Double.self)!
}
- func decode(_ type: String.Type) throws -> String {
- guard let value = try self.unbox(self.storage.topContainer, as: String.self) else {
- throw DecodingError.valueNotFound(String.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected String but found null value instead."))
- }
-
- return value
+ public func decode(_ type: String.Type) throws -> String {
+ try expectNonNull(String.self)
+ return try self.unbox(self.storage.topContainer, as: String.self)!
}
- func decode<T : Decodable>(_ type: T.Type) throws -> T {
- guard let value = try self.unbox(self.storage.topContainer, as: T.self) else {
- throw DecodingError.valueNotFound(T.self,
- DecodingError.Context(codingPath: self.codingPath,
- debugDescription: "Expected \(T.self) but found null value instead."))
- }
-
- return value
+ public func decode<T : Decodable>(_ type: T.Type) throws -> T {
+ try expectNonNull(T.self)
+ return try self.unbox(self.storage.topContainer, as: T.self)!
}
}
@@ -1611,8 +1727,7 @@
extension _JSONDecoder {
/// Returns the given value unboxed from a container.
- fileprivate func unbox(_ value: Any?, as type: Bool.Type) throws -> Bool? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Bool.Type) throws -> Bool? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1624,16 +1739,10 @@
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
}
- let bool = number.boolValue
- guard NSNumber(value: bool) == number else {
- throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Parsed JSON number <\(number)> does not fit in \(type)."))
- }
-
- return bool
+ return number.boolValue
}
- fileprivate func unbox(_ value: Any?, as type: Int.Type) throws -> Int? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Int.Type) throws -> Int? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1648,8 +1757,7 @@
return int
}
- fileprivate func unbox(_ value: Any?, as type: Int8.Type) throws -> Int8? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Int8.Type) throws -> Int8? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1664,8 +1772,7 @@
return int8
}
- fileprivate func unbox(_ value: Any?, as type: Int16.Type) throws -> Int16? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Int16.Type) throws -> Int16? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1680,8 +1787,7 @@
return int16
}
- fileprivate func unbox(_ value: Any?, as type: Int32.Type) throws -> Int32? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Int32.Type) throws -> Int32? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1696,8 +1802,7 @@
return int32
}
- fileprivate func unbox(_ value: Any?, as type: Int64.Type) throws -> Int64? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Int64.Type) throws -> Int64? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1712,8 +1817,7 @@
return int64
}
- fileprivate func unbox(_ value: Any?, as type: UInt.Type) throws -> UInt? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: UInt.Type) throws -> UInt? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1728,8 +1832,7 @@
return uint
}
- fileprivate func unbox(_ value: Any?, as type: UInt8.Type) throws -> UInt8? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: UInt8.Type) throws -> UInt8? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1744,8 +1847,7 @@
return uint8
}
- fileprivate func unbox(_ value: Any?, as type: UInt16.Type) throws -> UInt16? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: UInt16.Type) throws -> UInt16? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1760,8 +1862,7 @@
return uint16
}
- fileprivate func unbox(_ value: Any?, as type: UInt32.Type) throws -> UInt32? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: UInt32.Type) throws -> UInt32? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1776,8 +1877,7 @@
return uint32
}
- fileprivate func unbox(_ value: Any?, as type: UInt64.Type) throws -> UInt64? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: UInt64.Type) throws -> UInt64? {
guard !(value is NSNull) else { return nil }
guard let number = value as? NSNumber else {
@@ -1792,8 +1892,7 @@
return uint64
}
- fileprivate func unbox(_ value: Any?, as type: Float.Type) throws -> Float? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Float.Type) throws -> Float? {
guard !(value is NSNull) else { return nil }
if let number = value as? NSNumber {
@@ -1810,20 +1909,20 @@
return Float(double)
- /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
- } else if let double = value as? Double {
- if abs(double) <= Double(Float.max) {
- return Float(double)
- }
+ /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
+ } else if let double = value as? Double {
+ if abs(double) <= Double(Float.max) {
+ return Float(double)
+ }
- overflow = true
- } else if let int = value as? Int {
- if let float = Float(exactly: int) {
- return float
- }
+ overflow = true
+ } else if let int = value as? Int {
+ if let float = Float(exactly: int) {
+ return float
+ }
- overflow = true
- */
+ overflow = true
+ */
} else if let string = value as? String,
case .convertFromString(let posInfString, let negInfString, let nanString) = self.options.nonConformingFloatDecodingStrategy {
@@ -1839,8 +1938,7 @@
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
}
- func unbox(_ value: Any?, as type: Double.Type) throws -> Double? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Double.Type) throws -> Double? {
guard !(value is NSNull) else { return nil }
if let number = value as? NSNumber {
@@ -1850,16 +1948,16 @@
// * If it was Decimal, you will get back the nearest approximation
return number.doubleValue
- /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
- } else if let double = value as? Double {
- return double
- } else if let int = value as? Int {
- if let double = Double(exactly: int) {
- return double
- }
+ /* FIXME: If swift-corelibs-foundation doesn't change to use NSNumber, this code path will need to be included and tested:
+ } else if let double = value as? Double {
+ return double
+ } else if let int = value as? Int {
+ if let double = Double(exactly: int) {
+ return double
+ }
- overflow = true
- */
+ overflow = true
+ */
} else if let string = value as? String,
case .convertFromString(let posInfString, let negInfString, let nanString) = self.options.nonConformingFloatDecodingStrategy {
@@ -1875,8 +1973,7 @@
throw DecodingError._typeMismatch(at: self.codingPath, expectation: type, reality: value)
}
- func unbox(_ value: Any?, as type: String.Type) throws -> String? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: String.Type) throws -> String? {
guard !(value is NSNull) else { return nil }
guard let string = value as? String else {
@@ -1886,8 +1983,7 @@
return string
}
- func unbox(_ value: Any?, as type: Date.Type) throws -> Date? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Date.Type) throws -> Date? {
guard !(value is NSNull) else { return nil }
switch self.options.dateDecodingStrategy {
@@ -1933,8 +2029,7 @@
}
}
- func unbox(_ value: Any?, as type: Data.Type) throws -> Data? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Data.Type) throws -> Data? {
guard !(value is NSNull) else { return nil }
switch self.options.dataDecodingStrategy {
@@ -1957,15 +2052,23 @@
}
}
- func unbox<T : Decodable>(_ value: Any?, as type: T.Type) throws -> T? {
- guard let value = value else { return nil }
+ fileprivate func unbox(_ value: Any, as type: Decimal.Type) throws -> Decimal? {
guard !(value is NSNull) else { return nil }
+ // On Darwin we get (value as? Decimal) since JSONSerialization can produce NSDecimalNumber values.
+ // FIXME: Attempt to grab a Decimal value if JSONSerialization on Linux produces one.
+ let doubleValue = try self.unbox(value, as: Double.self)!
+ return Decimal(doubleValue)
+ }
+
+ fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
let decoded: T
if T.self == Date.self {
- decoded = (try self.unbox(value, as: Date.self) as! T)
+ guard let date = try self.unbox(value, as: Date.self) else { return nil }
+ decoded = date as! T
} else if T.self == Data.self {
- decoded = (try self.unbox(value, as: Data.self) as! T)
+ guard let data = try self.unbox(value, as: Data.self) else { return nil }
+ decoded = data as! T
} else if T.self == URL.self {
guard let urlString = try self.unbox(value, as: String.self) else {
return nil
@@ -1975,14 +2078,17 @@
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath,
debugDescription: "Invalid URL string."))
}
-
+
decoded = (url as! T)
+ } else if T.self == Decimal.self {
+ guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
+ decoded = decimal as! T
} else {
self.storage.push(container: value)
decoded = try T(from: self)
self.storage.popContainer()
}
-
+
return decoded
}
}
@@ -2027,7 +2133,7 @@
} else {
valueDescription = "\(T.self).nan"
}
-
+
let debugDescription = "Unable to encode \(valueDescription) directly in JSON. Use JSONEncoder.NonConformingFloatEncodingStrategy.convertToString to specify how the value should be encoded."
return .invalidValue(value, EncodingError.Context(codingPath: codingPath, debugDescription: debugDescription))
}