mod error;
mod input;
mod primitives;
pub use error::*;
pub use input::*;
use primitives::*;
use crate::table::Table;
#[derive(Debug)]
pub struct Encoder<'a> {
table: Table<'a>,
}
impl<'a> Encoder<'a> {
pub const HUFFMAN_NAME: u8 = 0x1;
pub const HUFFMAN_VALUE: u8 = 0x2;
pub const WITH_INDEXING: u8 = 0x4;
pub const NEVER_INDEXED: u8 = 0x8;
pub const BEST_FORMAT: u8 = 0x10;
pub fn with_dynamic_size(max_dynamic_size: u32) -> Self {
Self {
table: Table::with_dynamic_size(max_dynamic_size),
}
}
pub fn max_dynamic_size(&mut self) -> u32 {
self.table.max_dynamic_size()
}
pub fn encode<F>(
&mut self,
field: F,
dst: &mut Vec<u8>,
) -> Result<(), EncoderError>
where
F: Into<EncoderInput>,
{
match field.into() {
EncoderInput::Indexed(index) => {
self.encode_indexed(index, dst)
},
EncoderInput::IndexedName(index, value, flags) => {
self.encode_indexed_name(index, value, flags, dst)
},
EncoderInput::Literal(name, value, flags) => {
if flags & 0x10 == 0x10 {
match self.table.find(&name, &value) {
Some((index, true)) => {
self.encode_indexed(index as u32, dst)
},
Some((index, false)) => {
self.encode_indexed_name(index as u32, value, flags, dst)
},
None => {
self.encode_literal(name, value, flags, dst)
},
}
} else {
self.encode_literal(name, value, flags, dst)
}
},
}
}
pub fn encode_indexed(
&self,
index: u32,
dst: &mut Vec<u8>,
) -> Result<(), EncoderError> {
if self.table.get(index).is_none() {
return Err(EncoderError::InvalidIndex);
}
encode_integer(index, 0x80, 7, dst)
}
pub fn encode_indexed_name(
&mut self,
index: u32,
value: Vec<u8>,
flags: u8,
dst: &mut Vec<u8>,
) -> Result<(), EncoderError> {
let name = if let Some(entry) = self.table.get(index) {
entry.0.to_vec()
} else {
return Err(EncoderError::InvalidIndex);
};
if flags & 0x4 == 0x4 {
self.table.insert(name, value.clone());
encode_integer(index, 0x40, 6, dst)?;
} else if flags & 0x8 == 0x8 {
encode_integer(index, 0b00010000, 4, dst)?;
} else { encode_integer(index, 0x0, 4, dst)?;
}
encode_string(value, flags & 0x2 == 0x2, dst)
}
pub fn encode_literal(
&mut self,
name: Vec<u8>,
value: Vec<u8>,
flags: u8,
dst: &mut Vec<u8>,
) -> Result<(), EncoderError> {
if flags & 0x4 == 0x4 {
dst.push(0x40);
self.table.insert(name.clone(), value.clone());
} else if flags & 0x8 == 0x8 {
dst.push(0b00010000);
} else { dst.push(0x0);
}
encode_string(name, flags & 0x1 == 0x1, dst)?;
encode_string(value, flags & 0x2 == 0x2, dst)
}
pub fn update_max_dynamic_size(
&mut self,
size: u32,
dst: &mut Vec<u8>,
) -> Result<(), EncoderError> {
self.table.update_max_dynamic_size(size);
encode_integer(size, 0b00100000, 5, dst)
}
}
impl<'a> Default for Encoder<'a> {
fn default() -> Self {
Self {
table: Table::default(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn encodes_indexed() {
let mut encoder = Encoder::default();
encoder.table.insert(b"name62".to_vec(), b"value62".to_vec()); let fields = vec![
(2, vec![0x80 | 2]), (3, vec![0x80 | 3]), (14, vec![0x80 | 14]), (62, vec![0x80 | 62]), ];
for (index, res) in fields {
let mut dst = Vec::new();
encoder.encode(index, &mut dst).unwrap();
assert_eq!(dst, res);
}
assert_eq!(encoder.table.len(), 62); }
#[test]
fn encodes_indexed_name_with_indexing() {
let mut encoder = Encoder::default();
let mut dst = Vec::new();
let field = (
2, b"PATCH".to_vec(),
0x2 | 0x4,
);
encoder.encode(field, &mut dst).unwrap(); assert_eq!(dst[0] & 0b01000000, 64); assert_eq!(dst[1] & 0b10000000, 128); assert_eq!(&dst[2..], vec![215, 14, 251, 216, 255]); assert_eq!(encoder.table.len(), 62); let entry = encoder.table.get(62).unwrap();
assert_eq!(entry.0, b":method"); assert_eq!(entry.1, b"PATCH"); }
#[test]
fn encodes_literal_with_indexing() {
let mut encoder = Encoder::default();
let mut dst = Vec::new();
let field = (
b"foo".to_vec(),
b"bar".to_vec(),
0x4 | 0x1 | 0x2,
);
encoder.encode(field, &mut dst).unwrap(); assert_eq!(dst[0], 0b01000000); assert_eq!(&dst[1..4], vec![130, 148, 231]); assert_eq!(&dst[4..], vec![131, 140, 118, 127]); assert_eq!(encoder.table.len(), 62); let entry = encoder.table.get(62).unwrap();
assert_eq!(entry.0, b"foo"); assert_eq!(entry.1, b"bar"); }
#[test]
fn encodes_indexed_name_without_indexing() {
let mut encoder = Encoder::default();
let mut dst = Vec::new();
let field = (13, b"PATCH".to_vec(), 0x0);
encoder.encode(field, &mut dst).unwrap(); assert_eq!(dst[0], 13); assert_eq!(&dst[1..], vec![5, 80, 65, 84, 67, 72]); assert_eq!(encoder.table.len(), 61); }
#[test]
fn encodes_literal_without_indexing() {
let mut encoder = Encoder::default();
let mut dst = Vec::new();
let field = (b"foo".to_vec(), b"bar".to_vec(), 0x1);
encoder.encode(field, &mut dst).unwrap(); assert_eq!(dst[0], 0); assert_eq!(&dst[2..4], vec![148, 231]); assert_eq!(&dst[4..], vec![3, 98, 97, 114]); assert_eq!(encoder.table.len(), 61); }
#[test]
fn encodes_indexed_name_never_indexed() {
let mut encoder = Encoder::default();
let mut dst = Vec::new();
let field = (13, b"PATCH".to_vec(), 0x8);
encoder.encode(field, &mut dst).unwrap(); assert_eq!(dst[0] & 0b00010000, 16); assert_eq!(&dst[1..], vec![5, 80, 65, 84, 67, 72]); assert_eq!(encoder.table.len(), 61); }
#[test]
fn encodes_literal_never_indexed() {
let mut encoder = Encoder::default();
let mut dst = Vec::new();
let field = (b"foo".to_vec(), b"bar".to_vec(), 0x8);
encoder.encode(field, &mut dst).unwrap(); assert_eq!(dst[0], 0b00010000); assert_eq!(&dst[1..5], vec![3, 102, 111, 111]); assert_eq!(&dst[5..], vec![3, 98, 97, 114]); assert_eq!(encoder.table.len(), 61); }
#[test]
fn encodes_literal_automatically() {
let mut encoder = Encoder::default();
let fields = vec![
((b":method".to_vec(), b"GET".to_vec(), 0x10), vec![130]), ((b":method".to_vec(), b"DELETE".to_vec(), 0x10 | 0x4), vec![66, 6, 68, 69, 76, 69, 84, 69]), ((b"a".to_vec(), b"b".to_vec(), 0x10 | 0x1), vec![0, 129, 31, 1, 98]), ];
for (field, res) in fields {
let mut dst = Vec::new();
encoder.encode(field, &mut dst).unwrap();
assert_eq!(dst, res);
}
assert_eq!(encoder.table.len(), 62); }
#[test]
fn updates_max_dynamic_size() {
let mut encoder = Encoder::with_dynamic_size(70);
encoder.table.insert(b"a".to_vec(), b"a".to_vec()); encoder.table.insert(b"b".to_vec(), b"b".to_vec()); let mut dst = Vec::new();
encoder.update_max_dynamic_size(50, &mut dst).unwrap();
assert_eq!(dst[0] & 0b00100000, 32); assert_eq!(dst, vec![63, 19]); assert_eq!(encoder.table.dynamic_len(), 1); }
}