1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
enum LEBError: Swift.Error, Equatable {
case overflow
case integerRepresentationTooLong
case insufficientBytes
}
extension FixedWidthInteger where Self: UnsignedInteger {
init(LEB nextByte: () -> UInt8?) throws {
var result: Self = 0
var shift: UInt = 0
var byte: UInt8
repeat {
byte = try {
guard let byte = nextByte() else {
throw LEBError.insufficientBytes
}
return byte
}()
guard shift < Self.bitWidth else {
throw LEBError.integerRepresentationTooLong
}
let slice = Self(byte & 0b0111_1111)
guard (slice << shift) >> shift == slice else {
throw LEBError.overflow
}
result |= slice << shift
shift += 7
} while byte & 0b1000_0000 != 0
self = result
}
}
extension FixedWidthInteger where Self: SignedInteger {
init(LEB nextByte: () -> UInt8?) throws {
var result: Self = 0
var shift: Self = 0
var byte: UInt8
repeat {
byte = try {
guard let byte = nextByte() else {
throw LEBError.insufficientBytes
}
return byte
}()
let slice = Self(byte & 0b0111_1111)
result |= slice << shift
// When we don't have enough bit width
if shift > (Self.bitWidth - 7) {
let remainingBitWidth = Self.bitWidth - Int(shift)
let continuationBit = (byte & 0b1000_0000) != 0
// When a next byte is expected
if continuationBit {
throw LEBError.integerRepresentationTooLong
}
let signAndDiscardingBits = Int8(bitPattern: byte << 1) >> remainingBitWidth
// When meaningful bits are discarded
if signAndDiscardingBits != 0 && signAndDiscardingBits != -1 {
throw LEBError.overflow
}
self = result
return
}
shift += 7
} while byte & 0b1000_0000 != 0
// Sign flag is second high-order bit
if byte & 0b0100_0000 != 0 {
// Sign extend
result |= Self(~0) << shift
}
self = result
}
}
|