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))
     }