Source code

Revision control

Copy as Markdown

Other Tools

// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[derive(Copy, Clone, Debug)]
pub struct Prefix {
#[allow(unknown_lints)] // available with Rust v1.75
#[allow(clippy::struct_field_names)]
prefix: u8,
len: u8,
mask: u8,
}
impl Prefix {
pub fn new(prefix: u8, len: u8) -> Self {
// len should never be larger than 7.
// Most of Prefixes are instantiated as consts bellow. The only place where this
// construcrtor is used is in tests and when literals are encoded and the Huffman
// bit is added to one of the consts bellow. create_prefix guaranty that all const
// have len < 7 so we can safely assert that len is <=7.
assert!(len <= 7);
assert!((len == 0) || (prefix & ((1 << (8 - len)) - 1) == 0));
Self {
prefix,
len,
mask: if len == 0 {
0xFF
} else {
((1 << len) - 1) << (8 - len)
},
}
}
pub fn len(self) -> u8 {
self.len
}
pub fn prefix(self) -> u8 {
self.prefix
}
pub fn cmp_prefix(self, b: u8) -> bool {
(b & self.mask) == self.prefix
}
}
#[macro_export]
macro_rules! create_prefix {
($n:ident) => {
pub const $n: Prefix = Prefix {
prefix: 0x0,
len: 0,
mask: 0xFF,
};
};
($n:ident, $v:expr, $l:expr) => {
static_assertions::const_assert!($l < 7);
static_assertions::const_assert!($v & ((1 << (8 - $l)) - 1) == 0);
pub const $n: Prefix = Prefix {
prefix: $v,
len: $l,
mask: ((1 << $l) - 1) << (8 - $l),
};
};
($n:ident, $v:expr, $l:expr, $m:expr) => {
static_assertions::const_assert!($l < 7);
static_assertions::const_assert!($v & ((1 << (8 - $l)) - 1) == 0);
static_assertions::const_assert!((((1 << $l) - 1) << (8 - $l)) >= $m);
pub const $n: Prefix = Prefix {
prefix: $v,
len: $l,
mask: $m,
};
};
}
create_prefix!(NO_PREFIX);
//=====================================================================
// Decoder instructions prefix
//=====================================================================
// | 1 | Stream ID (7+) |
create_prefix!(DECODER_HEADER_ACK, 0x80, 1);
// | 0 | 1 | Stream ID (6+) |
create_prefix!(DECODER_STREAM_CANCELLATION, 0x40, 2);
// | 0 | 0 | Increment (6+) |
create_prefix!(DECODER_INSERT_COUNT_INCREMENT, 0x00, 2);
//=====================================================================
// Encoder instructions prefix
//=====================================================================
// | 0 | 0 | 1 | Capacity (5+) |
create_prefix!(ENCODER_CAPACITY, 0x20, 3);
// | 1 | T | Name Index (6+) |
// T == 1 static
// T == 0 dynamic
create_prefix!(ENCODER_INSERT_WITH_NAME_REF_STATIC, 0xC0, 2);
create_prefix!(ENCODER_INSERT_WITH_NAME_REF_DYNAMIC, 0x80, 2);
// | 0 | 1 | H | Name Length (5+) |
// H is not relevant for decoding this prefix, therefore the mask is 1100 0000 = 0xC0
create_prefix!(ENCODER_INSERT_WITH_NAME_LITERAL, 0x40, 2);
// | 0 | 0 | 0 | Index (5+) |
create_prefix!(ENCODER_DUPLICATE, 0x00, 3);
//=====================================================================
// Header block encoding prefixes
//=====================================================================
create_prefix!(BASE_PREFIX_POSITIVE, 0x00, 1);
create_prefix!(BASE_PREFIX_NEGATIVE, 0x80, 1);
// | 1 | T | index(6+) |
// T == 1 static
// T == 0 dynamic
create_prefix!(HEADER_FIELD_INDEX_STATIC, 0xC0, 2);
create_prefix!(HEADER_FIELD_INDEX_DYNAMIC, 0x80, 2);
// | 0 | 0 | 0 | 1 | Index(4+) |
create_prefix!(HEADER_FIELD_INDEX_DYNAMIC_POST, 0x10, 4);
// | 0 | 1 | N | T | Index(4+) |
// T == 1 static
// T == 0 dynamic
// N is ignored, therefore the mask is 1101 0000 = 0xD0
create_prefix!(HEADER_FIELD_LITERAL_NAME_REF_STATIC, 0x50, 4, 0xD0);
create_prefix!(HEADER_FIELD_LITERAL_NAME_REF_DYNAMIC, 0x40, 4, 0xD0);
// | 0 | 0 | 0 | 0 | N | Index(3+) |
// N is ignored, therefore the mask is 1111 0000 = 0xF0
create_prefix!(HEADER_FIELD_LITERAL_NAME_REF_DYNAMIC_POST, 0x00, 5, 0xF0);
// | 0 | 0 | 1 | N | H | Index(3+) |
// N is ignored and H is not relevant for decoding this prefix, therefore the mask is 1110 0000 =
// 0xE0
create_prefix!(HEADER_FIELD_LITERAL_NAME_LITERAL, 0x20, 4, 0xE0);