struct Header [src]
Fields
descriptor: Descriptor
window_descriptor: ?u8
dictionary_id: ?u32
content_size: ?u64
Members
- decode (Function)
- DecodeError (Error Set)
- Descriptor (struct)
- windowSize (Function)
Source
pub const Header = struct {
descriptor: Descriptor,
window_descriptor: ?u8,
dictionary_id: ?u32,
content_size: ?u64,
pub const Descriptor = packed struct {
dictionary_id_flag: u2,
content_checksum_flag: bool,
reserved: bool,
unused: bool,
single_segment_flag: bool,
content_size_flag: u2,
};
pub const DecodeError = Reader.Error || error{ReservedBitSet};
pub fn decode(in: *Reader) DecodeError!Header {
const descriptor: Descriptor = @bitCast(try in.takeByte());
if (descriptor.reserved) return error.ReservedBitSet;
const window_descriptor: ?u8 = if (descriptor.single_segment_flag) null else try in.takeByte();
const dictionary_id: ?u32 = if (descriptor.dictionary_id_flag > 0) d: {
// if flag is 3 then field_size = 4, else field_size = flag
const field_size = (@as(u4, 1) << descriptor.dictionary_id_flag) >> 1;
break :d try in.takeVarInt(u32, .little, field_size);
} else null;
const content_size: ?u64 = if (descriptor.single_segment_flag or descriptor.content_size_flag > 0) c: {
const field_size = @as(u4, 1) << descriptor.content_size_flag;
const content_size = try in.takeVarInt(u64, .little, field_size);
break :c if (field_size == 2) content_size + 256 else content_size;
} else null;
return .{
.descriptor = descriptor,
.window_descriptor = window_descriptor,
.dictionary_id = dictionary_id,
.content_size = content_size,
};
}
/// Returns the window size required to decompress a frame, or `null` if it
/// cannot be determined (which indicates a malformed frame header).
pub fn windowSize(header: Header) ?u64 {
if (header.window_descriptor) |descriptor| {
const exponent = (descriptor & 0b11111000) >> 3;
const mantissa = descriptor & 0b00000111;
const window_log = 10 + exponent;
const window_base = @as(u64, 1) << @as(u6, @intCast(window_log));
const window_add = (window_base / 8) * mantissa;
return window_base + window_add;
} else return header.content_size;
}
}