         }
     }
 
-    mutating func decode(_ type: Bool.Type)   throws -> Bool { return try unbox() }
-    mutating func decode(_ type: Int.Type)    throws -> Int { return try unbox() }
-    mutating func decode(_ type: Int8.Type)   throws -> Int8 { return try unbox() }
-    mutating func decode(_ type: Int16.Type)  throws -> Int16 { return try unbox() }
-    mutating func decode(_ type: Int32.Type)  throws -> Int32 { return try unbox() }
-    mutating func decode(_ type: Int64.Type)  throws -> Int64 { return try unbox() }
-    mutating func decode(_ type: UInt.Type)   throws -> UInt { return try unbox() }
-    mutating func decode(_ type: UInt8.Type)  throws -> UInt8 { return try unbox() }
-    mutating func decode(_ type: UInt16.Type) throws -> UInt16 { return try unbox() }
-    mutating func decode(_ type: UInt32.Type) throws -> UInt32 { return try unbox() }
-    mutating func decode(_ type: UInt64.Type) throws -> UInt64 { return try unbox() }
-    mutating func decode(_ type: Float.Type)  throws -> Float { return try unbox() }
-    mutating func decode(_ type: Double.Type) throws -> Double { return try unbox() }
-    mutating func decode(_ type: String.Type) throws -> String { return try unbox() }
-
-    mutating func decode<T>(_ type: T.Type) throws -> T where T: Decodable {
-        try throwErrorIfAtEnd(type)
-        let value = try currentDecoder.decode(type)
-        currentIndex += 1
-        return value
-    }
+    mutating func decode(_ type: Bool.Type)   throws -> Bool { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Int.Type)    throws -> Int { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Int8.Type)   throws -> Int8 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Int16.Type)  throws -> Int16 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Int32.Type)  throws -> Int32 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Int64.Type)  throws -> Int64 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: UInt.Type)   throws -> UInt { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: UInt8.Type)  throws -> UInt8 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: UInt16.Type) throws -> UInt16 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: UInt32.Type) throws -> UInt32 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: UInt64.Type) throws -> UInt64 { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Float.Type)  throws -> Float { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: Double.Type) throws -> Double { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode(_ type: String.Type) throws -> String { return try currentDecoder { try $0.decode(type) } }
+    mutating func decode<T: Decodable>(_ type: T.Type) throws -> T { return try currentDecoder { try $0.decode(type) } }
 
     mutating func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer<NestedKey> {
-        try throwErrorIfAtEnd(KeyedDecodingContainer<NestedKey>.self)
-        let container = try currentDecoder.container(keyedBy: type)
-        currentIndex += 1
-        return container
+        return try currentDecoder { try $0.container(keyedBy: type) }
     }
 
     mutating func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer {
-        try throwErrorIfAtEnd(UnkeyedDecodingContainer.self)
-        let container = try currentDecoder.unkeyedContainer()
-        currentIndex += 1
-        return container
+        return try currentDecoder { try $0.unkeyedContainer() }
     }
 
     mutating func superDecoder() throws -> Decoder {
-        try throwErrorIfAtEnd(Decoder.self)
-        defer { currentIndex += 1 }
-        return currentDecoder
+        return try currentDecoder { $0 }
     }
 
     // MARK: -
 
     private var currentKey: CodingKey { return _ObjectCodingKey(index: currentIndex) }
     private var currentObject: Any { return array[currentIndex] }
-    private var currentDecoder: _Decoder { return decoder.decoder(referencing: currentObject, as: currentKey) }
 
     private func throwErrorIfAtEnd<T>(_ type: T.Type) throws {
         if isAtEnd { throw _valueNotFound(at: codingPath + [currentKey], type, "Unkeyed container is at end.") }
     }
 
-    private mutating func unbox<T: Decodable>() throws -> T {
+    private mutating func currentDecoder<T>(closure: (_Decoder) throws -> T) throws -> T {
         try throwErrorIfAtEnd(T.self)
-        let decoded: T = try currentDecoder.unbox(currentObject)
+        let decoded: T = try closure(decoder.decoder(referencing: currentObject, as: currentKey))
         currentIndex += 1
         return decoded
     }

        return value
    }

    /// create a new `_Decoder` instance referencing `object` as `key` inheriting `userInfo`
    fileprivate func decoder(referencing object: Any, `as` key: CodingKey) -> _Decoder {
        return .init(object, options, userInfo, codingPath + [key])


    private func decoder(for key: CodingKey) throws -> _Decoder {
        return decoder.decoder(referencing: try object(for: key), as: key)
    }
}

