feature. See also
. The project being documented here (as the example) is the Zig library itself.
BitcodeReader.nextRecord
fn nextRecord(bc: *BitcodeReader) !?Record
File
Code
fn nextRecord(bc: *BitcodeReader) !?Record {
const state = &bc.stack.items[bc.stack.items.len - 1];
const abbrev_id = bc.readFixed(u32, state.abbrev_id_width) catch |err| switch (err) {
error.EndOfStream => return null,
else => |e| return e,
};
if (abbrev_id >= state.abbrevs.abbrevs.items.len) return error.InvalidAbbrevId;
const abbrev = state.abbrevs.abbrevs.items[abbrev_id];
var record_arena = bc.record_arena.promote(bc.allocator);
defer bc.record_arena = record_arena.state;
_ = record_arena.reset(.retain_capacity);
var operands = try std.array_list.Managed(u64).initCapacity(record_arena.allocator(), abbrev.operands.len);
var blob = std.array_list.Managed(u8).init(record_arena.allocator());
for (abbrev.operands, 0..) |abbrev_operand, abbrev_operand_i| switch (abbrev_operand) {
.literal => |value| operands.appendAssumeCapacity(value),
.encoding => |abbrev_encoding| switch (abbrev_encoding) {
.fixed => |width| operands.appendAssumeCapacity(try bc.readFixed(u64, width)),
.vbr => |width| operands.appendAssumeCapacity(try bc.readVbr(u64, width)),
.array => |len_width| {
assert(abbrev_operand_i + 2 == abbrev.operands.len);
const len: usize = @intCast(try bc.readVbr(u32, len_width));
try operands.ensureUnusedCapacity(len);
for (0..len) |_| switch (abbrev.operands[abbrev.operands.len - 1]) {
.literal => |elem_value| operands.appendAssumeCapacity(elem_value),
.encoding => |elem_encoding| switch (elem_encoding) {
.fixed => |elem_width| operands.appendAssumeCapacity(try bc.readFixed(u64, elem_width)),
.vbr => |elem_width| operands.appendAssumeCapacity(try bc.readVbr(u64, elem_width)),
.array, .blob => return error.InvalidArrayElement,
.char6 => operands.appendAssumeCapacity(try bc.readChar6()),
},
.align_32_bits, .block_len => return error.UnsupportedArrayElement,
.abbrev_op => switch (try bc.readFixed(u1, 1)) {
1 => try operands.appendSlice(&.{
Abbrev.Operand.literal_id,
try bc.readVbr(u64, 8),
}),
0 => {
const encoding: Abbrev.Operand.Encoding =
@fromBackingInt(@intCast(try bc.readFixed(u3, 3)));
try operands.append(@backingInt(encoding));
switch (encoding) {
.fixed, .vbr => try operands.append(try bc.readVbr(u7, 5)),
.array, .char6, .blob => {},
_ => return error.UnsuportedAbbrevEncoding,
}
},
},
};
break;
},
.char6 => operands.appendAssumeCapacity(try bc.readChar6()),
.blob => |len_width| {
assert(abbrev_operand_i + 1 == abbrev.operands.len);
const len = std.math.cast(usize, try bc.readVbr(u32, len_width)) orelse
return error.Overflow;
bc.align32Bits();
try bc.readBytes(try blob.addManyAsSlice(len));
bc.align32Bits();
},
},
.align_32_bits => bc.align32Bits(),
.block_len => operands.appendAssumeCapacity(try bc.read32Bits()),
.abbrev_op => unreachable,
};
return .{
.name = name: {
if (operands.items.len < 1) break :name &.{};
const record_id = std.math.cast(u32, operands.items[0]) orelse break :name &.{};
if (state.block_id) |block_id| {
if (bc.block_info.get(block_id)) |block_info| {
break :name block_info.record_names.get(record_id) orelse break :name &.{};
}
}
break :name &.{};
},
.id = std.math.cast(u32, operands.items[0]) orelse return error.InvalidRecordId,
.operands = operands.items[1..],
.blob = blob.items,
};
}