| //! Fixed size parameters list with optional subparameters. |
| |
| use core::fmt::{self, Debug, Formatter}; |
| |
| pub(crate) const MAX_PARAMS: usize = 32; |
| |
| #[derive(Default, Clone, PartialEq, Eq)] |
| pub struct Params { |
| /// Number of subparameters for each parameter. |
| /// |
| /// For each entry in the `params` slice, this stores the length of the param as number of |
| /// subparams at the same index as the param in the `params` slice. |
| /// |
| /// At the subparam positions the length will always be `0`. |
| subparams: [u8; MAX_PARAMS], |
| |
| /// All parameters and subparameters. |
| params: [u16; MAX_PARAMS], |
| |
| /// Number of suparameters in the current parameter. |
| current_subparams: u8, |
| |
| /// Total number of parameters and subparameters. |
| len: usize, |
| } |
| |
| impl Params { |
| /// Returns the number of parameters. |
| #[inline] |
| pub fn len(&self) -> usize { |
| self.len |
| } |
| |
| /// Returns `true` if there are no parameters present. |
| #[inline] |
| pub fn is_empty(&self) -> bool { |
| self.len == 0 |
| } |
| |
| /// Returns an iterator over all parameters and subparameters. |
| #[inline] |
| pub fn iter(&self) -> ParamsIter<'_> { |
| ParamsIter::new(self) |
| } |
| |
| /// Returns `true` if there is no more space for additional parameters. |
| #[inline] |
| pub(crate) fn is_full(&self) -> bool { |
| self.len == MAX_PARAMS |
| } |
| |
| /// Clear all parameters. |
| #[inline] |
| pub(crate) fn clear(&mut self) { |
| self.current_subparams = 0; |
| self.len = 0; |
| } |
| |
| /// Add an additional parameter. |
| #[inline] |
| pub(crate) fn push(&mut self, item: u16) { |
| self.subparams[self.len - self.current_subparams as usize] = self.current_subparams + 1; |
| self.params[self.len] = item; |
| self.current_subparams = 0; |
| self.len += 1; |
| } |
| |
| /// Add an additional subparameter to the current parameter. |
| #[inline] |
| pub(crate) fn extend(&mut self, item: u16) { |
| self.subparams[self.len - self.current_subparams as usize] = self.current_subparams + 1; |
| self.params[self.len] = item; |
| self.current_subparams += 1; |
| self.len += 1; |
| } |
| } |
| |
| impl<'a> IntoIterator for &'a Params { |
| type IntoIter = ParamsIter<'a>; |
| type Item = &'a [u16]; |
| |
| fn into_iter(self) -> Self::IntoIter { |
| self.iter() |
| } |
| } |
| |
| /// Immutable subparameter iterator. |
| pub struct ParamsIter<'a> { |
| params: &'a Params, |
| index: usize, |
| } |
| |
| impl<'a> ParamsIter<'a> { |
| fn new(params: &'a Params) -> Self { |
| Self { params, index: 0 } |
| } |
| } |
| |
| impl<'a> Iterator for ParamsIter<'a> { |
| type Item = &'a [u16]; |
| |
| fn next(&mut self) -> Option<Self::Item> { |
| if self.index >= self.params.len() { |
| return None; |
| } |
| |
| // Get all subparameters for the current parameter. |
| let num_subparams = self.params.subparams[self.index]; |
| let param = &self.params.params[self.index..self.index + num_subparams as usize]; |
| |
| // Jump to the next parameter. |
| self.index += num_subparams as usize; |
| |
| Some(param) |
| } |
| |
| fn size_hint(&self) -> (usize, Option<usize>) { |
| let remaining = self.params.len() - self.index; |
| (remaining, Some(remaining)) |
| } |
| } |
| |
| impl Debug for Params { |
| fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| write!(f, "[")?; |
| |
| for (i, param) in self.iter().enumerate() { |
| if i != 0 { |
| write!(f, ";")?; |
| } |
| |
| for (i, subparam) in param.iter().enumerate() { |
| if i != 0 { |
| write!(f, ":")?; |
| } |
| |
| subparam.fmt(f)?; |
| } |
| } |
| |
| write!(f, "]") |
| } |
| } |