tpm2_protocol/basic/
list.rs1use crate::{TpmMarshal, TpmProtocolError, TpmResult, TpmSized, TpmUnmarshal};
6use core::{
7 convert::TryFrom,
8 fmt::Debug,
9 mem::{size_of, MaybeUninit},
10 ops::Deref,
11 slice,
12};
13
14#[derive(Clone, Copy)]
16pub struct TpmList<T: Copy, const CAPACITY: usize> {
17 items: [MaybeUninit<T>; CAPACITY],
18 len: usize,
19}
20
21impl<T: Copy, const CAPACITY: usize> TpmList<T, CAPACITY> {
22 #[must_use]
24 pub fn new() -> Self {
25 Self {
26 items: [const { MaybeUninit::uninit() }; CAPACITY],
27 len: 0,
28 }
29 }
30
31 #[must_use]
33 pub fn is_empty(&self) -> bool {
34 self.len == 0
35 }
36
37 pub fn try_push(&mut self, item: T) -> Result<(), TpmProtocolError> {
44 if self.len >= CAPACITY {
45 return Err(TpmProtocolError::TooManyItems);
46 }
47 self.items[self.len].write(item);
48 self.len += 1;
49 Ok(())
50 }
51
52 pub fn try_extend_from_slice(&mut self, slice: &[T]) -> Result<(), TpmProtocolError> {
59 let new_len = self
60 .len
61 .checked_add(slice.len())
62 .ok_or(TpmProtocolError::TooManyItems)?;
63
64 if new_len > CAPACITY {
65 return Err(TpmProtocolError::TooManyItems);
66 }
67
68 for (dest, src) in self.items[self.len..new_len].iter_mut().zip(slice) {
69 dest.write(*src);
70 }
71 self.len = new_len;
72 Ok(())
73 }
74}
75
76#[allow(unsafe_code)]
77impl<T: Copy, const CAPACITY: usize> Deref for TpmList<T, CAPACITY> {
78 type Target = [T];
79
80 fn deref(&self) -> &Self::Target {
87 unsafe { slice::from_raw_parts(self.items.as_ptr().cast::<T>(), self.len) }
88 }
89}
90
91impl<T: Copy, const CAPACITY: usize> Default for TpmList<T, CAPACITY> {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97impl<T: Copy + Debug, const CAPACITY: usize> Debug for TpmList<T, CAPACITY> {
98 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
99 f.debug_list().entries(self.iter()).finish()
100 }
101}
102
103impl<T: Copy + PartialEq, const CAPACITY: usize> PartialEq for TpmList<T, CAPACITY> {
104 fn eq(&self, other: &Self) -> bool {
105 **self == **other
106 }
107}
108
109impl<T: Copy + Eq, const CAPACITY: usize> Eq for TpmList<T, CAPACITY> {}
110
111impl<T: TpmSized + Copy, const CAPACITY: usize> TpmSized for TpmList<T, CAPACITY> {
112 const SIZE: usize = size_of::<u32>() + (T::SIZE * CAPACITY);
113 fn len(&self) -> usize {
114 size_of::<u32>() + self.iter().map(TpmSized::len).sum::<usize>()
115 }
116}
117
118impl<T: TpmMarshal + Copy, const CAPACITY: usize> TpmMarshal for TpmList<T, CAPACITY> {
119 fn marshal(&self, writer: &mut crate::TpmWriter) -> TpmResult<()> {
120 let len = u32::try_from(self.len).map_err(|_| TpmProtocolError::OperationFailed)?;
121 TpmMarshal::marshal(&len, writer)?;
122 for item in &**self {
123 TpmMarshal::marshal(item, writer)?;
124 }
125 Ok(())
126 }
127}
128
129impl<T: TpmUnmarshal + Copy, const CAPACITY: usize> TpmUnmarshal for TpmList<T, CAPACITY> {
130 fn unmarshal(buf: &[u8]) -> TpmResult<(Self, &[u8])> {
131 let (count_u32, mut buf) = u32::unmarshal(buf)?;
132 let count = count_u32 as usize;
133 if count > CAPACITY {
134 return Err(TpmProtocolError::TooManyItems);
135 }
136
137 let mut list = Self::new();
138 for _ in 0..count {
139 let (item, rest) = T::unmarshal(buf)?;
140 list.try_push(item)?;
141 buf = rest;
142 }
143
144 Ok((list, buf))
145 }
146}