1use crate::error::Error;
19use crate::utils::init;
20
21use super::{
22 EitherIter, TLVElement, TLVSequenceIter, TLVSequenceTLVIter, TLVTag, TLVValue, TLVValueType,
23 TLVWrite, TLV,
24};
25
26pub use builder::*;
27pub use container::*;
28pub use maybe::*;
29pub use octets::*;
30pub use slice::*;
31pub use str::*;
32
33mod array;
34mod bitflags;
35mod builder;
36mod container;
37mod maybe;
38mod octets;
39mod primitive;
40mod slice;
41mod str;
42mod vec;
43
44pub trait FromTLV<'a>: Sized + 'a {
47 fn from_tlv(element: &TLVElement<'a>) -> Result<Self, Error>;
49
50 fn init_from_tlv(element: TLVElement<'a>) -> impl init::Init<Self, Error> {
53 unsafe {
54 init::init_from_closure(move |slot| {
55 core::ptr::write(slot, Self::from_tlv(&element)?);
56
57 Ok(())
58 })
59 }
60 }
61
62 fn nullable_from_tlv(element: &TLVElement<'a>) -> Result<Self, Error> {
68 Self::from_tlv(element)
69 }
70
71 fn init_nullable_from_tlv(element: TLVElement<'a>) -> impl init::Init<Self, Error> {
78 unsafe {
79 init::init_from_closure(move |slot| {
80 core::ptr::write(slot, Self::nullable_from_tlv(&element)?);
81
82 Ok(())
83 })
84 }
85 }
86}
87
88pub trait ToTLV {
91 fn to_tlv<W: TLVWrite>(&self, tag: &TLVTag, tw: W) -> Result<(), Error>;
93
94 fn tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>>;
97
98 fn nullable_to_tlv<W: TLVWrite>(&self, tag: &TLVTag, tw: W) -> Result<(), Error> {
104 self.to_tlv(tag, tw)
105 }
106
107 fn nullable_tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
114 self.tlv_iter(tag)
115 }
116}
117
118impl<T> ToTLV for &T
119where
120 T: ToTLV,
121{
122 fn to_tlv<W: TLVWrite>(&self, tag: &TLVTag, tw: W) -> Result<(), Error> {
123 (*self).to_tlv(tag, tw)
124 }
125
126 fn tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
127 (*self).tlv_iter(tag)
128 }
129
130 fn nullable_to_tlv<W: TLVWrite>(&self, tag: &TLVTag, tw: W) -> Result<(), Error> {
131 (*self).nullable_to_tlv(tag, tw)
132 }
133
134 fn nullable_tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
135 (*self).nullable_tlv_iter(tag)
136 }
137}
138
139impl<'a> FromTLV<'a> for TLVElement<'a> {
140 fn from_tlv(element: &TLVElement<'a>) -> Result<Self, Error> {
141 Ok(element.clone())
142 }
143}
144
145impl ToTLV for TLVElement<'_> {
146 fn to_tlv<W: TLVWrite>(&self, tag: &TLVTag, mut tw: W) -> Result<(), Error> {
147 if self.is_empty() {
148 Ok(())
151 } else {
152 tw.raw_value(tag, self.control()?.value_type, self.raw_value()?)
153 }
154 }
155
156 fn tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
157 TLVElementTLVIter::Start(tag, self.clone())
158 }
159}
160
161enum TLVElementTLVIter<'a> {
162 Start(TLVTag, TLVElement<'a>),
163 Seq(TLVSequenceTLVIter<'a>),
164 Finished,
165}
166
167impl<'a> Iterator for TLVElementTLVIter<'a> {
168 type Item = Result<TLV<'a>, Error>;
169
170 fn next(&mut self) -> Option<Self::Item> {
171 match core::mem::replace(self, Self::Finished) {
172 TLVElementTLVIter::Start(tag, elem) => {
173 if elem.is_empty() {
174 None
177 } else {
178 let value = elem.value().map(|value| TLV::new(tag, value));
179
180 if let Ok(seq) = elem.container() {
181 *self = Self::Seq(seq.tlv_iter());
182 } else {
183 *self = TLVElementTLVIter::Finished;
184 }
185
186 Some(value)
187 }
188 }
189 TLVElementTLVIter::Seq(mut iter) => {
190 if let Some(value) = iter.next() {
191 *self = TLVElementTLVIter::Seq(iter);
192 Some(value)
193 } else {
194 Some(Ok(TLV::end_container()))
195 }
196 }
197 TLVElementTLVIter::Finished => None,
198 }
199 }
200}
201
202impl<'a> FromTLV<'a> for TLVValue<'a> {
203 fn from_tlv(element: &TLVElement<'a>) -> Result<Self, Error> {
204 element.value()
205 }
206}
207
208impl ToTLV for TLVValue<'_> {
209 fn to_tlv<W: TLVWrite>(&self, tag: &TLVTag, mut tw: W) -> Result<(), Error> {
210 tw.tlv(tag, self)
211 }
212
213 fn tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
214 TLV::new(tag, self.clone()).into_tlv_iter()
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 use core::fmt::Debug;
221 use core::mem::MaybeUninit;
222
223 use rs_matter_macros::{FromTLV, ToTLV};
224
225 use crate::tlv::{Octets, TLVElement, TLV};
226 use crate::utils::init::InitMaybeUninit;
227 use crate::utils::storage::WriteBuf;
228
229 use super::{FromTLV, OctetStr, TLVTag, ToTLV};
230
231 fn test_from_tlv<'a, T: FromTLV<'a> + PartialEq + Debug>(data: &'a [u8], expected: T) {
232 let root = TLVElement::new(data);
233 let test = T::from_tlv(&root).unwrap();
234 ::core::assert_eq!(test, expected);
235
236 let test_init = T::init_from_tlv(root);
237
238 let mut test = MaybeUninit::<T>::uninit();
239
240 let test = test.try_init_with(test_init).unwrap();
241
242 ::core::assert_eq!(*test, expected);
243 }
244
245 fn test_to_tlv<T: ToTLV>(t: T, expected: &[u8]) {
246 let mut buf = [0; 20];
247 let mut tw = WriteBuf::new(&mut buf);
248
249 t.to_tlv(&TLVTag::Anonymous, &mut tw).unwrap();
250
251 assert_eq!(tw.as_slice(), expected);
252
253 tw.reset();
254
255 let mut iter = t
256 .tlv_iter(TLVTag::Anonymous)
257 .flat_map(TLV::result_into_bytes_iter);
258 loop {
259 match iter.next() {
260 Some(Ok(byte)) => tw.append(&[byte]).unwrap(),
261 None => break,
262 _ => panic!("Error in iterator"),
263 }
264 }
265
266 ::core::assert_eq!(tw.as_slice(), expected);
267 }
268
269 #[derive(ToTLV, Debug)]
270 struct TestDerive {
271 a: u16,
272 b: u32,
273 }
274
275 #[test]
276 fn test_derive_totlv() {
277 test_to_tlv(
278 TestDerive {
279 a: 0x1010,
280 b: 0x20202020,
281 },
282 &[21, 37, 0, 0x10, 0x10, 38, 1, 0x20, 0x20, 0x20, 0x20, 24],
283 );
284 }
285
286 #[derive(FromTLV, Debug, PartialEq)]
287 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
288 struct TestDeriveSimple {
289 a: u16,
290 b: u32,
291 }
292
293 #[test]
294 fn test_derive_fromtlv() {
295 test_from_tlv(
296 &[21, 37, 0, 10, 0, 38, 1, 20, 0, 0, 0, 24],
297 TestDeriveSimple { a: 10, b: 20 },
298 );
299 }
300
301 #[derive(FromTLV, Debug, PartialEq)]
302 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
303 #[tlvargs(lifetime = "'a")]
304 struct TestDeriveStr<'a> {
305 a: u16,
306 b: OctetStr<'a>,
307 }
308
309 #[test]
310 fn test_derive_fromtlv_str() {
311 test_from_tlv(
312 &[21, 37, 0, 10, 0, 0x30, 0x01, 0x03, 10, 11, 12, 0],
313 TestDeriveStr {
314 a: 10,
315 b: Octets(&[10, 11, 12]),
316 },
317 );
318 }
319
320 #[derive(FromTLV, Debug, PartialEq)]
321 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
322 struct TestDeriveOption {
323 a: u16,
324 b: Option<u16>,
325 c: Option<u16>,
326 }
327
328 #[test]
329 fn test_derive_fromtlv_option() {
330 test_from_tlv(
331 &[21, 37, 0, 10, 0, 37, 2, 11, 0],
332 TestDeriveOption {
333 a: 10,
334 b: None,
335 c: Some(11),
336 },
337 );
338 }
339
340 #[derive(FromTLV, ToTLV, Debug, PartialEq)]
341 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
342 struct TestDeriveFabScoped {
343 a: u16,
344 #[tagval(0xFE)]
345 fab_idx: u16,
346 }
347
348 #[test]
349 fn test_derive_fromtlv_fab_scoped() {
350 test_from_tlv(
351 &[21, 37, 0, 10, 0, 37, 0xFE, 11, 0],
352 TestDeriveFabScoped { a: 10, fab_idx: 11 },
353 );
354 }
355
356 #[test]
357 fn test_derive_totlv_fab_scoped() {
358 test_to_tlv(
359 TestDeriveFabScoped { a: 20, fab_idx: 3 },
360 &[21, 36, 0, 20, 36, 0xFE, 3, 24],
361 );
362 }
363
364 #[derive(ToTLV, FromTLV, PartialEq, Debug)]
365 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
366 enum TestDeriveEnum {
367 ValueA(u32),
368 ValueB(u32),
369 }
370
371 #[test]
372 fn test_derive_from_to_tlv_enum() {
373 test_from_tlv(&[21, 36, 0, 100, 24, 0], TestDeriveEnum::ValueA(100));
375
376 test_to_tlv(TestDeriveEnum::ValueB(10), &[21, 36, 1, 10, 24]);
378 }
379}