in Sources/TSCUtility/BitstreamReader.swift [221:276]
mutating func readBlockInfoBlock(abbrevWidth: Int) throws {
var currentBlockID: UInt64?
while true {
switch try cursor.read(abbrevWidth) {
case Bitstream.AbbreviationID.endBlock.rawValue:
try cursor.advance(toBitAlignment: 32)
// FIXME: check expected length
return
case Bitstream.AbbreviationID.enterSubblock.rawValue:
throw Error.nestedBlockInBlockInfo
case Bitstream.AbbreviationID.defineAbbreviation.rawValue:
guard let blockID = currentBlockID else {
throw Error.missingSETBID
}
let numOps = Int(try cursor.readVBR(5))
if globalAbbrevs[blockID] == nil { globalAbbrevs[blockID] = [] }
globalAbbrevs[blockID]!.append(try readAbbrev(numOps: numOps))
case Bitstream.AbbreviationID.unabbreviatedRecord.rawValue:
let code = try cursor.readVBR(6)
let numOps = try cursor.readVBR(6)
var operands = [UInt64]()
for _ in 0..<numOps {
operands.append(try cursor.readVBR(6))
}
switch code {
case UInt64(Bitstream.BlockInfoCode.setBID.rawValue):
guard operands.count == 1 else { throw Error.invalidBlockInfoRecord(recordID: code) }
currentBlockID = operands.first
case UInt64(Bitstream.BlockInfoCode.blockName.rawValue):
guard let blockID = currentBlockID else {
throw Error.missingSETBID
}
if blockInfo[blockID] == nil { blockInfo[blockID] = BlockInfo() }
blockInfo[blockID]!.name = String(bytes: operands.map { UInt8($0) }, encoding: .utf8) ?? "<invalid>"
case UInt64(Bitstream.BlockInfoCode.setRecordName.rawValue):
guard let blockID = currentBlockID else {
throw Error.missingSETBID
}
if blockInfo[blockID] == nil { blockInfo[blockID] = BlockInfo() }
guard let recordID = operands.first else {
throw Error.invalidBlockInfoRecord(recordID: code)
}
blockInfo[blockID]!.recordNames[recordID] = String(bytes: operands.dropFirst().map { UInt8($0) }, encoding: .utf8) ?? "<invalid>"
default:
throw Error.invalidBlockInfoRecord(recordID: code)
}
case let abbrevID:
throw Error.noSuchAbbrev(blockID: 0, abbrevID: Int(abbrevID))
}
}
}