     }
     
     func decode(_ type: Int.Type, forKey key: K) throws -> Int {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.intDecodingStrategy)
+        return try self.decoder.settings.intDecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: Int8.Type, forKey key: K) throws -> Int8 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.int8DecodingStrategy)
+        return try self.decoder.settings.int8DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: Int16.Type, forKey key: K) throws -> Int16 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.int16DecodingStrategy)
+        return try self.decoder.settings.int16DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: Int32.Type, forKey key: K) throws -> Int32 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.int32DecodingStrategy)
+        return try self.decoder.settings.int32DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: Int64.Type, forKey key: K) throws -> Int64 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.int64DecodingStrategy)
+        return try self.decoder.settings.int64DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: UInt.Type, forKey key: K) throws -> UInt {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.uintDecodingStrategy)
+        return try self.decoder.settings.uintDecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: UInt8.Type, forKey key: K) throws -> UInt8 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.uint8DecodingStrategy)
+        return try self.decoder.settings.uint8DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: UInt16.Type, forKey key: K) throws -> UInt16 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.uint16DecodingStrategy)
+        return try self.decoder.settings.uint16DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: UInt32.Type, forKey key: K) throws -> UInt32 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.uint32DecodingStrategy)
+        return try self.decoder.settings.uint32DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode(_ type: UInt64.Type, forKey key: K) throws -> UInt64 {
-        return try decodeInteger(type, forKey: key, strategy: self.decoder.settings.uint64DecodingStrategy)
+        return try self.decoder.settings.uint64DecodingStrategy.decode(from: self.decoder, forKey: key, path: path(forKey: key))
     }
     
     func decode<T>(_ type: T.Type, forKey key: K) throws -> T where T : Decodable {
-        fatalError()
-    }
-    
-    public func decodeInteger<I: FixedWidthInteger>(
-        _ type: I.Type,
-        forKey key: K,
-        strategy: BSONDecoderSettings.IntegerDecodingStrategy<I>
-    ) throws -> I {
-        switch strategy {
-        case .string:
-            let string = try self.decode(String.self, forKey: key)
-            
-            if I.isSigned {
-                guard let int = Int64(string) else {
-                    throw BSONTypeConversionError(from: string, to: I.self)
-                }
-                
-                return numericCast(int)
-            } else {
-                guard let int = UInt64(string) else {
-                    throw BSONTypeConversionError(from: string, to: I.self)
-                }
-                
-                return numericCast(int)
-            }
-        case .int32:
-            return try self.decode(Int32.self, forKey: key).convert(to: I.self)
-        case .int64:
-            return try self.decode(Int64.self, forKey: key).convert(to: I.self)
-        case .anyInteger, .roundingAnyNumber:
-            guard let type = document.typeIdentifier(of: key.stringValue) else {
-                throw BSONValueNotFound(type: I.self, path: self.path(forKey: key))
-            }
-            
-            switch (type, strategy) {
-            case (.int32, _):
-                return try self.decode(Int32.self, forKey: key).convert(to: I.self)
-            case (.int64, _):
-                // Necessary also for custom integer types
-                return try self.decode(Int64.self, forKey: key).convert(to: I.self)
-            case (.double, .roundingAnyNumber):
-                let double = try self.decode(Double.self, forKey: key)
-                
-                return I(double)
-            default:
-                throw BSONTypeConversionError(from: document[key.stringValue], to: I.self)
-            }
-        case .custom(let strategy):
-            guard let value: I = try strategy(self.document[key.stringValue]) else {
-                throw BSONValueNotFound(type: I.self, path: self.path(forKey: key))
-            }
-            
-            return value
-        }
+        <#code#>
     }
     
     func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: K) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {

        fileprivate func decode(from value: DecoderValue, path: [String]) throws -> Float {
            switch self {
            case .double:
                let double = try value.decode(asType: Double.self, path: path)
                return Float(double)
            case .string:
                let string	 = try value.decode(asType: String.self, path: path)
                
                guard let float = Float(string) else {
                    throw BSONValueNotFound(type: Float.self, path: path)

        case .nothing:
            return nil
        }
    }
    
    func unwrap<P: Primitive, K: CodingKey>(asType type: P.Type, atKey key: K, path: [String]) throws -> P {
