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