Returns the number of values followed by the bitsize of the extra bits.
fn buildClen(
dyn_bits: []const u4,
out_values: []u8,
out_extra: []u8,
out_freqs: *[19]u16,
) struct
fn buildClen(
dyn_bits: []const u4,
out_values: []u8,
out_extra: []u8,
out_freqs: *[19]u16,
) struct { u16, u16 } {
assert(dyn_bits.len <= out_values.len);
assert(out_values.len == out_extra.len);
var len: u16 = 0;
var extra_bitsize: u16 = 0;
var remaining_bits = dyn_bits;
var prev: u4 = 0;
while (true) {
const b = remaining_bits[0];
const n_max = @min(@as(u8, if (b != 0)
if (b != prev) 1 else 6
else
138), remaining_bits.len);
prev = b;
var n: u8 = 0;
while (true) {
remaining_bits = remaining_bits[1..];
n += 1;
if (n == n_max or remaining_bits[0] != b) break;
}
const code, const extra, const xsize = switch (n) {
0 => unreachable,
1...2 => .{ b, 0, 0 },
3...10 => .{
@as(u8, 16) + @intFromBool(b == 0),
n - 3,
@as(u8, 2) + @intFromBool(b == 0),
},
11...138 => .{ 18, n - 11, 7 },
else => unreachable,
};
while (true) {
out_values[len] = code;
out_extra[len] = extra;
out_freqs[code] += 1;
extra_bitsize += xsize;
len += 1;
if (n != 2) {
@branchHint(.likely);
break;
}
// Code needs outputted once more
n = 1;
}
if (remaining_bits.len == 0) break;
}
return .{ len, extra_bitsize };
}