diff --git a/Sources/MaxMindDBReader/NumericDecoder.swift b/Sources/MaxMindDBReader/NumericDecoder.swift index 373e812..93a756b 100644 --- a/Sources/MaxMindDBReader/NumericDecoder.swift +++ b/Sources/MaxMindDBReader/NumericDecoder.swift @@ -13,12 +13,16 @@ class NumericDecoder { init(inputEndianness: Endianness) { self.input = inputEndianness } - private func pad(_ data: Data, byteCount: Int) -> Data { - let padBytes = Data(count: byteCount) - return input == .big ? padBytes + data : data + padBytes + private func padded(_ data: Data) -> T where T: FixedWidthInteger { + let byteCount = MemoryLayout.size - data.count + let padBytes = Data(count: byteCount) + var wellSizedData: Data = input == .big ? padBytes + data : data + padBytes + return UnsafeRawPointer(&wellSizedData).load(as: T.self) } - private func truncate(_ data: Data, byteCount: Int) -> Data { + private func truncated(_ data: Data) -> T where T: FixedWidthInteger { + let byteCount = MemoryLayout.size + let bounds = input == .big ? ( lower: data.limitedIndex(data.endIndex, offsetBy: -byteCount), @@ -28,22 +32,22 @@ class NumericDecoder { lower: data.startIndex, upper: data.limitedIndex(data.startIndex, offsetBy: byteCount) ) - return data.subdata(in: Range(uncheckedBounds: bounds)) + + var wellSizedData: Data = data.subdata(in: Range(uncheckedBounds: bounds)) + return UnsafeRawPointer(&wellSizedData).load(as: T.self) } private func unpack(_ data: Data) -> T where T: FixedWidthInteger { let strayBytes = MemoryLayout.size - data.count - var wellSizedData: Data - /// TODO : Move the unsafe raw pointer based type creation into truncate & pad. That way we can handle the php monkeys' integer signing problem switch strayBytes { case _ where strayBytes > 0: - wellSizedData = pad(data, byteCount: strayBytes) + return padded(data) case _ where strayBytes < 0: - wellSizedData = truncate(data, byteCount: MemoryLayout.size) + return truncated(data) default: - wellSizedData = data + var wellSizedData: Data = data + return UnsafeRawPointer(&wellSizedData).load(as: T.self) } - return UnsafeRawPointer(&wellSizedData).load(as: T.self) } func decode(_ data: Data) -> T where T: FixedWidthInteger {