tpm2_protocol/macro/
struct.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2025 Opinsys Oy
3// Copyright (c) 2024-2025 Jarkko Sakkinen
4
5#[macro_export]
6macro_rules! tpm_struct {
7    (
8        $(#[$meta:meta])*
9        $name:ident,
10        $cc:expr,
11        $no_sessions:expr,
12        $with_sessions:expr,
13        $handles:expr,
14        {
15            $(pub $field_name:ident: $field_type:ty),*
16            $(,)?
17        }
18    ) => {
19        $crate::tpm_struct! {
20            $(#[$meta])*
21            pub struct $name {
22                $(pub $field_name: $field_type,)*
23            }
24        }
25
26        impl $crate::message::TpmHeader for $name {
27            const COMMAND: $crate::data::TpmCc = $cc;
28            const NO_SESSIONS: bool = $no_sessions;
29            const WITH_SESSIONS: bool = $with_sessions;
30            const HANDLES: usize = $handles;
31        }
32    };
33
34    (
35        $(#[$meta:meta])*
36        $vis:vis struct $name:ident {
37            $(pub $field_name:ident: $field_type:ty),*
38            $(,)?
39        }
40    ) => {
41        $(#[$meta])*
42        $vis struct $name {
43            $(pub $field_name: $field_type,)*
44        }
45
46        impl $crate::TpmSized for $name {
47            const SIZE: usize = 0 $(+ <$field_type>::SIZE)*;
48            fn len(&self) -> usize {
49                0 $(+ $crate::TpmSized::len(&self.$field_name))*
50            }
51        }
52
53        impl $crate::TpmBuild for $name {
54            #[allow(unused_variables)]
55            fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
56                $( $crate::TpmBuild::build(&self.$field_name, writer)?; )*
57                Ok(())
58            }
59        }
60
61        impl $crate::TpmParse for $name {
62            fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
63                $(let ($field_name, buf) = <$field_type>::parse(buf)?;)*
64                Ok((
65                    Self {
66                        $($field_name,)*
67                    },
68                    buf,
69                ))
70            }
71        }
72    };
73}
74
75#[macro_export]
76macro_rules! tpm_tagged_struct {
77    (
78        $(#[$outer:meta])*
79        $vis:vis struct $name:ident {
80            pub $tag_field:ident: $tag_ty:ty,
81            pub $value_field:ident: $value_ty:ty,
82        }
83    ) => {
84        $(#[$outer])*
85        $vis struct $name {
86            pub $tag_field: $tag_ty,
87            pub $value_field: $value_ty,
88        }
89
90        impl $crate::TpmTagged for $name {
91            type Tag = $tag_ty;
92            type Value = $value_ty;
93        }
94
95        impl $crate::TpmSized for $name {
96            const SIZE: usize = <$tag_ty>::SIZE + <$value_ty>::SIZE;
97            fn len(&self) -> usize {
98                $crate::TpmSized::len(&self.$tag_field) + $crate::TpmSized::len(&self.$value_field)
99            }
100        }
101
102        impl $crate::TpmBuild for $name {
103            fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
104                $crate::TpmBuild::build(&self.$tag_field, writer)?;
105                $crate::TpmBuild::build(&self.$value_field, writer)
106            }
107        }
108
109        impl $crate::TpmParse for $name {
110            fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
111                let ($tag_field, buf) = <$tag_ty>::parse(buf)?;
112                let ($value_field, buf) =
113                    <$value_ty as $crate::TpmParseTagged>::parse_tagged($tag_field, buf)?;
114                Ok((
115                    Self {
116                        $tag_field,
117                        $value_field,
118                    },
119                    buf,
120                ))
121            }
122        }
123    };
124}