In Swift 4:
There are a few things to consider when extracting an integer value from a Data stream. Signature and Endianse. So I came up with a function in the extension to Data that tells Signedness from the type of integer you want to extract, and passes Endianess and Index as parameters. The types of integers that can be extracted conform to the FixedWidthInteger protocol.
Reminder: This function does not check if the Index range is inside the boundaries of the Data buffer, so that it may crash depending on the size of the type being retrieved due to the end of the buffer.
extension Data { enum Endianness { case BigEndian case LittleEndian } func scanValue<T: FixedWidthInteger>(at index: Data.Index, endianess: Endianness) -> T { let number: T = self.subdata(in: index..<index + MemoryLayout<T>.size).withUnsafeBytes({ $0.pointee }) switch endianess { case .BigEndian: return number.bigEndian case .LittleEndian: return number.littleEndian } } }
Example:
let data = Data(bytes: [0xFF,0x1F,0x1F,0xFF]) let number1 = data.scanValue(at: 0, endianess: .LittleEndian) as UInt16 let number2 = data.scanValue(at: 0, endianess: .BigEndian) as UInt16 let number3: Int16 = data.scanValue(at: 2, endianess: .LittleEndian) let number4: Int16 = data.scanValue(at: 2, endianess: .BigEndian)
Results:
number1 is 8191
number2 is 65311
number3 is -225
number4 is 8191
Watch function calls to see how the type to be retrieved is inferred. Of course, Endianess doesn't make sense for Int8 or UInt8 , but the function works as expected.
Values ββcan later be added to Int if necessary.
Gustavo seidler
source share