1 //! Fixed size parameters list with optional subparameters.
2 
3 use core::fmt::{self, Debug, Formatter};
4 
5 pub(crate) const MAX_PARAMS: usize = 32;
6 
7 #[derive(Default)]
8 pub struct Params {
9     /// Number of subparameters for each parameter.
10     ///
11     /// For each entry in the `params` slice, this stores the length of the param as number of
12     /// subparams at the same index as the param in the `params` slice.
13     ///
14     /// At the subparam positions the length will always be `0`.
15     subparams: [u8; MAX_PARAMS],
16 
17     /// All parameters and subparameters.
18     params: [u16; MAX_PARAMS],
19 
20     /// Number of suparameters in the current parameter.
21     current_subparams: u8,
22 
23     /// Total number of parameters and subparameters.
24     len: usize,
25 }
26 
27 impl Params {
28     /// Returns the number of parameters.
29     #[inline]
len(&self) -> usize30     pub fn len(&self) -> usize {
31         self.len
32     }
33 
34     /// Returns `true` if there are no parameters present.
35     #[inline]
is_empty(&self) -> bool36     pub fn is_empty(&self) -> bool {
37         self.len == 0
38     }
39 
40     /// Returns an iterator over all parameters and subparameters.
41     #[inline]
iter(&self) -> ParamsIter<'_>42     pub fn iter(&self) -> ParamsIter<'_> {
43         ParamsIter::new(self)
44     }
45 
46     /// Returns `true` if there is no more space for additional parameters.
47     #[inline]
is_full(&self) -> bool48     pub(crate) fn is_full(&self) -> bool {
49         self.len == MAX_PARAMS
50     }
51 
52     /// Clear all parameters.
53     #[inline]
clear(&mut self)54     pub(crate) fn clear(&mut self) {
55         self.current_subparams = 0;
56         self.len = 0;
57     }
58 
59     /// Add an additional parameter.
60     #[inline]
push(&mut self, item: u16)61     pub(crate) fn push(&mut self, item: u16) {
62         self.subparams[self.len - self.current_subparams as usize] = self.current_subparams + 1;
63         self.params[self.len] = item;
64         self.current_subparams = 0;
65         self.len += 1;
66     }
67 
68     /// Add an additional subparameter to the current parameter.
69     #[inline]
extend(&mut self, item: u16)70     pub(crate) fn extend(&mut self, item: u16) {
71         self.params[self.len] = item;
72         self.current_subparams += 1;
73         self.len += 1;
74     }
75 }
76 
77 impl<'a> IntoIterator for &'a Params {
78     type IntoIter = ParamsIter<'a>;
79     type Item = &'a [u16];
80 
into_iter(self) -> Self::IntoIter81     fn into_iter(self) -> Self::IntoIter {
82         self.iter()
83     }
84 }
85 
86 /// Immutable subparameter iterator.
87 pub struct ParamsIter<'a> {
88     params: &'a Params,
89     index: usize,
90 }
91 
92 impl<'a> ParamsIter<'a> {
new(params: &'a Params) -> Self93     fn new(params: &'a Params) -> Self {
94         Self { params, index: 0 }
95     }
96 }
97 
98 impl<'a> Iterator for ParamsIter<'a> {
99     type Item = &'a [u16];
100 
next(&mut self) -> Option<Self::Item>101     fn next(&mut self) -> Option<Self::Item> {
102         if self.index >= self.params.len() {
103             return None;
104         }
105 
106         // Get all subparameters for the current parameter.
107         let num_subparams = self.params.subparams[self.index];
108         let param = &self.params.params[self.index..self.index + num_subparams as usize];
109 
110         // Jump to the next parameter.
111         self.index += num_subparams as usize;
112 
113         Some(param)
114     }
115 
size_hint(&self) -> (usize, Option<usize>)116     fn size_hint(&self) -> (usize, Option<usize>) {
117         let remaining = self.params.len() - self.index;
118         (remaining, Some(remaining))
119     }
120 }
121 
122 impl Debug for Params {
fmt(&self, f: &mut Formatter<'_>) -> fmt::Result123     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
124         write!(f, "[")?;
125 
126         for (i, param) in self.iter().enumerate() {
127             if i != 0 {
128                 write!(f, ";")?;
129             }
130 
131             for (i, subparam) in param.iter().enumerate() {
132                 if i != 0 {
133                     write!(f, ":")?;
134                 }
135 
136                 subparam.fmt(f)?;
137             }
138         }
139 
140         write!(f, "]")
141     }
142 }
143