1use crate::{
6 TpmCast, TpmCastMut, TpmMarshal, TpmResult, TpmSized, TpmUnmarshal, TpmWireBytes, TpmWriter,
7};
8use core::{
9 cmp::Ordering,
10 convert::TryFrom,
11 fmt::{Debug, Display, Formatter, LowerHex, UpperHex},
12 hash::{Hash, Hasher},
13 marker::PhantomData,
14};
15
16trait TpmIntBytes<const N: usize>: Copy + Ord {
18 fn to_be_bytes(self) -> [u8; N];
19 fn from_be_bytes(bytes: [u8; N]) -> Self;
20}
21
22#[repr(transparent)]
24pub struct TpmInt<T, const N: usize>([u8; N], PhantomData<T>);
25
26impl<T, const N: usize> Copy for TpmInt<T, N> {}
27
28impl<T, const N: usize> Clone for TpmInt<T, N> {
29 fn clone(&self) -> Self {
30 *self
31 }
32}
33
34impl<T, const N: usize> TpmInt<T, N> {
35 #[must_use]
36 pub const fn from_be_bytes(bytes: [u8; N]) -> Self {
37 Self(bytes, PhantomData)
38 }
39
40 #[must_use]
41 pub const fn as_bytes(&self) -> &[u8; N] {
42 &self.0
43 }
44
45 #[must_use]
46 pub fn as_bytes_mut(&mut self) -> &mut [u8; N] {
47 &mut self.0
48 }
49
50 #[must_use]
51 pub const fn to_be_bytes(self) -> [u8; N] {
52 self.0
53 }
54
55 pub fn cast(buf: &[u8]) -> TpmResult<&Self> {
64 Self::validate(buf)?;
65
66 Ok(unsafe { Self::cast_unchecked(buf) })
69 }
70
71 pub fn validate(buf: &[u8]) -> TpmResult<()> {
80 TpmWireBytes::<N>::validate(buf)
81 }
82
83 pub fn validate_prefix(buf: &[u8]) -> TpmResult<()> {
90 TpmWireBytes::<N>::validate_prefix(buf)
91 }
92
93 pub fn cast_prefix(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
100 Self::validate_prefix(buf)?;
101 let (head, tail) = buf.split_at(N);
102
103 Ok((unsafe { Self::cast_unchecked(head) }, tail))
106 }
107
108 pub fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
117 Self::validate(buf)?;
118
119 Ok(unsafe { Self::cast_mut_unchecked(buf) })
122 }
123
124 pub fn cast_prefix_mut(buf: &mut [u8]) -> TpmResult<(&mut Self, &mut [u8])> {
131 Self::validate_prefix(buf)?;
132 let (head, tail) = buf.split_at_mut(N);
133
134 Ok((unsafe { Self::cast_mut_unchecked(head) }, tail))
137 }
138}
139
140crate::tpm_byte_view!(array TpmInt<T, const N: usize>);
141
142impl<T, const N: usize> Default for TpmInt<T, N> {
143 fn default() -> Self {
144 Self::from_be_bytes([0; N])
145 }
146}
147
148impl<T, const N: usize> PartialEq for TpmInt<T, N> {
149 fn eq(&self, other: &Self) -> bool {
150 self.0 == other.0
151 }
152}
153
154impl<T, const N: usize> Eq for TpmInt<T, N> {}
155
156impl<T, const N: usize> Hash for TpmInt<T, N> {
157 fn hash<H: Hasher>(&self, state: &mut H) {
158 self.0.hash(state);
159 }
160}
161
162impl<T: TpmIntBytes<N>, const N: usize> PartialOrd for TpmInt<T, N> {
163 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
164 Some(self.cmp(other))
165 }
166}
167
168impl<T: TpmIntBytes<N>, const N: usize> Ord for TpmInt<T, N> {
169 fn cmp(&self, other: &Self) -> Ordering {
170 T::from_be_bytes(self.0).cmp(&T::from_be_bytes(other.0))
171 }
172}
173
174impl<T: TpmIntBytes<N> + Debug, const N: usize> Debug for TpmInt<T, N> {
175 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
176 f.debug_tuple("TpmInt")
177 .field(&T::from_be_bytes(self.0))
178 .finish()
179 }
180}
181
182impl<T: TpmIntBytes<N>, const N: usize> From<T> for TpmInt<T, N> {
183 fn from(value: T) -> Self {
184 Self::from_be_bytes(value.to_be_bytes())
185 }
186}
187
188impl<T: TpmIntBytes<N> + Display, const N: usize> Display for TpmInt<T, N> {
189 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
190 Display::fmt(&T::from_be_bytes(self.0), f)
191 }
192}
193
194impl<T: TpmIntBytes<N> + LowerHex, const N: usize> LowerHex for TpmInt<T, N> {
195 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
196 LowerHex::fmt(&T::from_be_bytes(self.0), f)
197 }
198}
199
200impl<T: TpmIntBytes<N> + UpperHex, const N: usize> UpperHex for TpmInt<T, N> {
201 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
202 UpperHex::fmt(&T::from_be_bytes(self.0), f)
203 }
204}
205
206impl<T, const N: usize> TpmSized for TpmInt<T, N> {
207 const SIZE: usize = N;
208
209 fn len(&self) -> usize {
210 Self::SIZE
211 }
212}
213
214impl<T, const N: usize> TpmMarshal for TpmInt<T, N> {
215 fn marshal(&self, writer: &mut TpmWriter) -> TpmResult<()> {
216 writer.write_bytes(self.as_bytes())
217 }
218}
219
220impl<T, const N: usize> TpmUnmarshal for TpmInt<T, N> {
221 fn unmarshal(buffer: &[u8]) -> TpmResult<(Self, &[u8])> {
222 let (value, remainder) = TpmWireBytes::<N>::cast_prefix(buffer)?;
223 Ok((Self::from_be_bytes(*value.as_bytes()), remainder))
224 }
225}
226
227impl<T, const N: usize> TpmCast for TpmInt<T, N> {
228 fn cast(buf: &[u8]) -> TpmResult<&Self> {
229 Self::cast(buf)
230 }
231
232 fn cast_prefix(buf: &[u8]) -> TpmResult<(&Self, &[u8])> {
233 Self::cast_prefix(buf)
234 }
235
236 unsafe fn cast_unchecked(buf: &[u8]) -> &Self {
237 unsafe { Self::cast_unchecked(buf) }
239 }
240}
241
242impl<T, const N: usize> TpmCastMut for TpmInt<T, N> {
243 fn cast_mut(buf: &mut [u8]) -> TpmResult<&mut Self> {
244 Self::cast_mut(buf)
245 }
246
247 fn cast_prefix_mut(buf: &mut [u8]) -> TpmResult<(&mut Self, &mut [u8])> {
248 Self::cast_prefix_mut(buf)
249 }
250
251 unsafe fn cast_mut_unchecked(buf: &mut [u8]) -> &mut Self {
252 unsafe { Self::cast_mut_unchecked(buf) }
254 }
255}
256
257impl<T, const N: usize> TryFrom<usize> for TpmInt<T, N>
258where
259 T: TpmIntBytes<N> + TryFrom<usize>,
260{
261 type Error = T::Error;
262
263 fn try_from(value: usize) -> Result<Self, Self::Error> {
264 T::try_from(value).map(Self::from)
265 }
266}
267
268macro_rules! tpm_int {
269 ($name:ident, $raw:ty, $n:literal) => {
270 pub type $name = TpmInt<$raw, $n>;
271
272 impl TpmIntBytes<$n> for $raw {
273 fn to_be_bytes(self) -> [u8; $n] {
274 <$raw>::to_be_bytes(self)
275 }
276
277 fn from_be_bytes(bytes: [u8; $n]) -> Self {
278 <$raw>::from_be_bytes(bytes)
279 }
280 }
281
282 impl TpmInt<$raw, $n> {
283 #[must_use]
284 pub const fn new(value: $raw) -> Self {
285 Self::from_be_bytes(<$raw>::to_be_bytes(value))
286 }
287
288 #[must_use]
289 pub const fn value(self) -> $raw {
290 <$raw>::from_be_bytes(self.to_be_bytes())
291 }
292
293 pub const fn set(&mut self, value: $raw) {
294 *self = Self::new(value);
295 }
296 }
297
298 impl From<TpmInt<$raw, $n>> for $raw {
299 fn from(value: TpmInt<$raw, $n>) -> $raw {
300 value.value()
301 }
302 }
303 };
304}
305
306tpm_int!(TpmUint8, u8, 1);
307tpm_int!(TpmInt8, i8, 1);
308tpm_int!(TpmUint16, u16, 2);
309tpm_int!(TpmUint32, u32, 4);
310tpm_int!(TpmUint64, u64, 8);
311tpm_int!(TpmInt32, i32, 4);
312
313pub type TpmHandle = TpmUint32;