use crate::error::QpackError;
pub fn encode_integer(buf: &mut [u8], value: u64, prefix_bits: u8, prefix: u8) -> Option<usize> {
if prefix_bits == 0 || prefix_bits > 8 {
return None;
}
let max_prefix = (1u64 << prefix_bits) - 1;
if value < max_prefix {
if buf.is_empty() {
return None;
}
buf[0] = prefix | (value as u8);
Some(1)
} else {
if buf.is_empty() {
return None;
}
buf[0] = prefix | (max_prefix as u8);
let mut offset = 1;
let mut remaining = value - max_prefix;
while remaining >= 128 {
if offset >= buf.len() {
return None;
}
buf[offset] = 0x80 | ((remaining & 0x7f) as u8);
remaining >>= 7;
offset += 1;
}
if offset >= buf.len() {
return None;
}
buf[offset] = remaining as u8;
Some(offset + 1)
}
}
pub fn encode_integer_to_vec(buf: &mut Vec<u8>, value: u64, prefix_bits: u8, prefix: u8) {
if prefix_bits == 0 || prefix_bits > 8 {
return;
}
let max_prefix = (1u64 << prefix_bits) - 1;
if value < max_prefix {
buf.push(prefix | (value as u8));
} else {
buf.push(prefix | (max_prefix as u8));
let mut remaining = value - max_prefix;
while remaining >= 128 {
buf.push(0x80 | ((remaining & 0x7f) as u8));
remaining >>= 7;
}
buf.push(remaining as u8);
}
}
pub fn decode_integer(data: &[u8], prefix_bits: u8) -> Result<(u64, usize), QpackError> {
if data.is_empty() {
return Err(QpackError::BufferTooShort);
}
if prefix_bits == 0 || prefix_bits > 8 {
return Err(QpackError::DecodeFailed);
}
let mask = ((1u16 << prefix_bits) - 1) as u8;
let prefix_value = data[0] & mask;
if prefix_value < mask {
return Ok((prefix_value as u64, 1));
}
let mut value = prefix_value as u64;
let mut shift = 0u32;
let mut offset = 1;
loop {
if offset >= data.len() {
return Err(QpackError::BufferTooShort);
}
let byte = data[offset];
value += ((byte & 0x7f) as u64) << shift;
offset += 1;
if byte & 0x80 == 0 {
break;
}
shift += 7;
if shift > 56 {
return Err(QpackError::DecodeFailed);
}
}
Ok((value, offset))
}