diff --git a/Sources/MaxMindDBReader/Decoder.swift b/Sources/MaxMindDBReader/Decoder.swift index 23bc2cc..43a9235 100644 --- a/Sources/MaxMindDBReader/Decoder.swift +++ b/Sources/MaxMindDBReader/Decoder.swift @@ -38,9 +38,17 @@ class Decoder { } } - func decode(_ data: Data) -> UInt16 { - var wellSizedData = unpack(data, toBytesLength: 2) - let value = UnsafeRawPointer(&wellSizedData).load(as: UInt16.self) + func decode(_ data: Data) -> T where T: FixedWidthInteger, T: UnsignedInteger { + var wellSizedData = unpack(data, toBytesLength: MemoryLayout.size) + let value = UnsafeRawPointer(&wellSizedData).load(as: T.self) return input == .big ? value.bigEndian : value.littleEndian } + + func decode(_ data: Data) -> T where T: FixedWidthInteger, T: SignedInteger { + var wellSizedData = unpack(data, toBytesLength: MemoryLayout.size) + let value = UnsafeRawPointer(&wellSizedData).load(as: T.self) + return input == .big ? value.bigEndian : value.littleEndian + } + } + diff --git a/Tests/MaxMindDBReaderTests/DecoderTest.swift b/Tests/MaxMindDBReaderTests/DecoderTest.swift index 566f6d6..bb1e88a 100644 --- a/Tests/MaxMindDBReaderTests/DecoderTest.swift +++ b/Tests/MaxMindDBReaderTests/DecoderTest.swift @@ -4,7 +4,7 @@ import XCTest fileprivate typealias TestSpec = (expected: T, input: Data) -fileprivate let testSpecs: [TestSpec] = [ +fileprivate let testSpecs_uInt16: [TestSpec] = [ (expected: 0, input: Data()), (expected: 0, input: Data(count: 1)), (expected: 0, input: Data(count: 2)), @@ -17,16 +17,106 @@ fileprivate let testSpecs: [TestSpec] = [ (expected: 14200, input: Data(count: 14) + Data([0b0011_0111, 0b0111_1000])) ] +fileprivate let testSpecs_uInt32: [TestSpec] = [ + (expected: 0, input: Data()), + (expected: 0, input: Data(count: 1)), + (expected: 0, input: Data(count: 2)), + (expected: 0, input: Data(count: 3)), + (expected: 0, input: Data(count: 4)), + (expected: 0, input: Data(count: 5)), + (expected: 4294967295, input: Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])), + (expected: 4294967295, input: Data(count: 1) + Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])), + (expected: 14200, input: Data([0b0011_0111, 0b0111_1000])), + (expected: 14200, input: Data(count: 14) + Data([0b0011_0111, 0b0111_1000])), + (expected: 16702650, input: Data([0xFE, 0xDC, 0xBA])), + (expected: 16702650, input: Data(count: 14) + Data([0xFE, 0xDC, 0xBA])) +] + +fileprivate let testSpecs_int32: [TestSpec] = [ + (expected: 0, input: Data()), + (expected: 0, input: Data(count: 1)), + (expected: 0, input: Data(count: 2)), + (expected: 0, input: Data(count: 3)), + (expected: 0, input: Data(count: 4)), + (expected: 0, input: Data(count: 5)), + (expected: -2147483647, input: Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])), + (expected: -2147483647, input: Data(count: 1) + Data([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])), + (expected: 2147483647, input: Data([0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])), + (expected: 2147483647, input: Data(count: 1) + Data([0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])), + (expected: 14200, input: Data([0b0011_0111, 0b0111_1000])), + (expected: 14200, input: Data(count: 14) + Data([0b0011_0111, 0b0111_1000])), + (expected: -14200, input: Data([0b1011_0111, 0b0111_1000])), + (expected: -14200, input: Data([0b1000_0000]) + Data(count: 13) + Data([0b0011_0111, 0b0111_1000])), + (expected: 16702650, input: Data([0xFE, 0xDC, 0xBA])), + (expected: 16702650, input: Data(count: 14) + Data([0xFE, 0xDC, 0xBA])) +] + +fileprivate let testSpecs_uInt64: [TestSpec] = [ + (expected: 0, input: Data()), + (expected: 0, input: Data(count: 1)), + (expected: 0, input: Data(count: 2)), + (expected: 0, input: Data(count: 3)), + (expected: 0, input: Data(count: 4)), + (expected: 0, input: Data(count: 5)), + (expected: 255, input: Data([0b1111_1111])), + (expected: 255, input: Data(count: 1) + Data([0b1111_1111])), + (expected: 14200, input: Data([0b0011_0111, 0b0111_1000])), + (expected: 14200, input: Data(count: 14) + Data([0b0011_0111, 0b0111_1000])), + (expected: 16702650, input: Data([0xFE, 0xDC, 0xBA])), + (expected: 16702650, input: Data(count: 14) + Data([0xFE, 0xDC, 0xBA])), + (expected: 280223976814164, input: Data([0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54])), + (expected: 280223976814164, input: Data(count: 14) + Data([0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54])) +] + class DecoderTest: XCTestCase { private let bigEndianDecoder = Decoder(inputEndianness: .big) private let littleEndianDecoder = Decoder(inputEndianness: .little) - func testDecode() { - for (expected, input) in testSpecs { + func testDecode_uInt16() { + for (expected, input) in testSpecs_uInt16 { assertDecodedValue(expected, bigEndianDecoder.decode, data: input) } - for (expected, input) in testSpecs { + for (expected, input) in testSpecs_uInt16 { + assertDecodedValue( + expected, + littleEndianDecoder.decode, + data: Data(input.reversed()) + ) + } + } + + func testDecode_uInt32() { + for (expected, input) in testSpecs_uInt32 { + assertDecodedValue(expected, bigEndianDecoder.decode, data: input) + } + for (expected, input) in testSpecs_uInt32 { + assertDecodedValue( + expected, + littleEndianDecoder.decode, + data: Data(input.reversed()) + ) + } + } + + func testDecode_uInt64() { + for (expected, input) in testSpecs_uInt64 { + assertDecodedValue(expected, bigEndianDecoder.decode, data: input) + } + for (expected, input) in testSpecs_uInt64 { + assertDecodedValue( + expected, + littleEndianDecoder.decode, + data: Data(input.reversed()) + ) + } + } + + func testDecode_int32() { + for (expected, input) in testSpecs_int32 { + assertDecodedValue(expected, bigEndianDecoder.decode, data: input) + } + for (expected, input) in testSpecs_int32 { assertDecodedValue( expected, littleEndianDecoder.decode,