diff --git a/Sources/BSON/Codable/Decoding/BSONDecoder.swift b/Sources/BSON/Codable/Decoding/BSONDecoder.swift index 8e88ef7..fd90359 100644 --- a/Sources/BSON/Codable/Decoding/BSONDecoder.swift +++ b/Sources/BSON/Codable/Decoding/BSONDecoder.swift @@ -138,6 +138,13 @@ extension BSONDecoderSettings.IntegerDecodingStrategy { case (let int as Int, _): return try int.convert(to: I.self) case (let double as Double, .roundingAnyNumber), (let double as Double, .adaptive): + guard + double >= Double(I.min), + double <= Double(I.max) + else { + throw DecodingError.typeMismatch(Double.self, .init(codingPath: [], debugDescription: "The IntegerDecodingStrategy is adaptive, but the Double could not be converted to \(I.self)")) + } + return I(double) case (let string as String, .adaptive): guard let int = I(string) else { @@ -177,6 +184,13 @@ extension BSONDecoderSettings.IntegerDecodingStrategy { case (.int64, let int as Int), (.adaptive, let int as Int), (.anyInteger, let int as Int), (.roundingAnyNumber, let int as Int): return try int.convert(to: I.self) case (.roundingAnyNumber, let double as Double), (.adaptive, let double as Double): + guard + double >= Double(I.min), + double <= Double(I.max) + else { + throw DecodingError.typeMismatch(Double.self, .init(codingPath: [], debugDescription: "The IntegerDecodingStrategy is adaptive, but the Double could not be converted to \(I.self)")) + } + return I(double) case (.custom(let strategy), _): guard let value: I = try strategy(key, value) else { diff --git a/Sources/BSON/Codable/Decoding/Fast/FastBSONDecoder.swift b/Sources/BSON/Codable/Decoding/Fast/FastBSONDecoder.swift index 487af88..7d4c868 100644 --- a/Sources/BSON/Codable/Decoding/Fast/FastBSONDecoder.swift +++ b/Sources/BSON/Codable/Decoding/Fast/FastBSONDecoder.swift @@ -116,8 +116,18 @@ struct _FastKeyedContainer: KeyedDecodingContainerProtocol { } return F(int) + case .double: + guard + let double = document.storage.getDouble(at: offset), + double >= Double(F.min), + double <= Double(F.max) + else { + throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue) + [key.stringValue]) + } + + return F(double) default: - throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue)) + throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue) + [key.stringValue]) } } @@ -127,7 +137,7 @@ struct _FastKeyedContainer: KeyedDecodingContainerProtocol { type == .boolean, let int: UInt8 = document.storage.getInteger(at: offset, endianness: .little) else { - throw BSONValueNotFound(type: Bool.self, path: codingPath.map(\.stringValue)) + throw BSONValueNotFound(type: Bool.self, path: codingPath.map(\.stringValue) + [key.stringValue]) } return int == 0x01 @@ -139,7 +149,7 @@ struct _FastKeyedContainer: KeyedDecodingContainerProtocol { type == .string, let string = document.storage.getBSONString(at: offset) else { - throw BSONValueNotFound(type: String.self, path: codingPath.map(\.stringValue)) + throw BSONValueNotFound(type: String.self, path: codingPath.map(\.stringValue) + [key.stringValue]) } return string @@ -151,7 +161,7 @@ struct _FastKeyedContainer: KeyedDecodingContainerProtocol { type == .double, let double = document.storage.getDouble(at: offset) else { - throw BSONValueNotFound(type: Double.self, path: codingPath.map(\.stringValue)) + throw BSONValueNotFound(type: String.self, path: codingPath.map(\.stringValue) + [key.stringValue]) } return double @@ -690,6 +700,16 @@ struct _FastUnkeyedContainer: UnkeyedDecodingContainer { currentIndex += 1 return F(int) + case .double: + guard + let double = document.storage.getDouble(at: offset), + double >= Double(F.min), + double <= Double(F.max) + else { + throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue)) + } + + return F(double) default: throw BSONValueNotFound(type: F.self, path: codingPath.map(\.stringValue)) }