tpm2_protocol/macro/
enum.rs1#[macro_export]
10macro_rules! tpm_enum {
11 (
12 $(#[$enum_meta:meta])*
13 $vis:vis enum $name:ident($repr:ty) {
14 $(
15 $(#[$variant_meta:meta])*
16 ($variant:ident, $value:expr, $display:literal)
17 ),* $(,)?
18 }
19 ) => {
20 $(#[$enum_meta])*
21 #[repr($repr)]
22 $vis enum $name {
23 $(
24 $(#[$variant_meta])*
25 $variant = $value
26 ),*
27 }
28
29 impl TryFrom<$repr> for $name {
30 type Error = ();
31
32 #[allow(clippy::cognitive_complexity)]
33 fn try_from(value: $repr) -> Result<Self, ()> {
34 $(
35 if value == $value {
36 return Ok(Self::$variant);
37 }
38 )*
39 Err(())
40 }
41 }
42
43 impl core::fmt::Display for $name {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 let s = match self {
46 $(Self::$variant => $display),*
47 };
48 write!(f, "{}", s)
49 }
50 }
51
52 impl core::str::FromStr for $name {
53 type Err = ();
54
55 fn from_str(s: &str) -> Result<Self, Self::Err> {
56 match s {
57 $($display => Ok(Self::$variant),)*
58 _ => Err(()),
59 }
60 }
61 }
62
63 impl $crate::TpmSized for $name {
64 const SIZE: usize = core::mem::size_of::<$repr>();
65
66 fn len(&self) -> usize {
67 Self::SIZE
68 }
69 }
70
71 impl $crate::TpmBuild for $name {
72 fn build(&self, writer: &mut $crate::TpmWriter) -> $crate::TpmResult<()> {
73 $crate::TpmBuild::build(&(*self as $repr), writer)
74 }
75 }
76
77 impl $crate::TpmParse for $name {
78 fn parse(buf: &[u8]) -> $crate::TpmResult<(Self, &[u8])> {
79 let (val, buf) = <$repr>::parse(buf)?;
80 let enum_val = Self::try_from(val).map_err(|()| $crate::TpmError::UnknownDiscriminant (stringify!($name), val.into()))?;
81 Ok((enum_val, buf))
82 }
83 }
84 };
85}