1use crate::{Error, Result};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum Lengths {
10 U16(Vec<u16>),
12 U32(Vec<u32>),
14 U64(Vec<u64>),
16}
17
18impl Lengths {
19 fn empty(max_length: u64) -> Self {
20 match max_length {
21 ..=65_536 => Self::U16(Vec::new()),
22 65_537..=4_294_967_296 => Self::U32(Vec::new()),
23 _ => Self::U64(Vec::new()),
24 }
25 }
26
27 pub fn new(max_length: u64) -> Result<Self> {
29 if max_length == 0 {
30 return Err(Error::InvalidFrameSize);
31 }
32 Ok(Self::empty(max_length))
33 }
34
35 pub(crate) fn for_config(config: &crate::Config) -> Self {
36 Self::empty(config.max_frame_len())
37 }
38
39 pub fn len(&self) -> usize {
41 match self {
42 Self::U16(v) => v.len(),
43 Self::U32(v) => v.len(),
44 Self::U64(v) => v.len(),
45 }
46 }
47 pub fn is_empty(&self) -> bool {
49 self.len() == 0
50 }
51 pub fn width(&self) -> usize {
53 match self {
54 Self::U16(_) => 2,
55 Self::U32(_) => 4,
56 Self::U64(_) => 8,
57 }
58 }
59 pub fn get(&self, index: usize) -> Option<u64> {
61 match self {
62 Self::U16(v) => v.get(index).map(|v| u64::from(*v) + 1),
63 Self::U32(v) => v.get(index).map(|v| u64::from(*v) + 1),
64 Self::U64(v) => v.get(index).and_then(|v| v.checked_add(1)),
65 }
66 }
67 pub fn push(&mut self, length: u64) -> Result<()> {
69 let encoded = length.checked_sub(1).ok_or(Error::InvalidFrameSize)?;
70 match self {
71 Self::U16(v) => {
72 let value = u16::try_from(encoded).map_err(|_| Error::Overflow)?;
73 v.try_reserve(1).map_err(|_| Error::Allocation)?;
74 v.push(value);
75 }
76 Self::U32(v) => {
77 let value = u32::try_from(encoded).map_err(|_| Error::Overflow)?;
78 v.try_reserve(1).map_err(|_| Error::Allocation)?;
79 v.push(value);
80 }
81 Self::U64(v) => {
82 v.try_reserve(1).map_err(|_| Error::Allocation)?;
83 v.push(encoded);
84 }
85 }
86 Ok(())
87 }
88 pub(crate) fn reserve_one(&mut self) -> Result<()> {
89 match self {
90 Self::U16(v) => v.try_reserve(1),
91 Self::U32(v) => v.try_reserve(1),
92 Self::U64(v) => v.try_reserve(1),
93 }
94 .map_err(|_| Error::Allocation)
95 }
96}