Skip to main content
added 187 characters in body
Source Link
Martin R
  • 23.5k
  • 2
  • 36
  • 92
mutating func consume<T: FixedWidthInteger>FixedWidthInteger & UnsignedInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    defer { idx += size }
    return bytes[idx..<idx + size].enumerated().reduce(0) {
        $0 + T($1.element) << (8 * $1.offset)
    }
}

which can be used for all signed and unsigned integer types (U)IntUInt, (U)Int8UInt8, ..., (U)Int64UInt64, e.g.

let header: UInt8 = try buffer.consume()

and for the signed integer types via the bitPattern: initializer, e.g.

let word = try! Int16(bitPattern: buffer.consume())
mutating func consume<T: FixedWidthInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    defer { idx += size }
    return bytes[idx..<idx + size].enumerated().reduce(0) {
        $0 + T($1.element) << (8 * $1.offset)
    }
}

which can be used for all signed and unsigned integer types (U)Int, (U)Int8, ..., (U)Int64.

mutating func consume<T: FixedWidthInteger & UnsignedInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    defer { idx += size }
    return bytes[idx..<idx + size].enumerated().reduce(0) {
        $0 + T($1.element) << (8 * $1.offset)
    }
}

which can be used for all unsigned integer types UInt, UInt8, ..., UInt64, e.g.

let header: UInt8 = try buffer.consume()

and for the signed integer types via the bitPattern: initializer, e.g.

let word = try! Int16(bitPattern: buffer.consume())
added 494 characters in body
Source Link
Martin R
  • 23.5k
  • 2
  • 36
  • 92

Another option is to copy the bytes into a value of the desired type instead of bit shifting and adding:

mutating func consume<T: FixedWidthInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    var value: T = 0
    bytes.withUnsafeBytes { _ = memcpy(&value, $0.baseAddress! + idx, size) }
    idx += size
    return T(littleEndian: value)
}

Another option is to copy the bytes into a value of the desired type instead of bit shifting and adding:

mutating func consume<T: FixedWidthInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    var value: T = 0
    bytes.withUnsafeBytes { _ = memcpy(&value, $0.baseAddress! + idx, size) }
    idx += size
    return T(littleEndian: value)
}
FixedWidthInteger is more appropriate.
Source Link
Martin R
  • 23.5k
  • 2
  • 36
  • 92
mutating func consume<T: BinaryInteger>FixedWidthInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    defer { idx += size }
    return bytes[idx..<idx + size].enumerated().reduce(0) {
        $0 + T($1.element) << (8 * $1.offset)
    }
}
mutating func consume<T: BinaryInteger>FixedWidthInteger>(_: T.Type) throws -> T { ... }
mutating func consume<T: BinaryInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    defer { idx += size }
    return bytes[idx..<idx + size].enumerated().reduce(0) {
        $0 + T($1.element) << (8 * $1.offset)
    }
}
mutating func consume<T: BinaryInteger>(_: T.Type) throws -> T { ... }
mutating func consume<T: FixedWidthInteger>() throws -> T {
    let size = MemoryLayout<T>.size
    guard idx + size <= bytes.count else {
        throw Error.notEnoughBytes
    }
    defer { idx += size }
    return bytes[idx..<idx + size].enumerated().reduce(0) {
        $0 + T($1.element) << (8 * $1.offset)
    }
}
mutating func consume<T: FixedWidthInteger>(_: T.Type) throws -> T { ... }
added 350 characters in body
Source Link
Martin R
  • 23.5k
  • 2
  • 36
  • 92
Loading
Source Link
Martin R
  • 23.5k
  • 2
  • 36
  • 92
Loading