From 4f937979a5c56eeb64e840125fade12af2b7488f Mon Sep 17 00:00:00 2001 From: Simon Whitty Date: Wed, 26 Jun 2024 16:50:00 +1000 Subject: [PATCH] Decode doubles as Int if exactly represented --- Sources/KeyValueDecoder.swift | 10 +++++++++- Tests/KeyValueDecoderTests.swift | 24 ++++++++++++++++++++---- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Sources/KeyValueDecoder.swift b/Sources/KeyValueDecoder.swift index 6c08430..65825d7 100644 --- a/Sources/KeyValueDecoder.swift +++ b/Sources/KeyValueDecoder.swift @@ -155,7 +155,15 @@ private extension KeyValueDecoder { throw DecodingError.typeMismatch(type, context) } return val - } else { + } else if let double = (value as? NSNumber)?.getDoubleValue() { + let val = T(double) + guard Double(val) == double else { + let context = DecodingError.Context(codingPath: codingPath, debugDescription: "\(valueDescription) at \(codingPath.makeKeyPath()), cannot be exactly represented by \(type)") + throw DecodingError.typeMismatch(type, context) + } + return val + } + else { let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Expected BinaryInteger at \(codingPath.makeKeyPath()), found \(valueDescription)") if decodeNil() { throw DecodingError.valueNotFound(type, context) diff --git a/Tests/KeyValueDecoderTests.swift b/Tests/KeyValueDecoderTests.swift index e381e1b..929a829 100644 --- a/Tests/KeyValueDecoderTests.swift +++ b/Tests/KeyValueDecoderTests.swift @@ -103,6 +103,14 @@ final class KeyValueDecoderTests: XCTestCase { try KeyValueDecoder.decode(Int16.self, from: NSNumber(10)), 10 ) + XCTAssertEqual( + try KeyValueDecoder.decode(Int16.self, from: 10.0), + 10 + ) + XCTAssertEqual( + try KeyValueDecoder.decode(Int16.self, from: NSNumber(10.0)), + 10 + ) XCTAssertThrowsError( try KeyValueDecoder.decode(Int8.self, from: Int16.max) ) @@ -129,6 +137,14 @@ final class KeyValueDecoderTests: XCTestCase { try KeyValueDecoder.decode(UInt8.self, from: NSNumber(10)), 10 ) + XCTAssertEqual( + try KeyValueDecoder.decode(UInt8.self, from: 10.0), + 10 + ) + XCTAssertEqual( + try KeyValueDecoder.decode(UInt8.self, from: NSNumber(10.0)), + 10 + ) XCTAssertThrowsError( try KeyValueDecoder.decode(UInt8.self, from: UInt16.max) ) @@ -480,8 +496,8 @@ final class KeyValueDecoderTests: XCTestCase { func testDecodes_UnkeyedInts() { XCTAssertEqual( - try KeyValueDecoder.decode([Int].self, from: [-10, 20, 30]), - [-10, 20, 30] + try KeyValueDecoder.decode([Int].self, from: [-10, 20, 30, 40.0, -50.0]), + [-10, 20, 30, 40, -50] ) XCTAssertEqual( try KeyValueDecoder.decode([Int8].self, from: [10, -20, 30]), @@ -610,8 +626,8 @@ final class KeyValueDecoderTests: XCTestCase { func testDecodes_UnkeyedUInts() { XCTAssertEqual( - try KeyValueDecoder.decode([UInt].self, from: [10, 20, 30]), - [10, 20, 30] + try KeyValueDecoder.decode([UInt].self, from: [10, 20, 30, 40.0]), + [10, 20, 30, 40] ) XCTAssertEqual( try KeyValueDecoder.decode([UInt8].self, from: [10, 20, 30]),