rs_matter/tlv/read.rs
1/*
2 *
3 * Copyright (c) 2024-2026 Project CHIP Authors
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18use core::{cmp::Ordering, fmt};
19
20use crate::error::{Error, ErrorCode};
21
22use super::{pad, FromTLV, TLVControl, TLVTag, TLVTagType, TLVValue, TLVValueType, TLV};
23
24/// A newtype for reading TLV-encoded data from Rust `&[u8]` slices.
25///
26/// Semantically, a `TLVElement` is just a byte slice of TLV-encoded data/stream, and the methods provided by this therefore
27/// allow to parse - on the fly - the byte slice as TLV.
28///
29/// Note also, that - as per the Matter Core Spec:
30/// - A valid TLV stream always represents a SINGLE TLV element (hence why this type is named `TLVElement` and why we claim
31/// that it represents also a whole TLV stream)
32/// - If there is a need to encode more than one TLV element, they should be encoded in a TLV container (array, list or struct),
33/// hence we end up again with a single TLV element, which represents the whole container.
34///
35/// Parsing/reading/validating the TLV of the slice represented by a `TLVElement` is done on-demand. What this means is that:
36/// - `TLVElement::new(slice)` always succeeds, even when the passed slice contains invalid TLV data
37/// - As the various methods of `TLVElement` type are called, the data in the slice is parsed and validated on the fly. Hence why all methods
38/// on `TLVElement` except `is_empty` are fallible.
39///
40/// A TLV element can currently be constructed from an empty `&[]` slice, but the empty slice does not actually represent a TLV element,
41/// so all methods except `TLVElement::is_empty` would fail on a `TLVElement` constructed from an empty slice. The only reason why empty slices
42/// are currently allowed is to simplify the `FromTLV` trait a bit by representing data which was not found (i.e. optional data in TLV structures)
43/// as a TLVElement with an empty slice.
44///
45/// The design approach from above (on-demand parsing/validation) trades memory efficiency for extra computations, in that by simply decorating
46/// a Rust `&[u8]` slice anbd post-poning everything else post-construction it ensures the size of a `TLVElement` is equal to the size of the wrapped
47/// `&[u8]` slice - i.e., a regular Rust fat pointer (8 bytes on 32 bit archs and 16 bytes on 64 bit archs).
48///
49/// Furthermore, all accompanying types of `TLVElement`, like `TLVSequence`, `TLVContainerIter` and `TLVArray` are also just newtypes over byte slices
50/// and therefore just as small.
51///
52/// (Keeping interim data is still optionally possible, by using the `TLV::tag` and `TLV::value`
53/// methods to read the tag and value of a TLV as enums.)
54///
55/// As for representing the encoded TLV stream itself as a raw `&[u8]` slice - this trivializes the traversal of the stream
56/// as the stream traversal is represented as returning sub-slices of the original slice. It also allows `FromTLV` implementations where
57/// the data is borrowed directly from the `&[u8]` slice representing the encoded TLV stream without any data moves. Types that implement
58/// such borrowing are e.g.:
59/// - `&str` (used to represent borrowed TLV UTF-8 strings)
60/// - `Bytes<'a>` (a newtype over `&'a [u8]` - used to represent TLV octet strings)
61/// - `TLVArray`
62/// - `TLVSequence` - discussed below
63///
64/// Also, this representation naturally allows random-access to the TLV stream, which is necessary for a number of reasons:
65/// - Deserialization of TLV structs into Rust structs (with the `FromTLV` derive macro) where the order of the TLV elements
66/// of the struct is not known in advance
67/// - Delayed in-place initialization of large Rust types with `FromTLV::init_from_tlv` which requires random access for reasons
68/// beyond the possible unordering of the TLV struct elements.
69///
70/// In practice, random access - and in general - representation of the TLV stream as a `&[u8]` slice should be natural and
71/// convenient, as the TLV stream usually comes from the network UDP/TCP memory buffers of the Matter transport protocol, and
72/// these can and are borrowed as `&[u8]` slices in the upper-layer code for direct reads.
73#[derive(Clone, PartialEq, Eq, Hash)]
74#[repr(transparent)]
75pub struct TLVElement<'a>(TLVSequence<'a>);
76
77impl<'a> TLVElement<'a> {
78 /// Read a mandatory context-tagged field out of this (structure) element.
79 ///
80 /// Taking the tag as a runtime argument rather than baking it into the
81 /// caller is what keeps this cheap in code size: the generated per-field
82 /// accessors are otherwise structurally identical yet monomorphise
83 /// separately, so the same TLV walk is emitted once per *field* instead of
84 /// once per *type*.
85 pub fn read<T: FromTLV<'a>>(&self, ctx: u8) -> Result<T, Error> {
86 T::from_tlv(&self.structure()?.ctx(ctx)?)
87 }
88
89 /// Read an optional context-tagged field out of this (structure) element.
90 ///
91 /// Returns `None` when the field is absent. See [`Self::read`] for why the
92 /// tag is a runtime argument.
93 pub fn read_opt<T: FromTLV<'a>>(&self, ctx: u8) -> Result<Option<T>, Error> {
94 let element = self.structure()?.find_ctx(ctx)?;
95
96 if element.is_empty() {
97 Ok(None)
98 } else {
99 Ok(Some(T::from_tlv(&element)?))
100 }
101 }
102
103 /// Create a new `TLVElement` from a byte slice, where the byte slice contains an encoded TLV stream (a TLV element).
104 #[inline(always)]
105 pub const fn new(data: &'a [u8]) -> Self {
106 Self(TLVSequence(data))
107 }
108
109 /// Return `true` if the wrapped byte slice is the empty `&[]` slice.
110 /// Empty byte slices do not represent valid TLV data, as the TLV data should be a valid TLV element,
111 /// yet they are useful when implementing the `FromTLV` trait.
112 #[inline(always)]
113 pub fn is_empty(&self) -> bool {
114 self.0 .0.is_empty()
115 }
116
117 /// Return `Some(self)` if the wrapped byte slice is not empty, `None` otherwise.
118 pub fn non_empty(&self) -> Option<&TLVElement<'a>> {
119 if self.is_empty() {
120 None
121 } else {
122 Some(self)
123 }
124 }
125
126 /// Return a copy of the wrapped TLV byte slice.
127 #[inline(always)]
128 pub const fn raw_data(&self) -> &'a [u8] {
129 self.0 .0
130 }
131
132 /// Return the TLV control byte of the first TLV in the slice.
133 ///
134 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the first byte of the slice does
135 /// not represent a valid TLV control byte or if the wrapped byte slice is empty.
136 #[inline(always)]
137 pub fn control(&self) -> Result<TLVControl, Error> {
138 self.0.control()
139 }
140
141 /// Return a sub-slice of the wrapped byte slice that designates the encoded value
142 /// of this `TLVElement` (i.e. the raw "value" aspect of the Tag-Length-Value encoding)
143 ///
144 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
145 /// contains malformed TLV data.
146 ///
147 /// For getting a parsed value, use `value` or any of the other helper methods that
148 /// retrieve a value of a certain type.
149 #[inline(always)]
150 pub fn raw_value(&self) -> Result<&'a [u8], Error> {
151 self.0.raw_value()
152 }
153
154 /// Return a `TLV` struct representing the tag and value of this `TLVElement`.
155 /// This method is a convenience method that combines the `tag` and `value` methods.
156 pub fn tlv(&self) -> Result<TLV<'a>, Error> {
157 Ok(TLV {
158 tag: self.tag()?,
159 value: self.value()?,
160 })
161 }
162
163 /// Return a `TLVTag` enum representing the tag of this `TLVElement`.
164 ///
165 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV
166 /// byte slice contains malformed TLV data.
167 #[inline(always)]
168 pub fn tag(&self) -> Result<TLVTag, Error> {
169 let tag_type = self.control()?.tag_type;
170
171 let slice = self
172 .0
173 .tag_start()?
174 .get(..tag_type.size())
175 .ok_or(ErrorCode::TLVTypeMismatch)?;
176
177 let tag = match tag_type {
178 TLVTagType::Anonymous => TLVTag::Anonymous,
179 TLVTagType::Context => TLVTag::Context(slice[0]),
180 TLVTagType::CommonPrf16 => {
181 TLVTag::CommonPrf16(u16::from_le_bytes(unwrap!(slice.try_into())))
182 }
183 TLVTagType::CommonPrf32 => {
184 TLVTag::CommonPrf32(u32::from_le_bytes(unwrap!(slice.try_into())))
185 }
186 TLVTagType::ImplPrf16 => {
187 TLVTag::ImplPrf16(u16::from_le_bytes(unwrap!(slice.try_into())))
188 }
189 TLVTagType::ImplPrf32 => {
190 TLVTag::ImplPrf32(u32::from_le_bytes(unwrap!(slice.try_into())))
191 }
192 TLVTagType::FullQual48 => TLVTag::FullQual48 {
193 vendor_id: u16::from_le_bytes([slice[0], slice[1]]),
194 profile: u16::from_le_bytes([slice[2], slice[3]]),
195 tag: u16::from_le_bytes([slice[4], slice[5]]),
196 },
197 TLVTagType::FullQual64 => TLVTag::FullQual64 {
198 vendor_id: u16::from_le_bytes([slice[0], slice[1]]),
199 profile: u16::from_le_bytes([slice[2], slice[3]]),
200 tag: u32::from_le_bytes([slice[4], slice[5], slice[6], slice[7]]),
201 },
202 };
203
204 Ok(tag)
205 }
206
207 /// Return a `TLVValue` enum representing the value of this `TLVElement`.
208 ///
209 /// Note that if the TLV element is a container, the return `TLV` value would only deisgnate
210 /// the container type (struct, array or list) and not the actual content of the container.
211 pub fn value(&self) -> Result<TLVValue<'a>, Error> {
212 let control = self.control()?;
213
214 let slice = self.0.container_value(control)?;
215
216 let value = match control.value_type {
217 TLVValueType::S8 => TLVValue::S8(i8::from_le_bytes(unwrap!(slice.try_into()))),
218 TLVValueType::S16 => TLVValue::S16(i16::from_le_bytes(unwrap!(slice.try_into()))),
219 TLVValueType::S32 => TLVValue::S32(i32::from_le_bytes(unwrap!(slice.try_into()))),
220 TLVValueType::S64 => TLVValue::S64(i64::from_le_bytes(unwrap!(slice.try_into()))),
221 TLVValueType::U8 => TLVValue::U8(u8::from_le_bytes(unwrap!(slice.try_into()))),
222 TLVValueType::U16 => TLVValue::U16(u16::from_le_bytes(unwrap!(slice.try_into()))),
223 TLVValueType::U32 => TLVValue::U32(u32::from_le_bytes(unwrap!(slice.try_into()))),
224 TLVValueType::U64 => TLVValue::U64(u64::from_le_bytes(unwrap!(slice.try_into()))),
225 TLVValueType::False => TLVValue::False,
226 TLVValueType::True => TLVValue::True,
227 TLVValueType::F32 => TLVValue::F32(f32::from_le_bytes(unwrap!(slice.try_into()))),
228 TLVValueType::F64 => TLVValue::F64(f64::from_le_bytes(unwrap!(slice.try_into()))),
229 TLVValueType::Utf8l => TLVValue::Utf8l(
230 core::str::from_utf8(slice).map_err(|_| ErrorCode::TLVTypeMismatch)?,
231 ),
232 TLVValueType::Utf16l => TLVValue::Utf16l(
233 core::str::from_utf8(slice).map_err(|_| ErrorCode::TLVTypeMismatch)?,
234 ),
235 TLVValueType::Utf32l => TLVValue::Utf32l(
236 core::str::from_utf8(slice).map_err(|_| ErrorCode::TLVTypeMismatch)?,
237 ),
238 TLVValueType::Utf64l => TLVValue::Utf64l(
239 core::str::from_utf8(slice).map_err(|_| ErrorCode::TLVTypeMismatch)?,
240 ),
241 TLVValueType::Str8l => TLVValue::Str8l(slice),
242 TLVValueType::Str16l => TLVValue::Str16l(slice),
243 TLVValueType::Str32l => TLVValue::Str32l(slice),
244 TLVValueType::Str64l => TLVValue::Str64l(slice),
245 TLVValueType::Null => TLVValue::Null,
246 TLVValueType::Struct => TLVValue::Struct,
247 TLVValueType::Array => TLVValue::Array,
248 TLVValueType::List => TLVValue::List,
249 TLVValueType::EndCnt => TLVValue::EndCnt,
250 };
251
252 Ok(value)
253 }
254
255 /// Return the value of this TLV element as an `i8`.
256 ///
257 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
258 /// contains malformed TLV data.
259 ///
260 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
261 /// a TLV S8 value.
262 pub fn i8(&self) -> Result<i8, Error> {
263 let control = self.control()?;
264
265 if matches!(control.value_type, TLVValueType::S8) {
266 Ok(i8::from_le_bytes(
267 self.0
268 .value(control)?
269 .try_into()
270 .map_err(|_| ErrorCode::InvalidData)?,
271 ))
272 } else {
273 Err(ErrorCode::TLVTypeMismatch.into())
274 }
275 }
276
277 /// Return the value of this TLV element as a `u8`.
278 ///
279 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
280 /// contains malformed TLV data.
281 ///
282 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
283 /// a TLV U8 value.
284 pub fn u8(&self) -> Result<u8, Error> {
285 let control = self.control()?;
286
287 if matches!(control.value_type, TLVValueType::U8) {
288 Ok(u8::from_le_bytes(
289 self.0
290 .value(control)?
291 .try_into()
292 .map_err(|_| ErrorCode::InvalidData)?,
293 ))
294 } else {
295 Err(ErrorCode::TLVTypeMismatch.into())
296 }
297 }
298
299 /// Return the value of this TLV element as an `i16`.
300 ///
301 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
302 /// contains malformed TLV data.
303 ///
304 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
305 /// a TLV S8 or S16 value.
306 pub fn i16(&self) -> Result<i16, Error> {
307 let control = self.control()?;
308
309 if matches!(control.value_type, TLVValueType::S16) {
310 Ok(i16::from_le_bytes(
311 self.0
312 .value(control)?
313 .try_into()
314 .map_err(|_| ErrorCode::InvalidData)?,
315 ))
316 } else {
317 self.i8().map(|a| a.into())
318 }
319 }
320
321 /// Return the value of this TLV element as a `u16`.
322 ///
323 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
324 /// contains malformed TLV data.
325 ///
326 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
327 /// a TLV U8 or U16 value.
328 pub fn u16(&self) -> Result<u16, Error> {
329 let control = self.control()?;
330
331 if matches!(control.value_type, TLVValueType::U16) {
332 Ok(u16::from_le_bytes(
333 self.0
334 .value(control)?
335 .try_into()
336 .map_err(|_| ErrorCode::InvalidData)?,
337 ))
338 } else {
339 self.u8().map(|a| a.into())
340 }
341 }
342
343 /// Return the value of this TLV element as an `i32`.
344 ///
345 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
346 /// contains malformed TLV data.
347 ///
348 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
349 /// a TLV S8, S16 or S32 value.
350 pub fn i32(&self) -> Result<i32, Error> {
351 let control = self.control()?;
352
353 if matches!(control.value_type, TLVValueType::S32) {
354 Ok(i32::from_le_bytes(
355 self.0
356 .value(control)?
357 .try_into()
358 .map_err(|_| ErrorCode::InvalidData)?,
359 ))
360 } else {
361 self.i16().map(|a| a.into())
362 }
363 }
364
365 /// Return the value of this TLV element as a `u32`.
366 ///
367 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
368 /// contains malformed TLV data.
369 ///
370 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
371 /// a TLV U8, U16 or U32 value.
372 pub fn u32(&self) -> Result<u32, Error> {
373 let control = self.control()?;
374
375 if matches!(control.value_type, TLVValueType::U32) {
376 Ok(u32::from_le_bytes(
377 self.0
378 .value(control)?
379 .try_into()
380 .map_err(|_| ErrorCode::InvalidData)?,
381 ))
382 } else {
383 self.u16().map(|a| a.into())
384 }
385 }
386
387 /// Return the value of this TLV element as an `i64`.
388 ///
389 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
390 /// contains malformed TLV data.
391 ///
392 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
393 /// a TLV S8, S16, S32 or S64 value.
394 pub fn i64(&self) -> Result<i64, Error> {
395 let control = self.control()?;
396
397 if matches!(control.value_type, TLVValueType::S64) {
398 Ok(i64::from_le_bytes(
399 self.0
400 .value(control)?
401 .try_into()
402 .map_err(|_| ErrorCode::InvalidData)?,
403 ))
404 } else {
405 self.i32().map(|a| a.into())
406 }
407 }
408
409 /// Return the value of this TLV element as a `u64`.
410 ///
411 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
412 /// contains malformed TLV data.
413 ///
414 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
415 /// a TLV U8, U16, U32 or U64 value.
416 pub fn u64(&self) -> Result<u64, Error> {
417 let control = self.control()?;
418
419 if matches!(control.value_type, TLVValueType::U64) {
420 Ok(u64::from_le_bytes(
421 self.0
422 .value(control)?
423 .try_into()
424 .map_err(|_| ErrorCode::InvalidData)?,
425 ))
426 } else {
427 self.u32().map(|a| a.into())
428 }
429 }
430
431 /// Return the value of this TLV element as an `f32`.
432 ///
433 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
434 /// contains malformed TLV data.
435 ///
436 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
437 /// a TLV F32 value.
438 pub fn f32(&self) -> Result<f32, Error> {
439 let control = self.control()?;
440
441 if matches!(control.value_type, TLVValueType::F32) {
442 Ok(f32::from_le_bytes(
443 self.0
444 .value(control)?
445 .try_into()
446 .map_err(|_| ErrorCode::InvalidData)?,
447 ))
448 } else {
449 Err(ErrorCode::TLVTypeMismatch.into())
450 }
451 }
452
453 /// Return the value of this TLV element as an `f64`.
454 ///
455 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
456 /// contains malformed TLV data.
457 ///
458 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
459 /// a TLV F64 value.
460 pub fn f64(&self) -> Result<f64, Error> {
461 let control = self.control()?;
462
463 if matches!(control.value_type, TLVValueType::F64) {
464 Ok(f64::from_le_bytes(
465 self.0
466 .value(control)?
467 .try_into()
468 .map_err(|_| ErrorCode::InvalidData)?,
469 ))
470 } else {
471 Err(ErrorCode::TLVTypeMismatch.into())
472 }
473 }
474
475 /// Return the value of this TLV element as a byte slice.
476 ///
477 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
478 /// contains malformed TLV data.
479 ///
480 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
481 /// a TLV Octet String.
482 pub fn str(&self) -> Result<&'a [u8], Error> {
483 let control = self.control()?;
484
485 if !control.value_type.is_str() {
486 Err(ErrorCode::Invalid)?;
487 }
488
489 self.0.value(control)
490 }
491
492 /// Return the value of this TLV element as a UTF-8 string.
493 ///
494 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
495 /// contains malformed TLV data.
496 ///
497 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
498 /// a TLV UTF-8 String.
499 pub fn utf8(&self) -> Result<&'a str, Error> {
500 let control = self.control()?;
501
502 if !control.value_type.is_utf8() {
503 Err(ErrorCode::Invalid)?;
504 }
505
506 core::str::from_utf8(self.0.value(control)?).map_err(|_| ErrorCode::InvalidData.into())
507 }
508
509 /// Return the value of this TLV element as a UTF-16 string.
510 ///
511 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
512 /// contains malformed TLV data.
513 ///
514 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
515 /// a TLV UTF-8 String or a TLV octet string.
516 pub fn octets(&self) -> Result<&'a [u8], Error> {
517 let control = self.control()?;
518
519 if control.value_type.variable_size_len() == 0 {
520 Err(ErrorCode::Invalid)?;
521 }
522
523 self.0.value(control)
524 }
525
526 /// Return the value of this TLV element as a UTF-16 string.
527 ///
528 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
529 /// contains malformed TLV data.
530 ///
531 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
532 /// a TLV boolean.
533 pub fn bool(&self) -> Result<bool, Error> {
534 let control = self.control()?;
535
536 match control.value_type {
537 TLVValueType::False => Ok(false),
538 TLVValueType::True => Ok(true),
539 _ => Err(ErrorCode::TLVTypeMismatch.into()),
540 }
541 }
542
543 /// Return `true` if this TLV element is as a container (i.e., a struct, array or list).
544 ///
545 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
546 /// contains malformed TLV data.
547 pub fn is_container(&self) -> Result<bool, Error> {
548 Ok(self.control()?.value_type.is_container())
549 }
550
551 /// Confirm that this TLV element contains a TLV null value.
552 ///
553 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
554 /// contains malformed TLV data.
555 ///
556 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
557 /// a TLV null value.
558 pub fn null(&self) -> Result<(), Error> {
559 if matches!(self.control()?.value_type, TLVValueType::Null) {
560 Ok(())
561 } else {
562 Err(ErrorCode::InvalidData.into())
563 }
564 }
565
566 /// Return the content of the struct container represented by this TLV element.
567 ///
568 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
569 /// contains malformed TLV data.
570 ///
571 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
572 /// a TLV struct.
573 pub fn structure(&self) -> Result<TLVSequence<'a>, Error> {
574 self.r#struct()
575 }
576
577 /// Return the content of the struct container represented by this TLV element.
578 ///
579 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
580 /// contains malformed TLV data.
581 ///
582 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
583 /// a TLV struct.
584 ///
585 /// (Same as method `structure` but with a special name to ease the `FromTLV` trait derivation for
586 /// user types.)
587 pub fn r#struct(&self) -> Result<TLVSequence<'a>, Error> {
588 if matches!(self.control()?.value_type, TLVValueType::Struct) {
589 self.0.next_enter()
590 } else {
591 Err(ErrorCode::TLVTypeMismatch.into())
592 }
593 }
594
595 /// Return the content of the array container represented by this TLV element.
596 ///
597 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
598 /// contains malformed TLV data.
599 ///
600 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
601 /// a TLV array.
602 pub fn array(&self) -> Result<TLVSequence<'a>, Error> {
603 if matches!(self.control()?.value_type, TLVValueType::Array) {
604 self.0.next_enter()
605 } else {
606 Err(ErrorCode::InvalidData.into())
607 }
608 }
609
610 /// Return the content of the list container represented by this TLV element.
611 ///
612 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
613 /// contains malformed TLV data.
614 ///
615 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
616 /// a TLV list.
617 pub fn list(&self) -> Result<TLVSequence<'a>, Error> {
618 if matches!(self.control()?.value_type, TLVValueType::List) {
619 self.0.next_enter()
620 } else {
621 Err(ErrorCode::TLVTypeMismatch.into())
622 }
623 }
624
625 /// Return the content of the container (array, struct or list) represented by this TLV element.
626 ///
627 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
628 /// contains malformed TLV data.
629 ///
630 /// Returns an error with code `ErrorCode::InvalidData` if the value of the TLV element is not
631 /// a TLV container.
632 pub fn container(&self) -> Result<TLVSequence<'a>, Error> {
633 if matches!(
634 self.control()?.value_type,
635 TLVValueType::List | TLVValueType::Array | TLVValueType::Struct
636 ) {
637 self.0.next_enter()
638 } else {
639 Err(ErrorCode::TLVTypeMismatch.into())
640 }
641 }
642
643 /// Confirm that this TLV element is tagged with the anonymous tag (`TLVTag::Anonymous`).
644 ///
645 /// Returns an error with code `ErrorCode::TLVTypeMismatch` if the wrapped TLV byte slice
646 /// contains malformed TLV data.
647 ///
648 /// Returns an error with code `ErrorCode::InvalidData` if the tag of the TLV element is not
649 /// the anonymous tag.
650 pub fn confirm_anon(&self) -> Result<(), Error> {
651 if matches!(self.control()?.tag_type, TLVTagType::Anonymous) {
652 Ok(())
653 } else {
654 Err(ErrorCode::TLVTypeMismatch.into())
655 }
656 }
657
658 /// Retrieve the context ID of the element.
659 /// If element is not tagged with a context tag, the method will return an error.
660 pub fn ctx(&self) -> Result<u8, Error> {
661 Ok(self.try_ctx()?.ok_or(ErrorCode::TLVTypeMismatch)?)
662 }
663
664 /// Retrieve the context ID of the element.
665 /// If element is not tagged with a context tag, the method will return `None`.
666 pub fn try_ctx(&self) -> Result<Option<u8>, Error> {
667 let control = self.control()?;
668
669 if matches!(control.tag_type, TLVTagType::Context) {
670 Ok(Some(
671 *self
672 .0
673 .tag(control.tag_type)?
674 .first()
675 .ok_or(ErrorCode::TLVTypeMismatch)?,
676 ))
677 } else {
678 Ok(None)
679 }
680 }
681
682 fn fmt(&self, indent: usize, f: &mut fmt::Formatter) -> fmt::Result {
683 pad(indent, f)?;
684
685 let tag = self.tag().map_err(|_| fmt::Error)?;
686
687 tag.fmt(f)?;
688
689 if !matches!(tag.tag_type(), TLVTagType::Anonymous) {
690 write!(f, ": ")?;
691 }
692
693 let value = self.value().map_err(|_| fmt::Error)?;
694
695 value.fmt(f)?;
696
697 if value.value_type().is_container() {
698 let mut empty = true;
699
700 for (index, elem) in self.container().map_err(|_| fmt::Error)?.iter().enumerate() {
701 if index > 0 {
702 writeln!(f, ",")?;
703 } else {
704 writeln!(f)?;
705 }
706
707 elem.map_err(|_| fmt::Error)?.fmt(indent + 2, f)?;
708
709 empty = false;
710 }
711
712 if !empty {
713 writeln!(f)?;
714 pad(indent, f)?;
715 }
716
717 match value.value_type() {
718 TLVValueType::Struct => write!(f, "}}"),
719 TLVValueType::Array => write!(f, "]"),
720 TLVValueType::List => write!(f, ")"),
721 _ => unreachable!(),
722 }?;
723 }
724
725 Ok(())
726 }
727}
728
729impl fmt::Debug for TLVElement<'_> {
730 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
731 self.fmt(0, f)
732 }
733}
734
735impl fmt::Display for TLVElement<'_> {
736 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
737 self.fmt(0, f)
738 }
739}
740
741#[cfg(feature = "defmt")]
742impl defmt::Format for TLVElement<'_> {
743 fn format(&self, f: defmt::Formatter<'_>) {
744 defmt::Display2Format(self).format(f)
745 }
746}
747
748/// A newtype for iterating over the `TLVElement` "child" instances contained in `TLVElement` which is a TLV container
749/// (array, struct or list).
750/// (Internally, `TLVSequence` might be used for other purposes, but the external contract is only the one from above.)
751///
752/// Just like `TLVElement`, `TLVSequence` is a newtype over a byte slice - the byte sub-slice of the parent `TLVElement`
753/// container where its value starts.
754///
755/// Unlike `TLVElement`, `TLVSequence` - as the name suggests - represents a sequence of 0, 1 or more `TLVElements`.
756/// The only public API of `TLVSequence` however is the `iter` method which returns a `TLVContainerIter` iterator over
757/// the `TLVElement` instances in the sequence.
758#[derive(Clone, PartialEq, Eq, Hash)]
759#[repr(transparent)]
760pub struct TLVSequence<'a>(pub(crate) &'a [u8]);
761
762impl<'a> TLVSequence<'a> {
763 const EMPTY: Self = Self(&[]);
764
765 /// Return an iterator over the `TLVElement` instances in this `TLVSequence`.
766 #[inline(always)]
767 pub fn iter(&self) -> TLVSequenceIter<'a> {
768 TLVSequenceIter::new(self.clone())
769 }
770
771 /// Return an iterator over the `TLV` instances in this `TLVSequence`.
772 ///
773 /// The difference with `iter` is that for container elements, `tlv_iter`
774 /// will return separate `TLV` instances for the container start, the container
775 /// elements and the container end, where if an element in the container is
776 /// itself a container, the algorithm will be applied recursively to the inner container.
777 pub fn tlv_iter(&self) -> TLVSequenceTLVIter<'a> {
778 TLVSequenceTLVIter::new(self.clone())
779 }
780
781 /// A convenience utility that returns the first `TLVElement` in the sequence
782 /// which is tagged with a context tag (`TLVTag::Context`) where the context ID
783 /// is matching the ID passed in the `ctx` parameter.
784 ///
785 /// If there is no TLV element tagged with a context tag with the matching ID, the method
786 /// will return an error.
787 pub fn ctx(&self, ctx: u8) -> Result<TLVElement<'a>, Error> {
788 let element = self.find_ctx(ctx)?;
789
790 if element.is_empty() {
791 Err(ErrorCode::NotFound.into())
792 } else {
793 Ok(element)
794 }
795 }
796
797 /// A convenience utility that returns the first `TLVElement` in the sequence
798 /// which is tagged with a context tag (`TLVTag::Context`) where the context ID
799 /// is matching the ID passed in the `ctx` parameter.
800 ///
801 /// If there is no TLV element tagged with a context tag with the matching ID, the method
802 /// will return an empty `TLVElement`.
803 pub fn find_ctx(&self, ctx: u8) -> Result<TLVElement<'a>, Error> {
804 for elem in self.iter() {
805 let elem = elem?;
806
807 if let Some(elem_ctx) = elem.try_ctx()? {
808 if elem_ctx == ctx {
809 return Ok(elem);
810 }
811 }
812 }
813
814 Ok(TLVElement(Self::EMPTY))
815 }
816
817 /// A convenience utility that returns the first `TLVElement` in the sequence
818 /// which is tagged with a context tag (`TLVTag::Context`) where the context ID
819 /// is equal to the ID passed in the `ctx` parameter.
820 ///
821 /// If there is no TLV element tagged with a context tag with the matching ID, the method
822 /// will return an empty TLV element.
823 ///
824 /// As a side effect of calling this method, the `TLVSequence` instance will be updated
825 /// to point to the next element after the found element, or if an element with the
826 /// provided context ID does not exist, to the first element with a bigger context ID than
827 /// the one we are looking for.
828 pub fn scan_ctx(&mut self, ctx: u8) -> Result<TLVElement<'a>, Error> {
829 self.scan_map(move |elem| {
830 if elem.is_empty() {
831 return Ok(Some(elem));
832 }
833
834 if let Some(elem_ctx) = elem.try_ctx()? {
835 match elem_ctx.cmp(&ctx) {
836 Ordering::Equal => return Ok(Some(elem)),
837 Ordering::Greater => return Ok(Some(TLVElement(Self::EMPTY))),
838 _ => (),
839 }
840 }
841
842 Ok(None)
843 })
844 }
845
846 /// A convenience utility that returns scans the elements in the sequence,
847 /// in-order and stops scanning once the provided mapping closure `f`
848 /// returns a non-empty result.
849 ///
850 /// As a side effect of calling this method, the `TLVSequence` instance will be updated
851 /// to point to the next element after the one on which the provided closure
852 /// returned a non-empty result.
853 ///
854 /// Note that the closure _must_ ultimately return a non-empty result - if for nothing else
855 /// then for the empty element that is passed to it when the sequence is exhausted,
856 /// or else the method would loop forever.
857 pub fn scan_map<F, T>(&mut self, mut f: F) -> Result<T, Error>
858 where
859 F: FnMut(TLVElement<'a>) -> Result<Option<T>, Error>,
860 {
861 loop {
862 if let Some(elem) = f(self.current()?)? {
863 return Ok(elem);
864 }
865
866 *self = self.container_next()?;
867 }
868 }
869
870 /// Return a raw byte sub-slice representing the TLV-encoded elements and only those
871 /// elements that belong to the TLV container whose elements are represented by this `TLVSequence` instance.
872 ///
873 /// This method is necessary, because both `TLVElement` instances, as well as `TLVSequence` instances - for optimization purposes -
874 /// might be constructed during iteration on slices which are technically longer than the actual TLV-encoded data
875 /// they represent.
876 ///
877 /// So in case the user is need of the actual, exact raw representation of a TLV container **value**, this method is provided.
878 #[inline(always)]
879 pub fn raw_value(&self) -> Result<&'a [u8], Error> {
880 let control = self.control()?;
881
882 self.container_value(control)
883 }
884
885 /// Return a sub-sequence representing the TLV-encoded elements after the first one on the sequence.
886 ///
887 /// As the name suggests, if the first TLV element in the sequence is a container, this method will return a sub-sequence
888 /// which corresponds to the first element INSIDE the container.
889 ///
890 /// If the sequence is empty, or the sequence contains just one element, the method will return an empty `TLVSequence`.
891 ///
892 /// Note also that this method will also return sub-sequences where the first element might be a TLV `TLVValueType::EndCnt` marker,
893 /// which - formally speaking - is not a TLVElement, but a TLV control byte that marks the end of a container.
894 fn next_enter(&self) -> Result<Self, Error> {
895 if self.0.is_empty() {
896 return Ok(Self::EMPTY);
897 }
898
899 let control = self.control()?;
900
901 Ok(Self(self.next_start(control)?))
902 }
903
904 /// Return a sub-sequence representing the TLV-encoded elements after the first one on the sequence.
905 ///
906 /// As the name suggests, if the first TLV element in the sequence is a container, this method will return a sub-sequence
907 /// which corresponds to the elements AFTER the container element (i.e., the method "skips over" the elements of the container element).
908 ///
909 /// If the sequence is empty or the sequence starts with a container-end control byte, the method will return the current sequence.
910 fn container_next(&self) -> Result<Self, Error> {
911 if self.0.is_empty() {
912 return Ok(Self::EMPTY);
913 }
914
915 let control = self.control()?;
916
917 if control.value_type.is_container_end() {
918 control.confirm_container_end()?;
919
920 return Ok(self.clone());
921 }
922
923 let mut next = self.next_enter()?;
924
925 if control.value_type.is_container() {
926 let mut level = 1;
927
928 while level > 0 {
929 let control = next.control()?;
930
931 if control.value_type.is_container_end() {
932 control.confirm_container_end()?;
933 level -= 1;
934 } else if control.value_type.is_container() {
935 level += 1;
936 }
937
938 next = next.next_enter()?;
939 }
940 }
941
942 Ok(next)
943 }
944
945 /// Return the first TLV element in the sequence.
946 /// If the sequence is empty, or if the sequence starts with a container-end TLV,
947 /// an empty element will be returned.
948 fn current(&self) -> Result<TLVElement<'a>, Error> {
949 if self.0.is_empty() {
950 return Ok(TLVElement(Self::EMPTY));
951 }
952
953 let control = self.control()?;
954
955 if control.value_type.is_container_end() {
956 control.confirm_container_end()?;
957
958 return Ok(TLVElement(Self::EMPTY));
959 }
960
961 Ok(TLVElement::new(self.0))
962 }
963
964 /// Return the TLV control byte of the first TLV in the sequence.
965 /// If the sequence is empty, an error will be returned.
966 #[inline(always)]
967 fn control(&self) -> Result<TLVControl, Error> {
968 TLVControl::parse(*self.0.first().ok_or(ErrorCode::TLVTypeMismatch)?)
969 }
970
971 /// Return a sub-slice of the wrapped byte slice that designates the START of the tag payload
972 /// of the first TLV in the sequence.
973 ///
974 /// If there is no tag payload (i.e., the tag is of type `TLVTagType::Anonymous`), the returned sub-slice
975 /// will designate the start of the TLV element value or value length.
976 #[inline(always)]
977 fn tag_start(&self) -> Result<&'a [u8], Error> {
978 Ok(self.0.get(1..).ok_or(ErrorCode::TLVTypeMismatch)?)
979 }
980
981 /// Return a sub-slice of the wrapped byte slice that designates the exact raw slice representing the tag payload
982 /// of the first TLV in the sequence.
983 ///
984 /// If there is no tag payload (i.e., the tag is of type `TLVTagType::Anonymous`), the returned sub-slice
985 /// will be the empty slice.
986 #[inline(always)]
987 fn tag(&self, tag_type: TLVTagType) -> Result<&'a [u8], Error> {
988 Ok(self
989 .tag_start()?
990 .get(..tag_type.size())
991 .ok_or(ErrorCode::TLVTypeMismatch)?)
992 }
993
994 /// Return a sub-slice of the wrapped byte slice that designates the START of the value length field
995 /// of the first TLV in the sequence.
996 ///
997 /// The value length field is the field that designates the length of the value of the TLV element.
998 /// If the TLV element control byte designates an element with a fixed size or a container element,
999 /// the returned sub-slice will designate the start of the value field.
1000 #[inline(always)]
1001 fn value_len_start(&self, tag_type: TLVTagType) -> Result<&'a [u8], Error> {
1002 Ok(unwrap!(self.tag_start())
1003 .get(tag_type.size()..)
1004 .ok_or(ErrorCode::TLVTypeMismatch)?)
1005 }
1006
1007 /// Return a sub-slice of the wrapped byte slice that designates the START of the value field of
1008 /// the first TLV in the sequence.
1009 ///
1010 /// The value field is the field that designates the actual value of the TLV element.
1011 #[inline(always)]
1012 fn value_start(&self, control: TLVControl) -> Result<&'a [u8], Error> {
1013 Ok(self
1014 .value_len_start(control.tag_type)?
1015 .get(control.value_type.variable_size_len()..)
1016 .ok_or(ErrorCode::TLVTypeMismatch)?)
1017 }
1018
1019 /// Return a sub-slice of the wrapped byte slice that designates the exact raw slice representing the value payload
1020 /// of the first TLV element in the sequence.
1021 ///
1022 /// For container elements, this method will return the empty slice. Use `container_value` (a more computationally expensive method)
1023 /// to get the exact taw slice of the first TLV element value that also works for containers.
1024 #[inline(always)]
1025 fn value(&self, control: TLVControl) -> Result<&'a [u8], Error> {
1026 let value_len = self.value_len(control)?;
1027
1028 Ok(self
1029 .value_start(control)?
1030 .get(..value_len)
1031 .ok_or(ErrorCode::TLVTypeMismatch)?)
1032 }
1033
1034 /// Return a sub-slice of the wrapped byte slice that designates the exact raw slice representing the value payload
1035 /// of the first TLV element in the sequence.
1036 #[inline(always)]
1037 fn container_value(&self, control: TLVControl) -> Result<&'a [u8], Error> {
1038 let value_len = self.container_value_len(control)?;
1039
1040 Ok(self
1041 .value_start(control)?
1042 .get(..value_len)
1043 .ok_or(ErrorCode::TLVTypeMismatch)?)
1044 }
1045
1046 /// Return the length of the value field of the first TLV element in the sequence.
1047 ///
1048 /// - For elements that do have a fixed size, the fixed size will be returned.
1049 /// - For UTF-8 and octet strings, the actual string length will be returned.
1050 /// - For containers, a length of 0 will be returned. Use `container_value_len`
1051 /// (much more computationally expensive method) to get the exact length of the container.
1052 #[inline(always)]
1053 fn value_len(&self, control: TLVControl) -> Result<usize, Error> {
1054 if let Some(fixed_size) = control.value_type.fixed_size() {
1055 return Ok(fixed_size);
1056 }
1057
1058 let size_len = control.value_type.variable_size_len();
1059
1060 let value_len_slice = self
1061 .value_len_start(control.tag_type)?
1062 .get(..size_len)
1063 .ok_or(ErrorCode::TLVTypeMismatch)?;
1064
1065 let len = match size_len {
1066 1 => u8::from_be_bytes(unwrap!(value_len_slice.try_into())) as usize,
1067 2 => u16::from_le_bytes(unwrap!(value_len_slice.try_into())) as usize,
1068 4 => u32::from_le_bytes(unwrap!(value_len_slice.try_into())) as usize,
1069 8 => u64::from_le_bytes(unwrap!(value_len_slice.try_into())) as usize,
1070 _ => unreachable!(),
1071 };
1072
1073 Ok(len)
1074 }
1075
1076 /// Return the length of the value field of the first TLV element in the sequence, regardless of the
1077 /// element type (fixed size, variable size, or container).
1078 #[inline(always)]
1079 fn container_value_len(&self, control: TLVControl) -> Result<usize, Error> {
1080 if control.value_type.is_container() {
1081 let mut next = self.clone();
1082 let mut len = 0;
1083 let mut level = 1;
1084
1085 while level > 0 {
1086 next = next.next_enter()?;
1087 len += next.len()?;
1088
1089 let control = next.control()?;
1090
1091 if control.value_type.is_container_end() {
1092 control.confirm_container_end()?;
1093 level -= 1;
1094 } else if control.value_type.is_container() {
1095 level += 1;
1096 }
1097 }
1098
1099 Ok(len)
1100 } else {
1101 self.value_len(control)
1102 }
1103 }
1104
1105 /// Return the length of the first TLV element in the sequence.
1106 ///
1107 /// For containers, the return length will NOT include the elements contained inside
1108 /// the container, nor the one-byte `EndCnt` marker.
1109 #[inline(always)]
1110 fn len(&self) -> Result<usize, Error> {
1111 let control = self.control()?;
1112
1113 self.value_len(control).map(|value_len| {
1114 1 + control.tag_type.size() + control.value_type.variable_size_len() + value_len
1115 })
1116 }
1117
1118 /// Return the length of the first TLV element in the sequence, regardless of the element type.
1119 #[inline(always)]
1120 pub(crate) fn container_len(&self) -> Result<usize, Error> {
1121 let control = self.control()?;
1122
1123 self.container_value_len(control).map(|value_len| {
1124 1 + control.tag_type.size() + control.value_type.variable_size_len() + value_len
1125 })
1126 }
1127
1128 /// Returns a sub-slice representing the start of the next TLV element in the sequence.
1129 /// If the sequence contains just one element, the method will return an empty slice.
1130 /// If the sequence contains no elements, the method will return an error with code `ErrorCode::TLVTypeMismatch`.
1131 ///
1132 /// Just like `next_enter` (wich is based on `next_start`) this method does "enter" container elements,
1133 /// and might return a sub-slice where the first element is the special `EndCnt` marker.
1134 #[inline(always)]
1135 fn next_start(&self, control: TLVControl) -> Result<&'a [u8], Error> {
1136 let value_len = self.value_len(control)?;
1137
1138 Ok(self
1139 .value_start(control)?
1140 .get(value_len..)
1141 .ok_or(ErrorCode::TLVTypeMismatch)?)
1142 }
1143
1144 pub(crate) fn fmt(&self, indent: usize, f: &mut fmt::Formatter) -> fmt::Result {
1145 let mut first = true;
1146
1147 for elem in self.iter() {
1148 if first {
1149 first = false;
1150 } else {
1151 writeln!(f, ",")?;
1152 }
1153
1154 let elem = elem.map_err(|_| fmt::Error)?;
1155
1156 elem.fmt(indent, f)?;
1157 }
1158
1159 if !first {
1160 writeln!(f)?;
1161 }
1162
1163 Ok(())
1164 }
1165}
1166
1167impl fmt::Debug for TLVSequence<'_> {
1168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1169 self.fmt(0, f)
1170 }
1171}
1172
1173impl fmt::Display for TLVSequence<'_> {
1174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1175 self.fmt(0, f)
1176 }
1177}
1178
1179#[cfg(feature = "defmt")]
1180impl defmt::Format for TLVSequence<'_> {
1181 fn format(&self, f: defmt::Formatter<'_>) {
1182 defmt::Display2Format(self).format(f)
1183 }
1184}
1185
1186/// A type representing an iterator over the elements of a `TLVSequence` returning `TLV` instances.
1187#[derive(Clone)]
1188pub struct TLVSequenceTLVIter<'a> {
1189 seq: TLVSequence<'a>,
1190 nesting: usize,
1191}
1192
1193impl<'a> TLVSequenceTLVIter<'a> {
1194 /// Create a new `TLVContainerIter` instance.
1195 const fn new(seq: TLVSequence<'a>) -> Self {
1196 Self { seq, nesting: 0 }
1197 }
1198
1199 fn try_next(&mut self) -> Result<Option<TLV<'a>>, Error> {
1200 let current = self.seq.current()?;
1201 if current.is_empty() {
1202 return Ok(None);
1203 }
1204
1205 self.advance()?;
1206
1207 Ok(Some(TLV::new(current.tag()?, current.value()?)))
1208 }
1209
1210 fn advance(&mut self) -> Result<(), Error> {
1211 if self.nesting > 0 || !self.seq.0.is_empty() && !self.seq.control()?.is_container_end() {
1212 self.seq = self.seq.next_enter()?;
1213
1214 let control = self.seq.control()?;
1215
1216 if control.is_container_start() {
1217 self.nesting += 1;
1218 } else if control.is_container_end() {
1219 self.nesting -= 1;
1220 }
1221 }
1222
1223 Ok(())
1224 }
1225}
1226
1227impl<'a> Iterator for TLVSequenceTLVIter<'a> {
1228 type Item = Result<TLV<'a>, Error>;
1229
1230 fn next(&mut self) -> Option<Self::Item> {
1231 self.try_next().transpose()
1232 }
1233}
1234
1235/// A type representing an iterator over the elements of a `TLVSequence`.
1236#[derive(Clone)]
1237#[repr(transparent)]
1238pub struct TLVSequenceIter<'a>(TLVSequence<'a>);
1239
1240impl<'a> TLVSequenceIter<'a> {
1241 /// Create a new `TLVContainerIter` instance.
1242 const fn new(seq: TLVSequence<'a>) -> Self {
1243 Self(seq)
1244 }
1245
1246 fn advance(&mut self) -> Result<(), Error> {
1247 self.0 = self.0.container_next()?;
1248
1249 Ok(())
1250 }
1251}
1252
1253impl<'a> Iterator for TLVSequenceIter<'a> {
1254 type Item = Result<TLVElement<'a>, Error>;
1255
1256 fn next(&mut self) -> Option<Self::Item> {
1257 self.0
1258 .current()
1259 .and_then(|current| self.advance().map(|_| current))
1260 .map(|elem| (!elem.is_empty()).then_some(elem))
1261 .transpose()
1262 }
1263}
1264
1265impl fmt::Debug for TLVSequenceIter<'_> {
1266 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1267 self.0.fmt(0, f)
1268 }
1269}
1270
1271impl fmt::Display for TLVSequenceIter<'_> {
1272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1273 self.0.fmt(0, f)
1274 }
1275}
1276
1277#[cfg(feature = "defmt")]
1278impl defmt::Format for TLVSequenceIter<'_> {
1279 fn format(&self, f: defmt::Formatter<'_>) {
1280 defmt::Display2Format(self).format(f)
1281 }
1282}
1283
1284#[cfg(test)]
1285mod tests {
1286 use core::{f32, f64};
1287
1288 use super::TLVElement;
1289 use crate::{
1290 tlv::{TLVArray, TLVList, TLVSequence, TLVStruct, TLVTag, TLVValue, TLVWrite, TLV},
1291 utils::storage::WriteBuf,
1292 };
1293
1294 #[test]
1295 fn test_no_container_for_int() {
1296 // The 0x24 is a a tagged integer, here the integer is 2
1297 let data = &[0x15, 0x24, 0x1, 0x2];
1298 let seq = TLVSequence(data);
1299 // Skip the 0x15
1300 let seq = seq.next_enter().unwrap();
1301
1302 let elem = TLVElement(seq);
1303 assert!(elem.container().is_err());
1304 }
1305
1306 #[test]
1307 fn test_struct_iteration_with_mix_values() {
1308 // This is a struct with 3 valid values
1309 let data = &[
1310 0x15, 0x24, 0x0, 0x2, 0x26, 0x2, 0x4e, 0x10, 0x02, 0x00, 0x30, 0x3, 0x04, 0x73, 0x6d,
1311 0x61, 0x72,
1312 ];
1313
1314 let mut root_iter = TLVElement::new(data).structure().unwrap().iter();
1315 assert_eq!(
1316 root_iter.next().unwrap().unwrap().tlv().unwrap(),
1317 TLV {
1318 tag: TLVTag::Context(0),
1319 value: TLVValue::U8(2),
1320 }
1321 );
1322 assert_eq!(
1323 root_iter.next().unwrap().unwrap().tlv().unwrap(),
1324 TLV {
1325 tag: TLVTag::Context(2),
1326 value: TLVValue::U32(135246),
1327 }
1328 );
1329 assert_eq!(
1330 root_iter.next().unwrap().unwrap().tlv().unwrap(),
1331 TLV {
1332 tag: TLVTag::Context(3),
1333 value: TLVValue::Str8l(&[0x73, 0x6d, 0x61, 0x72]),
1334 }
1335 );
1336 }
1337
1338 #[test]
1339 fn test_struct_find_element_mix_values() {
1340 // This is a struct with 3 valid values
1341 let data = &[
1342 0x15, 0x30, 0x3, 0x04, 0x73, 0x6d, 0x61, 0x72, 0x24, 0x0, 0x2, 0x26, 0x2, 0x4e, 0x10,
1343 0x02, 0x00,
1344 ];
1345 let root = TLVElement::new(data).structure().unwrap();
1346
1347 assert_eq!(
1348 root.find_ctx(0).unwrap().tlv().unwrap(),
1349 TLV {
1350 tag: TLVTag::Context(0),
1351 value: TLVValue::U8(2),
1352 }
1353 );
1354 assert_eq!(root.find_ctx(2).unwrap().tag().unwrap(), TLVTag::Context(2));
1355 assert_eq!(root.find_ctx(2).unwrap().u64().unwrap(), 135246);
1356
1357 assert_eq!(root.find_ctx(3).unwrap().tag().unwrap(), TLVTag::Context(3));
1358 assert_eq!(
1359 root.find_ctx(3).unwrap().str().unwrap(),
1360 &[0x73, 0x6d, 0x61, 0x72]
1361 );
1362 }
1363
1364 #[test]
1365 fn test_container_len() {
1366 let mut buf = [0; 200];
1367 let mut tw = WriteBuf::new(&mut buf);
1368
1369 tw.start_struct(&TLVTag::Context(0)).unwrap();
1370 tw.u64(&TLVTag::Context(0), 1234).unwrap();
1371 tw.u64(&TLVTag::Context(1), 1234).unwrap();
1372 tw.end_container().unwrap();
1373
1374 // container_len should exactly match the underlying slice holding the complete structure
1375 assert_eq!(tw.as_slice().len(), 11);
1376 assert_eq!(
1377 TLVSequence(tw.as_slice()).container_len().unwrap(),
1378 tw.as_slice().len()
1379 );
1380 }
1381
1382 #[test]
1383 fn test_list_iteration_with_mix_values() {
1384 // This is a list with 3 valid values
1385 let data = &[
1386 0x17, 0x24, 0x0, 0x2, 0x26, 0x2, 0x4e, 0x10, 0x02, 0x00, 0x30, 0x3, 0x04, 0x73, 0x6d,
1387 0x61, 0x72,
1388 ];
1389 let mut root_iter = TLVElement::new(data).list().unwrap().iter();
1390 assert_eq!(
1391 root_iter.next().unwrap().unwrap().tlv().unwrap(),
1392 TLV {
1393 tag: TLVTag::Context(0),
1394 value: TLVValue::U8(2),
1395 }
1396 );
1397 assert_eq!(
1398 root_iter.next().unwrap().unwrap().tlv().unwrap(),
1399 TLV {
1400 tag: TLVTag::Context(2),
1401 value: TLVValue::U32(135246),
1402 }
1403 );
1404 assert_eq!(
1405 root_iter.next().unwrap().unwrap().tlv().unwrap(),
1406 TLV {
1407 tag: TLVTag::Context(3),
1408 value: TLVValue::Str8l(&[0x73, 0x6d, 0x61, 0x72]),
1409 }
1410 );
1411 }
1412
1413 #[test]
1414 fn test_read_past_end_of_container() {
1415 let data = &[0x15, 0x35, 0x0, 0x24, 0x1, 0x2, 0x18, 0x24, 0x0, 0x2, 0x18];
1416
1417 let mut struct2_iter = TLVElement::new(data)
1418 .structure()
1419 .unwrap()
1420 .find_ctx(0)
1421 .unwrap()
1422 .structure()
1423 .unwrap()
1424 .iter();
1425
1426 assert_eq!(
1427 struct2_iter.next().unwrap().unwrap().tlv().unwrap(),
1428 TLV {
1429 tag: TLVTag::Context(1),
1430 value: TLVValue::U8(2),
1431 }
1432 );
1433 assert!(struct2_iter.next().is_none());
1434 // Call next, even after the first next returns None
1435 assert!(struct2_iter.next().is_none());
1436 assert!(struct2_iter.next().is_none());
1437 }
1438
1439 #[test]
1440 fn test_iteration() {
1441 // This is the input we have
1442 // {
1443 // 0: [
1444 // {
1445 // 0: L[ 0: 2, 2: 6, 3: 1],
1446 // 1: {},
1447 // },
1448 // ],
1449 // }
1450
1451 let data = &[
1452 0x15, 0x36, 0x0, 0x15, 0x37, 0x0, 0x24, 0x0, 0x2, 0x24, 0x2, 0x6, 0x24, 0x3, 0x1, 0x18,
1453 0x35, 0x1, 0x18, 0x18, 0x18, 0x18,
1454 ];
1455
1456 let struct0 = TLVStruct::<TLVElement>::new(TLVElement::new(data)).unwrap();
1457
1458 assert_eq!(
1459 struct0.element().tlv().unwrap(),
1460 TLV {
1461 tag: TLVTag::Anonymous,
1462 value: TLVValue::Struct,
1463 }
1464 );
1465 assert_eq!(struct0.iter().count(), 1);
1466
1467 let array = TLVArray::<TLVElement>::new(struct0.iter().next().unwrap().unwrap()).unwrap();
1468
1469 assert_eq!(
1470 array.element().tlv().unwrap(),
1471 TLV {
1472 tag: TLVTag::Context(0),
1473 value: TLVValue::Array,
1474 }
1475 );
1476 assert_eq!(array.iter().count(), 1);
1477
1478 let struct1 = TLVStruct::<TLVElement>::new(array.iter().next().unwrap().unwrap()).unwrap();
1479 assert_eq!(
1480 struct1.element().tlv().unwrap(),
1481 TLV {
1482 tag: TLVTag::Anonymous,
1483 value: TLVValue::Struct,
1484 }
1485 );
1486 assert_eq!(struct1.iter().count(), 2);
1487
1488 let mut struct1_iter = struct1.iter();
1489
1490 let list = TLVList::<TLVElement>::new(struct1_iter.next().unwrap().unwrap()).unwrap();
1491 assert_eq!(
1492 list.element().tlv().unwrap(),
1493 TLV {
1494 tag: TLVTag::Context(0),
1495 value: TLVValue::List,
1496 }
1497 );
1498 assert_eq!(list.iter().count(), 3);
1499
1500 let mut list_iter = list.iter();
1501
1502 let le1 = list_iter.next().unwrap().unwrap();
1503 assert_eq!(
1504 le1.tlv().unwrap(),
1505 TLV {
1506 tag: TLVTag::Context(0),
1507 value: TLVValue::U8(2)
1508 }
1509 );
1510
1511 let le2 = list_iter.next().unwrap().unwrap();
1512 assert_eq!(
1513 le2.tlv().unwrap(),
1514 TLV {
1515 tag: TLVTag::Context(2),
1516 value: TLVValue::U8(6)
1517 }
1518 );
1519
1520 let le3 = list_iter.next().unwrap().unwrap();
1521 assert_eq!(
1522 le3.tlv().unwrap(),
1523 TLV {
1524 tag: TLVTag::Context(3),
1525 value: TLVValue::U8(1)
1526 }
1527 );
1528
1529 assert!(list_iter.next().is_none());
1530
1531 let struct2 = TLVStruct::<TLVElement>::new(struct1_iter.next().unwrap().unwrap()).unwrap();
1532 assert_eq!(
1533 struct2.element().tlv().unwrap(),
1534 TLV {
1535 tag: TLVTag::Context(1),
1536 value: TLVValue::Struct,
1537 }
1538 );
1539 assert_eq!(struct2.iter().count(), 0);
1540 }
1541
1542 #[test]
1543 fn test_matter_spec_examples() {
1544 let tlv = |slice| TLVElement::new(slice).tlv().unwrap();
1545
1546 // Boolean false
1547
1548 assert_eq!(
1549 tlv(&[0x08]),
1550 TLV {
1551 tag: TLVTag::Anonymous,
1552 value: TLVValue::False,
1553 }
1554 );
1555
1556 // Boolean true
1557
1558 assert_eq!(
1559 tlv(&[0x09]),
1560 TLV {
1561 tag: TLVTag::Anonymous,
1562 value: TLVValue::True,
1563 }
1564 );
1565
1566 // Signed Integer, 1-octet, value 42
1567
1568 assert_eq!(
1569 tlv(&[0x00, 0x2a]),
1570 TLV {
1571 tag: TLVTag::Anonymous,
1572 value: TLVValue::S8(42),
1573 }
1574 );
1575
1576 // Signed Integer, 1-octet, value -17
1577
1578 assert_eq!(
1579 tlv(&[0x00, 0xef]),
1580 TLV {
1581 tag: TLVTag::Anonymous,
1582 value: TLVValue::S8(-17),
1583 }
1584 );
1585
1586 // Unsigned Integer, 1-octet, value 42U
1587
1588 assert_eq!(
1589 tlv(&[0x04, 0x2a]),
1590 TLV {
1591 tag: TLVTag::Anonymous,
1592 value: TLVValue::U8(42),
1593 }
1594 );
1595
1596 // Signed Integer, 2-octet, value 42
1597
1598 assert_eq!(
1599 tlv(&[0x01, 0x2a, 0x00]),
1600 TLV {
1601 tag: TLVTag::Anonymous,
1602 value: TLVValue::S16(42),
1603 }
1604 );
1605
1606 // Signed Integer, 4-octet, value -170000
1607
1608 assert_eq!(
1609 tlv(&[0x02, 0xf0, 0x67, 0xfd, 0xff]),
1610 TLV {
1611 tag: TLVTag::Anonymous,
1612 value: TLVValue::S32(-170000),
1613 }
1614 );
1615
1616 // Signed Integer, 8-octet, value 40000000000
1617
1618 assert_eq!(
1619 tlv(&[0x03, 0x00, 0x90, 0x2f, 0x50, 0x09, 0x00, 0x00, 0x00]),
1620 TLV {
1621 tag: TLVTag::Anonymous,
1622 value: TLVValue::S64(40000000000),
1623 }
1624 );
1625
1626 // UTF-8 String, 1-octet length, "Hello!"
1627
1628 assert_eq!(
1629 tlv(&[0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21]),
1630 TLV {
1631 tag: TLVTag::Anonymous,
1632 value: TLVValue::Utf8l("Hello!"),
1633 }
1634 );
1635
1636 // UTF-8 String, 1-octet length, "Tschüs"
1637
1638 assert_eq!(
1639 tlv(&[0x0c, 0x07, 0x54, 0x73, 0x63, 0x68, 0xc3, 0xbc, 0x73]),
1640 TLV {
1641 tag: TLVTag::Anonymous,
1642 value: TLVValue::Utf8l("Tschüs"),
1643 }
1644 );
1645
1646 // Octet String, 1-octet length, octets 00 01 02 03 04
1647
1648 assert_eq!(
1649 tlv(&[0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04]),
1650 TLV {
1651 tag: TLVTag::Anonymous,
1652 value: TLVValue::Str8l(&[0x00, 0x01, 0x02, 0x03, 0x04]),
1653 }
1654 );
1655
1656 // Null
1657
1658 assert_eq!(
1659 tlv(&[0x14]),
1660 TLV {
1661 tag: TLVTag::Anonymous,
1662 value: TLVValue::Null,
1663 }
1664 );
1665
1666 // Single precision floating point 0.0
1667
1668 assert_eq!(
1669 tlv(&[0x0a, 0x00, 0x00, 0x00, 0x00]),
1670 TLV {
1671 tag: TLVTag::Anonymous,
1672 value: TLVValue::F32(0.0),
1673 }
1674 );
1675
1676 // Single precision floating point (1.0 / 3.0)
1677
1678 assert_eq!(
1679 tlv(&[0x0a, 0xab, 0xaa, 0xaa, 0x3e]),
1680 TLV {
1681 tag: TLVTag::Anonymous,
1682 value: TLVValue::F32(1.0 / 3.0),
1683 }
1684 );
1685
1686 // Single precision floating point 17.9
1687
1688 assert_eq!(
1689 tlv(&[0x0a, 0x33, 0x33, 0x8f, 0x41]),
1690 TLV {
1691 tag: TLVTag::Anonymous,
1692 value: TLVValue::F32(17.9),
1693 }
1694 );
1695
1696 // Single precision floating point infinity
1697
1698 assert_eq!(
1699 tlv(&[0x0a, 0x00, 0x00, 0x80, 0x7f]),
1700 TLV {
1701 tag: TLVTag::Anonymous,
1702 value: TLVValue::F32(f32::INFINITY),
1703 }
1704 );
1705
1706 // Single precision floating point negative infinity
1707
1708 assert_eq!(
1709 tlv(&[0x0a, 0x00, 0x00, 0x80, 0xff]),
1710 TLV {
1711 tag: TLVTag::Anonymous,
1712 value: TLVValue::F32(f32::NEG_INFINITY),
1713 }
1714 );
1715
1716 // Double precision floating point 0.0
1717
1718 assert_eq!(
1719 tlv(&[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]),
1720 TLV {
1721 tag: TLVTag::Anonymous,
1722 value: TLVValue::F64(0.0),
1723 }
1724 );
1725
1726 // Double precision floating point (1.0 / 3.0)
1727
1728 assert_eq!(
1729 tlv(&[0x0b, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f]),
1730 TLV {
1731 tag: TLVTag::Anonymous,
1732 value: TLVValue::F64(1.0 / 3.0),
1733 }
1734 );
1735
1736 // Double precision floating point 17.9
1737
1738 assert_eq!(
1739 tlv(&[0x0b, 0x66, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x31, 0x40]),
1740 TLV {
1741 tag: TLVTag::Anonymous,
1742 value: TLVValue::F64(17.9),
1743 }
1744 );
1745
1746 // Double precision floating point infinity (∞)
1747
1748 assert_eq!(
1749 tlv(&[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f]),
1750 TLV {
1751 tag: TLVTag::Anonymous,
1752 value: TLVValue::F64(f64::INFINITY),
1753 }
1754 );
1755
1756 // Double precision floating point negative infinity
1757
1758 assert_eq!(
1759 tlv(&[0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff]),
1760 TLV {
1761 tag: TLVTag::Anonymous,
1762 value: TLVValue::F64(f64::NEG_INFINITY),
1763 }
1764 );
1765
1766 // Empty Structure, {}
1767
1768 assert_eq!(
1769 tlv(&[0x15, 0x18]),
1770 TLV {
1771 tag: TLVTag::Anonymous,
1772 value: TLVValue::Struct,
1773 }
1774 );
1775
1776 assert!(TLVElement::new(&[0x15, 0x18])
1777 .structure()
1778 .unwrap()
1779 .iter()
1780 .next()
1781 .is_none());
1782
1783 // Empty Array, []
1784
1785 assert_eq!(
1786 tlv(&[0x16, 0x18]),
1787 TLV {
1788 tag: TLVTag::Anonymous,
1789 value: TLVValue::Array,
1790 }
1791 );
1792
1793 assert!(TLVElement::new(&[0x16, 0x18])
1794 .array()
1795 .unwrap()
1796 .iter()
1797 .next()
1798 .is_none());
1799
1800 // Empty List, []
1801
1802 assert_eq!(
1803 tlv(&[0x17, 0x18]),
1804 TLV {
1805 tag: TLVTag::Anonymous,
1806 value: TLVValue::List,
1807 }
1808 );
1809
1810 assert!(TLVElement::new(&[0x17, 0x18])
1811 .list()
1812 .unwrap()
1813 .iter()
1814 .next()
1815 .is_none());
1816
1817 // Structure, two context specific tags, Signed Intger, 1 octet values, {0 = 42, 1 = -17}
1818
1819 let data = &[0x15, 0x20, 0x00, 0x2a, 0x20, 0x01, 0xef, 0x18];
1820
1821 assert_eq!(
1822 tlv(data),
1823 TLV {
1824 tag: TLVTag::Anonymous,
1825 value: TLVValue::Struct,
1826 }
1827 );
1828
1829 let mut iter = TLVElement::new(data).structure().unwrap().iter();
1830
1831 let s1 = iter.next().unwrap().unwrap();
1832 assert_eq!(s1.tag().unwrap(), TLVTag::Context(0));
1833 assert_eq!(s1.i32().unwrap(), 42);
1834
1835 let s2 = iter.next().unwrap().unwrap();
1836 assert_eq!(s2.tag().unwrap(), TLVTag::Context(1));
1837 assert_eq!(s2.i16().unwrap(), -17);
1838
1839 assert!(iter.next().is_none());
1840
1841 // Array, Signed Integer, 1-octet values, [0, 1, 2, 3, 4]
1842
1843 let data = &[
1844 0x16, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x18,
1845 ];
1846
1847 assert_eq!(
1848 tlv(data),
1849 TLV {
1850 tag: TLVTag::Anonymous,
1851 value: TLVValue::Array,
1852 }
1853 );
1854
1855 let iter = TLVElement::new(data).array().unwrap().iter().enumerate();
1856
1857 for (index, elem) in iter {
1858 let elem = elem.unwrap();
1859
1860 assert_eq!(elem.tag().unwrap(), TLVTag::Anonymous);
1861 assert_eq!(elem.i8().unwrap(), index as i8);
1862 }
1863
1864 // List, mix of anonymous and context tags, Signed Integer, 1 octet values, [[1, 0 = 42, 2, 3, 0 = -17]]
1865
1866 let data = &[
1867 0x17, 0x00, 0x01, 0x20, 0x00, 0x2a, 0x00, 0x02, 0x00, 0x03, 0x20, 0x00, 0xef, 0x18,
1868 ];
1869
1870 assert_eq!(
1871 tlv(data),
1872 TLV {
1873 tag: TLVTag::Anonymous,
1874 value: TLVValue::List,
1875 }
1876 );
1877
1878 let expected = &[
1879 TLV {
1880 tag: TLVTag::Anonymous,
1881 value: TLVValue::S8(1),
1882 },
1883 TLV {
1884 tag: TLVTag::Context(0),
1885 value: TLVValue::S8(42),
1886 },
1887 TLV {
1888 tag: TLVTag::Anonymous,
1889 value: TLVValue::S8(2),
1890 },
1891 TLV {
1892 tag: TLVTag::Anonymous,
1893 value: TLVValue::S8(3),
1894 },
1895 TLV {
1896 tag: TLVTag::Context(0),
1897 value: TLVValue::S8(-17),
1898 },
1899 ];
1900
1901 let mut iter = TLVElement::new(data).list().unwrap().iter();
1902
1903 for elem in expected {
1904 assert_eq!(iter.next().unwrap().unwrap().tlv().unwrap(), *elem);
1905 }
1906
1907 assert!(iter.next().is_none());
1908
1909 // Array, mix of element types, [42, -170000, {}, 17.9, "Hello!"]
1910
1911 let data = &[
1912 0x16, 0x00, 0x2a, 0x02, 0xf0, 0x67, 0xfd, 0xff, 0x15, 0x18, 0x0a, 0x33, 0x33, 0x8f,
1913 0x41, 0x0c, 0x06, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x21, 0x18,
1914 ];
1915
1916 assert_eq!(
1917 tlv(data),
1918 TLV {
1919 tag: TLVTag::Anonymous,
1920 value: TLVValue::Array,
1921 }
1922 );
1923
1924 let mut iter = TLVElement::new(data).array().unwrap().iter();
1925
1926 assert_eq!(
1927 iter.next().unwrap().unwrap().tlv().unwrap(),
1928 TLV {
1929 tag: TLVTag::Anonymous,
1930 value: TLVValue::S8(42),
1931 }
1932 );
1933
1934 assert_eq!(
1935 iter.next().unwrap().unwrap().tlv().unwrap(),
1936 TLV {
1937 tag: TLVTag::Anonymous,
1938 value: TLVValue::S32(-170000),
1939 }
1940 );
1941
1942 assert_eq!(
1943 iter.next().unwrap().unwrap().tlv().unwrap(),
1944 TLV {
1945 tag: TLVTag::Anonymous,
1946 value: TLVValue::Struct,
1947 }
1948 );
1949
1950 assert_eq!(
1951 iter.next().unwrap().unwrap().tlv().unwrap(),
1952 TLV {
1953 tag: TLVTag::Anonymous,
1954 value: TLVValue::F32(17.9),
1955 }
1956 );
1957
1958 assert_eq!(
1959 iter.next().unwrap().unwrap().tlv().unwrap(),
1960 TLV {
1961 tag: TLVTag::Anonymous,
1962 value: TLVValue::Utf8l("Hello!"),
1963 }
1964 );
1965
1966 // Anonymous tag, Unsigned Integer, 1-octet value, 42U
1967
1968 assert_eq!(
1969 tlv(&[0x04, 0x2a]),
1970 TLV {
1971 tag: TLVTag::Anonymous,
1972 value: TLVValue::U8(42),
1973 }
1974 );
1975
1976 // Context tag 1, Unsigned Integer, 1-octet value, 1 = 42U
1977
1978 assert_eq!(
1979 tlv(&[0x24, 0x01, 0x2a]),
1980 TLV {
1981 tag: TLVTag::Context(1),
1982 value: TLVValue::U8(42),
1983 }
1984 );
1985
1986 // Common profile tag 1, Unsigned Integer, 1-octet value, Matter::1 = 42U
1987
1988 assert_eq!(
1989 tlv(&[0x44, 0x01, 0x00, 0x2a]),
1990 TLV {
1991 tag: TLVTag::CommonPrf16(1),
1992 value: TLVValue::U8(42),
1993 }
1994 );
1995
1996 // Common profile tag 100000, Unsigned Integer, 1-octet value, Matter::100000 = 42U
1997
1998 assert_eq!(
1999 tlv(&[0x64, 0xa0, 0x86, 0x01, 0x00, 0x2a]),
2000 TLV {
2001 tag: TLVTag::CommonPrf32(100000),
2002 value: TLVValue::U8(42),
2003 }
2004 );
2005
2006 // Fully qualified tag, Vendor ID 0xFFF1/65521, profile number 0xDEED/57069,
2007 // 2-octet tag 1, Unsigned Integer, 1-octet value 42, 65521::57069:1 = 42U
2008
2009 assert_eq!(
2010 tlv(&[0xc4, 0xf1, 0xff, 0xed, 0xde, 0x01, 0x00, 0x2a]),
2011 TLV {
2012 tag: TLVTag::FullQual48 {
2013 vendor_id: 65521,
2014 profile: 57069,
2015 tag: 1,
2016 },
2017 value: TLVValue::U8(42),
2018 }
2019 );
2020
2021 // Fully qualified tag, Vendor ID 0xFFF1/65521, profile number 0xDEED/57069,
2022 // 4-octet tag 0xAA55FEED/2857762541, Unsigned Integer, 1-octet value 42, 65521::57069:2857762541 = 42U
2023
2024 assert_eq!(
2025 tlv(&[0xe4, 0xf1, 0xff, 0xed, 0xde, 0xed, 0xfe, 0x55, 0xaa, 0x2a]),
2026 TLV {
2027 tag: TLVTag::FullQual64 {
2028 vendor_id: 65521,
2029 profile: 57069,
2030 tag: 2857762541,
2031 },
2032 value: TLVValue::U8(42),
2033 }
2034 );
2035
2036 // Structure with the fully qualified tag, Vendor ID 0xFFF1/65521, profile number 0xDEED/57069,
2037 // 2-octet tag 1. The structure contains a single element labeled using a fully qualified tag under
2038 // the same profile, with 2-octet tag 0xAA55/43605. 65521::57069:1 = {65521::57069:43605 = 42U}
2039
2040 let data = &[
2041 0xd5, 0xf1, 0xff, 0xed, 0xde, 0x01, 0x00, 0xc4, 0xf1, 0xff, 0xed, 0xde, 0x55, 0xaa,
2042 0x2a, 0x18,
2043 ];
2044
2045 assert_eq!(
2046 tlv(data),
2047 TLV {
2048 tag: TLVTag::FullQual48 {
2049 vendor_id: 65521,
2050 profile: 57069,
2051 tag: 1,
2052 },
2053 value: TLVValue::Struct,
2054 }
2055 );
2056
2057 let mut iter = TLVElement::new(data).structure().unwrap().iter();
2058
2059 let u1 = iter.next().unwrap().unwrap();
2060
2061 assert_eq!(
2062 u1.tag().unwrap(),
2063 TLVTag::FullQual48 {
2064 vendor_id: 65521,
2065 profile: 57069,
2066 tag: 43605,
2067 }
2068 );
2069
2070 assert_eq!(u1.u8().unwrap(), 42);
2071
2072 assert!(iter.next().is_none());
2073 }
2074}