use super::*;
pub(crate) fn decode_integer(buf: &[u8], val: &mut u32, prefix_size: u8) -> Result<usize, DecoderError> {
if prefix_size < 1 || prefix_size > 8 { return Err(DecoderError::InvalidPrefix);
}
let mut total = 0;
let byte = if buf.is_empty() {
return Err(DecoderError::IntegerUnderflow);
} else {
total += 1;
buf[total - 1]
};
let mask = ((1 << prefix_size) - 1) as u8; let mut value = (byte & mask) as u32;
if value < (mask as u32) { *val = value;
return Ok(total);
}
let mut shift = 0;
loop {
let byte = if buf.is_empty() {
return Err(DecoderError::IntegerUnderflow);
} else {
total += 1;
buf[total - 1]
};
value += ((byte & 0b01111111) as u32) << shift;
shift += 7;
if byte & 0b10000000 == 0 { *val = value;
return Ok(total);
} else if total == 5 { return Err(DecoderError::IntegerOverflow);
}
}
}
pub(crate) fn decode_string(buf: &[u8], speed: DecoderSpeed, dst: &mut Vec<u8>) -> Result<usize, DecoderError> {
let huffman = buf[0] & 128 == 128;
let mut len = 0;
let mut total = decode_integer(buf, &mut len, 7)?;
if len as usize > buf.len() - total {
return Err(DecoderError::IntegerUnderflow);
}
let mut buf: Vec<u8> = buf[total..total + len as usize].to_vec();
total += len as usize;
if huffman { httlib_huffman::decode(&buf, dst, speed)?;
} else { dst.append(&mut buf);
}
Ok(total)
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn decodes_integer() {
let examples = vec![
(vec![10], 5, 10, 1), (vec![31, 154, 10], 5, 1337, 3), (vec![31 + 32, 154, 10], 5, 1337, 3), (vec![31 + 64, 154, 10], 5, 1337, 3), (vec![31, 154, 10, 111, 22], 5, 1337, 3), (vec![42], 8, 42, 1), (vec![127, 0], 7, 127, 2),
(vec![255, 0], 7, 127, 2),
(vec![254], 8, 254, 1),
(vec![1], 8, 1, 1),
(vec![0], 8, 0, 1),
(vec![127, 128, 1], 7, 255, 3),
(vec![0xFF, 0xFF, 0xFF, 0xFF, 0xFF - 128], 8, 268435710, 5), ];
for (value, prefix, res, size) in examples {
let mut dst = 0;
let total = decode_integer(&value, &mut dst, prefix).unwrap();
assert_eq!(dst, res);
assert_eq!(total, size);
}
}
#[test]
fn decodes_string() {
let examples = vec![
(b"foo", vec![3, 102, 111, 111]), (b"foo", vec![130, 148, 231]), ];
for (value, bytes) in examples {
let mut dst = Vec::new();
decode_string(&bytes, DecoderSpeed::FourBits, &mut dst).unwrap();
assert_eq!(dst, value);
}
}
}