in Sources/TSCUtility/BitstreamReader.swift [278:338]
mutating func readBlock<Visitor: BitstreamVisitor>(id: UInt64, abbrevWidth: Int, abbrevInfo: [Bitstream.Abbreviation], visitor: inout Visitor) throws {
var abbrevInfo = abbrevInfo
while !cursor.isAtEnd {
switch try cursor.read(abbrevWidth) {
case Bitstream.AbbreviationID.endBlock.rawValue:
try cursor.advance(toBitAlignment: 32)
// FIXME: check expected length
try visitor.didExitBlock()
return
case Bitstream.AbbreviationID.enterSubblock.rawValue:
let blockID = try cursor.readVBR(8)
let newAbbrevWidth = Int(try cursor.readVBR(4))
try cursor.advance(toBitAlignment: 32)
let blockLength = try cursor.read(32) * 4
switch blockID {
case 0:
try readBlockInfoBlock(abbrevWidth: newAbbrevWidth)
case 1...7:
// Metadata blocks we don't understand yet
fallthrough
default:
guard try visitor.shouldEnterBlock(id: blockID) else {
try cursor.skip(bytes: Int(blockLength))
break
}
try readBlock(
id: blockID, abbrevWidth: newAbbrevWidth,
abbrevInfo: globalAbbrevs[blockID] ?? [], visitor: &visitor)
}
case Bitstream.AbbreviationID.defineAbbreviation.rawValue:
let numOps = Int(try cursor.readVBR(5))
abbrevInfo.append(try readAbbrev(numOps: numOps))
case Bitstream.AbbreviationID.unabbreviatedRecord.rawValue:
let code = try cursor.readVBR(6)
let numOps = try cursor.readVBR(6)
let operands = UnsafeMutableBufferPointer<UInt64>.allocate(capacity: Int(numOps))
defer { operands.deallocate() }
for i in 0..<Int(numOps) {
operands[i] = try cursor.readVBR(6)
}
try visitor.visit(record: .init(id: code, fields: UnsafeBufferPointer(operands), payload: .none))
case let abbrevID:
guard Int(abbrevID) - 4 < abbrevInfo.count else {
throw Error.noSuchAbbrev(blockID: id, abbrevID: Int(abbrevID))
}
try withAbbreviatedRecord(abbrevInfo[Int(abbrevID) - 4]) { record in
try visitor.visit(record: record)
}
}
}
guard id == Self.fakeTopLevelBlockID else {
throw Error.missingEndBlock(blockID: id)
}
}