zigbee_cluster_library/common/
parse.rs1#[macro_export]
3macro_rules! impl_byte {
4 (
5 $(#[$m:meta])*
6 $v:vis struct $name:ident($vt:vis $ty:ty);
7 ) => {
8 $(#[$m])*
9 $v struct $name($vt $ty);
10
11 impl<C: ::core::default::Default> ::byte::TryRead<'_, C> for $name {
12 fn try_read(bytes: &'_ [u8], _: C) -> ::byte::Result<(Self, usize)> {
13 let (v, sz) = <$ty>::try_read(bytes, ::byte::LE)?;
14 Ok((Self(v), sz))
15 }
16 }
17
18 impl<C: ::core::default::Default> ::byte::TryWrite<C> for $name {
19 fn try_write(self, bytes: &mut [u8], _: C) -> ::byte::Result<usize> {
20 self.0.try_write(bytes, ::byte::LE)
21 }
22 }
23 };
24 (
25 $(#[$m:meta])*
26 $v:vis struct $name:ident $(<$lifetime:lifetime>)? {
27 $(
28 $(#[doc = $doc:literal])*
29 $(#[ctx = $ctx_hdr:expr])?
30 $(#[parse_if = $parse_if_hdr:expr])?
31 $vf:vis $field_name:ident: $field_ty:ty
32 ),+
33 $(,)?
34 }
35 ) => {
36 $(#[$m])*
37 $v struct $name $(<$lifetime>)? {
38 $(
39 $(#[doc = $doc])*
40 $vf $field_name: $field_ty
41 ),+
42 }
43
44 #[allow(single_use_lifetimes, clippy::redundant_closure_call, unreachable_code, unused_variables)]
45 impl<'a, C: ::core::default::Default> ::byte::TryRead<'a, C> for $name $(<$lifetime>)? {
46 fn try_read(bytes: &'a [u8], _: C) -> ::byte::Result<(Self, usize)> {
47 use ::byte::BytesExt;
48 let offset = &mut 0;
49 $(
50 let ctx = ::byte::LE;
51 $(
52 let ctx = $ctx_hdr;
53 )?
54
55 let should_read = true;
56 $(let should_read = $parse_if_hdr;)?
57
58 let $field_name: $field_ty = if should_read {
59 let v = bytes.read_with(offset, ctx)?;
60 $(
61 let _ = $parse_if_hdr;
62 let v = Some(v);
63 )?
64 v
65 } else {
66 (|| {
67 $(
68 let _ = $parse_if_hdr;
69 return None;
70 )?
71 unreachable!()
72 })()
73 };
74 )+
75 let s = Self {
76 $($field_name,)+
77 };
78 Ok((s, *offset))
79 }
80 }
81
82 #[allow(single_use_lifetimes, unused_variables)]
83 impl<'a, C: ::core::default::Default> ::byte::TryWrite<C> for $name $(<$lifetime>)? {
84 fn try_write(self, bytes: &mut [u8], _: C) -> ::byte::Result<usize> {
85 use ::byte::BytesExt;
86 let offset = &mut 0;
87
88 let Self {
89 $($field_name,)+
90 } = self;
91
92 $(
93 let ctx = ::byte::LE;
94 $(
95 let _ = $ctx_hdr;
96 let ctx = ();
97 )?
98
99 let should_write = true;
100 $(let should_write = $parse_if_hdr;)?
101 if should_write {
102 let v = $field_name;
103 $(
104 let _ = $parse_if_hdr;
105 let v = v.unwrap();
106 )?
107 bytes.write_with(offset, v, ctx)?;
108 }
109 )+
110 Ok(*offset)
111 }
112 }
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use byte::TryRead;
119 use byte::TryWrite;
120
121 impl_byte! {
122 struct DataFrame<'a> {
123 flag: u8,
124 #[parse_if = flag > 0]
125 opt: Option<u16>,
126 length: u8,
127 #[ctx = byte::ctx::Bytes::Len(usize::from(length))]
128 data: &'a [u8],
129 }
130 }
131
132 #[test]
133 fn parse() {
134 let bytes = &[0x01, 0x11, 0x22, 0x4, 0xaa, 0xaa, 0xaa, 0xaa];
135
136 let (frame, len) =
137 DataFrame::try_read(bytes, ()).expect("Could not read DataFrame in test");
138
139 assert_eq!(len, 8);
140 assert_eq!(frame.flag, 0x01);
141 assert_eq!(frame.opt, Some(0x2211));
142 assert_eq!(frame.length, 0x04);
143 assert_eq!(frame.data, &[0xaa, 0xaa, 0xaa, 0xaa]);
144
145 let mut buf = [0u8; 8];
146 frame
147 .try_write(&mut buf, ())
148 .expect("Could not write DataFrame in test");
149 assert_eq!(&buf, bytes);
150 }
151}