From bee57f211ab72a7fbec2172b3900117e06a7b56e Mon Sep 17 00:00:00 2001 From: Adam Rocska Date: Mon, 4 May 2020 10:44:41 +0200 Subject: [PATCH] Last try before dumping & preconditioning: Moved the typed value contruction into the padding & truncating functions. Here the integer signed cases could be handled properly. Signed-off-by: Adam Rocska --- Sources/MaxMindDBReader/NumericDecoder.swift | 26 +++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) 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 {