1use crate::{TpmBuild, TpmErrorKind, TpmParse, TpmResult, TpmSized};
6use core::{convert::TryFrom, mem::size_of, ops::Deref};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct TpmList<T: Copy + Default, const CAPACITY: usize> {
10 items: [T; CAPACITY],
11 len: usize,
12}
13
14impl<T: Copy + Default, const CAPACITY: usize> TpmList<T, CAPACITY> {
15 #[must_use]
16 pub fn new() -> Self {
17 Self {
18 items: [T::default(); CAPACITY],
19 len: 0,
20 }
21 }
22
23 #[must_use]
25 pub fn is_empty(&self) -> bool {
26 self.len == 0
27 }
28
29 pub fn try_push(&mut self, item: T) -> Result<(), TpmErrorKind> {
36 if self.len >= CAPACITY {
37 return Err(TpmErrorKind::CapacityExceeded);
38 }
39 self.items[self.len] = item;
40 self.len += 1;
41 Ok(())
42 }
43}
44
45impl<T: Copy + Default, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
46 type Target = [T];
47
48 fn deref(&self) -> &Self::Target {
49 &self.items[..self.len]
50 }
51}
52
53impl<T: Copy + Default, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
54 fn default() -> Self {
55 Self::new()
56 }
57}
58
59impl<T: TpmSized + Copy + Default, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
60 const SIZE: usize = size_of::<u32>() + (T::SIZE * CAPACITY);
61 fn len(&self) -> usize {
62 size_of::<u32>() + self.iter().map(TpmSized::len).sum::<usize>()
63 }
64}
65
66impl<T: TpmBuild + Copy + Default, const CAPACITY: usize> TpmBuild for TpmList<T, CAPACITY> {
67 fn build(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
68 let len_u32 = u32::try_from(self.len).map_err(|_| TpmErrorKind::ValueTooLarge)?;
69 TpmBuild::build(&len_u32, writer)?;
70 for item in &**self {
71 TpmBuild::build(item, writer)?;
72 }
73 Ok(())
74 }
75}
76
77impl<T: TpmParse + Copy + Default, const CAPACITY: usize> TpmParse for TpmList<T, CAPACITY> {
78 fn parse(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
79 let (count_u32, mut buf) = u32::parse(buf)?;
80 let count = count_u32 as usize;
81 if count > CAPACITY {
82 return Err(TpmErrorKind::ValueTooLarge);
83 }
84
85 let mut list = Self::new();
86 for _ in 0..count {
87 let (item, rest) = T::parse(buf)?;
88 list.try_push(item)
89 .map_err(|_| TpmErrorKind::InternalError)?;
90 buf = rest;
91 }
92
93 Ok((list, buf))
94 }
95}