1#[macro_export]
6macro_rules! trace_header {
7 ($name:ident (max_size_bit: $upper_size_bit:literal) ($size_ty:ty) $(($header_ty:expr))? {
8 $($field_ty:ty, $getter:ident: $start_bit:literal, $end_bit:literal;)*
9 }) => {
10 trace_header!(
11 $name (max_size_bit: $upper_size_bit) ($size_ty) $(($header_ty))?
12 {
13 $($field_ty, $getter: $start_bit, $end_bit;)*
14 } => |_h| Ok(())
15 );
16 };
17 ($name:ident $(($header_ty:expr))? {
18 $($field_ty:ty, $getter:ident: $start_bit:literal, $end_bit:literal;)*
19 }) => {
20 trace_header!(
21 $name $(($header_ty))?
22 {
23 $($field_ty, $getter: $start_bit, $end_bit;)*
24 } => |_h| Ok(())
25 );
26 };
27 (
28 $name:ident $(($header_ty:expr))? {
29 $($field_ty:ty, $getter:ident: $start_bit:literal, $end_bit:literal;)*
30 } => |$header:ident $(: $header_arg_ty:ty)?| $verify:expr
31 ) => {
32 trace_header!(
33 $name (max_size_bit: 15) (u16) $(($header_ty))?
34 {
35 $($field_ty, $getter: $start_bit, $end_bit;)*
36 } => |$header $(: $header_arg_ty)?| $verify
37 );
38 };
39 (
40 $name:ident (max_size_bit: $upper_size_bit:literal) ($size_ty:ty) $(($header_ty:expr))? {
41 $($field_ty:ty, $getter:ident: $start_bit:literal, $end_bit:literal;)*
42 } => |$header:ident $(: $header_arg_ty:ty)?| $verify:expr
43 ) => {
44 #[derive(Clone, Copy, Eq, PartialEq)]
46 pub struct $name(u64);
47
48 bitfield::bitfield_bitrange! { struct $name(u64) }
49
50 impl std::fmt::Debug for $name {
52 bitfield::bitfield_debug! {
53 struct $name;
54 u8, raw_type, _: 3, 0;
55 $size_ty, size_words, _: $upper_size_bit, 4;
56 $($field_ty, $getter, _: $end_bit, $start_bit;)*
57 }
58 }
59
60 impl $name {
61 paste::paste! { bitfield::bitfield_fields! {
62 u64;
63 pub u8, raw_type, set_raw_type: 3, 0;
64 pub $size_ty, size_words, set_size_words: $upper_size_bit, 4;
65 $(pub $field_ty, $getter, [<set_ $getter>]: $end_bit, $start_bit;)*
66 }}
67
68 #[allow(unused, unused_mut)]
69 pub(crate) fn empty() -> Self {
70 let mut header = Self(0);
71 $(header.set_raw_type($header_ty);)?
72 header
73 }
74
75 fn new(bits: u64) -> Result<Self, crate::ParseError> {
76 let header = Self(bits);
77
78 $(if header.raw_type() != $header_ty {
79 return Err(crate::ParseError::WrongType {
80 context: stringify!($name),
81 expected: $header_ty,
82 observed: header.raw_type(),
83 });
84 })?
85
86 let res: Result<(), crate::ParseError> = (|$header $(: $header_arg_ty)?| $verify)(&header);
88 res?;
89
90 Ok(header)
91 }
92
93 #[allow(unused)] fn parse(buf: &[u8]) -> crate::ParseResult<'_, Self> {
95 use nom::Parser;
96 nom::combinator::map_res(nom::number::streaming::le_u64, |h| Self::new(h)).parse(buf)
97 }
98
99 #[allow(unused)] fn take_payload<'a>(&self, buf: &'a [u8]) -> crate::ParseResult<'a, &'a [u8]> {
101 if self.size_words() == 0 {
102 return Err(nom::Err::Failure(crate::ParseError::InvalidSize));
103 }
104 let size_bytes_without_header = (self.size_words() as usize - 1) * 8;
105 if size_bytes_without_header > buf.len() {
106 let needed = size_bytes_without_header - buf.len();
107 return Err(nom::Err::Incomplete(nom::Needed::Size(
108 std::num::NonZero::new(needed).unwrap())
109 ));
110 }
111 let (payload, rem) = buf.split_at(size_bytes_without_header);
112 Ok((rem, payload))
113 }
114 }
115
116 impl crate::header::TraceHeader for $name {
117 fn set_size_words(&mut self, n: u16) {
118 self.set_size_words(n.try_into().unwrap());
119 }
120 fn to_le_bytes(&self) -> [u8; 8] {
121 self.0.to_le_bytes()
122 }
123 }
124 };
125}
126
127pub(crate) trait TraceHeader {
128 fn set_size_words(&mut self, n: u16);
129 fn to_le_bytes(&self) -> [u8; 8];
130}