use crate::{Error, Result};
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Lengths {
U16(Vec<u16>),
U32(Vec<u32>),
U64(Vec<u64>),
}
impl Lengths {
fn empty(max_length: u64) -> Self {
match max_length {
..=65_536 => Self::U16(Vec::new()),
65_537..=4_294_967_296 => Self::U32(Vec::new()),
_ => Self::U64(Vec::new()),
}
}
pub fn new(max_length: u64) -> Result<Self> {
if max_length == 0 {
return Err(Error::InvalidFrameSize);
}
Ok(Self::empty(max_length))
}
pub(crate) fn for_config(config: &crate::Config) -> Self {
Self::empty(config.max_frame_len())
}
pub fn len(&self) -> usize {
match self {
Self::U16(v) => v.len(),
Self::U32(v) => v.len(),
Self::U64(v) => v.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn width(&self) -> usize {
match self {
Self::U16(_) => 2,
Self::U32(_) => 4,
Self::U64(_) => 8,
}
}
pub fn get(&self, index: usize) -> Option<u64> {
match self {
Self::U16(v) => v.get(index).map(|v| u64::from(*v) + 1),
Self::U32(v) => v.get(index).map(|v| u64::from(*v) + 1),
Self::U64(v) => v.get(index).and_then(|v| v.checked_add(1)),
}
}
pub fn push(&mut self, length: u64) -> Result<()> {
let encoded = length.checked_sub(1).ok_or(Error::InvalidFrameSize)?;
match self {
Self::U16(v) => {
let value = u16::try_from(encoded).map_err(|_| Error::Overflow)?;
v.try_reserve(1).map_err(|_| Error::Allocation)?;
v.push(value);
}
Self::U32(v) => {
let value = u32::try_from(encoded).map_err(|_| Error::Overflow)?;
v.try_reserve(1).map_err(|_| Error::Allocation)?;
v.push(value);
}
Self::U64(v) => {
v.try_reserve(1).map_err(|_| Error::Allocation)?;
v.push(encoded);
}
}
Ok(())
}
pub(crate) fn reserve_one(&mut self) -> Result<()> {
match self {
Self::U16(v) => v.try_reserve(1),
Self::U32(v) => v.try_reserve(1),
Self::U64(v) => v.try_reserve(1),
}
.map_err(|_| Error::Allocation)
}
}