1use core::borrow::Borrow;
19use core::fmt;
20use core::iter::Once;
21use core::marker::PhantomData;
22
23use num::FromPrimitive;
24use num_traits::ToBytes;
25
26use crate::error::{Error, ErrorCode};
27
28pub use rs_matter_macros::{FromTLV, ToTLV};
29
30pub use read::*;
31pub use toiter::*;
32pub use traits::*;
33pub use write::*;
34
35mod read;
36mod toiter;
37mod traits;
38mod write;
39
40#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, num_derive::FromPrimitive)]
42#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43#[repr(u8)]
44pub enum TLVTagType {
45 Anonymous = 0,
46 Context = 1,
47 CommonPrf16 = 2,
48 CommonPrf32 = 3,
49 ImplPrf16 = 4,
50 ImplPrf32 = 5,
51 FullQual48 = 6,
52 FullQual64 = 7,
53}
54
55impl TLVTagType {
56 pub const fn size(&self) -> usize {
59 match self {
60 Self::Anonymous => 0,
61 Self::Context => 1,
62 Self::CommonPrf16 => 2,
63 Self::CommonPrf32 => 4,
64 Self::ImplPrf16 => 2,
65 Self::ImplPrf32 => 4,
66 Self::FullQual48 => 6,
67 Self::FullQual64 => 8,
68 }
69 }
70}
71
72impl fmt::Display for TLVTagType {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 match self {
75 Self::Anonymous => write!(f, "Anonymous"),
76 Self::Context => write!(f, "Context"),
77 Self::CommonPrf16 => write!(f, "CommonPrf16"),
78 Self::CommonPrf32 => write!(f, "CommonPrf32"),
79 Self::ImplPrf16 => write!(f, "ImplPrf16"),
80 Self::ImplPrf32 => write!(f, "ImplPrf32"),
81 Self::FullQual48 => write!(f, "FullQual48"),
82 Self::FullQual64 => write!(f, "FullQual64"),
83 }
84 }
85}
86
87#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, num_derive::FromPrimitive)]
89#[cfg_attr(feature = "defmt", derive(defmt::Format))]
90#[repr(u8)]
91pub enum TLVValueType {
92 S8 = 0,
93 S16 = 1,
94 S32 = 2,
95 S64 = 3,
96 U8 = 4,
97 U16 = 5,
98 U32 = 6,
99 U64 = 7,
100 False = 8,
101 True = 9,
102 F32 = 10,
103 F64 = 11,
104 Utf8l = 12,
105 Utf16l = 13,
106 Utf32l = 14,
107 Utf64l = 15,
108 Str8l = 16,
109 Str16l = 17,
110 Str32l = 18,
111 Str64l = 19,
112 Null = 20,
113 Struct = 21,
114 Array = 22,
115 List = 23,
116 EndCnt = 24,
117}
118
119impl TLVValueType {
120 pub const fn fixed_size(&self) -> Option<usize> {
124 match self {
125 Self::S8 => Some(1),
126 Self::S16 => Some(2),
127 Self::S32 => Some(4),
128 Self::S64 => Some(8),
129 Self::U8 => Some(1),
130 Self::U16 => Some(2),
131 Self::U32 => Some(4),
132 Self::U64 => Some(8),
133 Self::F32 => Some(4),
134 Self::F64 => Some(8),
135 Self::Utf8l
136 | Self::Utf16l
137 | Self::Utf32l
138 | Self::Utf64l
139 | Self::Str8l
140 | Self::Str16l
141 | Self::Str32l
142 | Self::Str64l => None,
143 _ => Some(0),
144 }
145 }
146
147 pub const fn variable_size_len(&self) -> usize {
152 match self {
153 Self::Utf8l | Self::Str8l => 1,
154 Self::Utf16l | Self::Str16l => 2,
155 Self::Utf32l | Self::Str32l => 4,
156 Self::Utf64l | Self::Str64l => 8,
157 _ => 0,
158 }
159 }
160
161 pub const fn is_container(&self) -> bool {
164 self.is_container_start() || self.is_container_end()
165 }
166
167 pub const fn is_container_start(&self) -> bool {
169 matches!(self, Self::Struct | Self::Array | Self::List)
170 }
171
172 pub const fn is_container_end(&self) -> bool {
174 matches!(self, Self::EndCnt)
175 }
176
177 pub const fn is_str(&self) -> bool {
179 matches!(
180 self,
181 Self::Str8l | Self::Str16l | Self::Str32l | Self::Str64l
182 )
183 }
184
185 pub const fn is_utf8(&self) -> bool {
187 matches!(
188 self,
189 Self::Utf8l | Self::Utf16l | Self::Utf32l | Self::Utf64l
190 )
191 }
192
193 pub fn container_value<'a>(&self) -> Result<TLVValue<'a>, Error> {
194 Ok(match self {
195 Self::Struct => TLVValue::Struct,
196 Self::Array => TLVValue::Array,
197 Self::List => TLVValue::List,
198 Self::EndCnt => TLVValue::EndCnt,
199 _ => Err(ErrorCode::TLVTypeMismatch)?,
200 })
201 }
202}
203
204impl fmt::Display for TLVValueType {
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 match self {
207 Self::S8 => write!(f, "S8"),
208 Self::S16 => write!(f, "S16"),
209 Self::S32 => write!(f, "S32"),
210 Self::S64 => write!(f, "S64"),
211 Self::U8 => write!(f, "U8"),
212 Self::U16 => write!(f, "U16"),
213 Self::U32 => write!(f, "U32"),
214 Self::U64 => write!(f, "U64"),
215 Self::False => write!(f, "False"),
216 Self::True => write!(f, "True"),
217 Self::F32 => write!(f, "F32"),
218 Self::F64 => write!(f, "F64"),
219 Self::Utf8l => write!(f, "Utf8l"),
220 Self::Utf16l => write!(f, "Utf16l"),
221 Self::Utf32l => write!(f, "Utf32l"),
222 Self::Utf64l => write!(f, "Utf64l"),
223 Self::Str8l => write!(f, "Str8l"),
224 Self::Str16l => write!(f, "Str16l"),
225 Self::Str32l => write!(f, "Str32l"),
226 Self::Str64l => write!(f, "Str64l"),
227 Self::Null => write!(f, "Null"),
228 Self::Struct => write!(f, "Struct"),
229 Self::Array => write!(f, "Array"),
230 Self::List => write!(f, "List"),
231 Self::EndCnt => write!(f, "EndCnt"),
232 }
233 }
234}
235
236#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
238#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239pub struct TLVControl {
240 pub tag_type: TLVTagType,
241 pub value_type: TLVValueType,
242}
243
244impl TLVControl {
245 const TAG_SHIFT_BITS: u8 = 5;
246 const TAG_MASK: u8 = 0xe0;
247 const TYPE_MASK: u8 = 0x1f;
248
249 #[inline(always)]
251 pub const fn new(tag_type: TLVTagType, value_type: TLVValueType) -> Self {
252 Self {
253 tag_type,
254 value_type,
255 }
256 }
257
258 #[inline(always)]
263 pub fn parse(control: u8) -> Result<Self, Error> {
264 let tag_type = FromPrimitive::from_u8((control & Self::TAG_MASK) >> Self::TAG_SHIFT_BITS)
265 .ok_or(ErrorCode::TLVTypeMismatch)?;
266 let value_type =
267 FromPrimitive::from_u8(control & Self::TYPE_MASK).ok_or(ErrorCode::TLVTypeMismatch)?;
268
269 Ok(Self::new(tag_type, value_type))
270 }
271
272 #[inline(always)]
274 pub const fn as_raw(&self) -> u8 {
275 ((self.tag_type as u8) << Self::TAG_SHIFT_BITS) | (self.value_type as u8)
276 }
277
278 #[inline(always)]
280 pub fn is_container_start(&self) -> bool {
281 self.value_type.is_container_start()
282 }
283
284 #[inline(always)]
286 pub fn is_container_end(&self) -> bool {
287 matches!(self.tag_type, TLVTagType::Anonymous) && self.value_type.is_container_end()
288 }
289
290 #[inline(always)]
292 pub fn confirm_container_end(&self) -> Result<(), Error> {
293 if !self.is_container_end() {
294 return Err(ErrorCode::InvalidData.into());
295 }
296
297 Ok(())
298 }
299}
300
301impl fmt::Display for TLVControl {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 write!(f, "Control({} {})", self.tag_type, self.value_type)
304 }
305}
306
307#[derive(Debug, Clone, PartialEq)]
332#[cfg_attr(feature = "defmt", derive(defmt::Format))]
333pub struct TLV<'a> {
334 pub tag: TLVTag,
335 pub value: TLVValue<'a>,
336}
337
338impl<'a> TLV<'a> {
339 pub const fn new(tag: TLVTag, value: TLVValue<'a>) -> Self {
341 Self { tag, value }
342 }
343
344 pub const fn i8(tag: TLVTag, value: i8) -> Self {
346 Self::new(tag, TLVValue::i8(value))
347 }
348
349 pub const fn i16(tag: TLVTag, value: i16) -> Self {
352 Self::new(tag, TLVValue::i16(value))
353 }
354
355 pub const fn i32(tag: TLVTag, value: i32) -> Self {
358 Self::new(tag, TLVValue::i32(value))
359 }
360
361 pub const fn i64(tag: TLVTag, value: i64) -> Self {
364 Self::new(tag, TLVValue::i64(value))
365 }
366
367 pub const fn u8(tag: TLVTag, value: u8) -> Self {
369 Self::new(tag, TLVValue::u8(value))
370 }
371
372 pub const fn u16(tag: TLVTag, value: u16) -> Self {
375 Self::new(tag, TLVValue::u16(value))
376 }
377
378 pub const fn u32(tag: TLVTag, value: u32) -> Self {
381 Self::new(tag, TLVValue::u32(value))
382 }
383
384 pub const fn u64(tag: TLVTag, value: u64) -> Self {
387 Self::new(tag, TLVValue::u64(value))
388 }
389
390 pub const fn f32(tag: TLVTag, value: f32) -> Self {
392 Self::new(tag, TLVValue::f32(value))
393 }
394
395 pub const fn f64(tag: TLVTag, value: f64) -> Self {
397 Self::new(tag, TLVValue::f64(value))
398 }
399
400 pub const fn utf8(tag: TLVTag, value: &'a str) -> Self {
404 Self::new(tag, TLVValue::utf8(value))
405 }
406
407 pub const fn str(tag: TLVTag, value: &'a [u8]) -> Self {
411 Self::new(tag, TLVValue::str(value))
412 }
413
414 pub const fn r#struct(tag: TLVTag) -> Self {
416 Self::new(tag, TLVValue::r#struct())
417 }
418
419 pub const fn structure(tag: TLVTag) -> Self {
421 Self::new(tag, TLVValue::structure())
422 }
423
424 pub const fn array(tag: TLVTag) -> Self {
426 Self::new(tag, TLVValue::array())
427 }
428
429 pub const fn list(tag: TLVTag) -> Self {
431 Self::new(tag, TLVValue::list())
432 }
433
434 pub const fn end_container() -> Self {
436 Self::new(TLVTag::Anonymous, TLVValue::end_container())
437 }
438
439 pub const fn null(tag: TLVTag) -> Self {
441 Self::new(tag, TLVValue::null())
442 }
443
444 pub const fn bool(tag: TLVTag, value: bool) -> Self {
446 Self::new(tag, TLVValue::bool(value))
447 }
448
449 pub fn into_tlv_iter(self) -> OnceTLVIter<'a> {
451 core::iter::once(Ok(self))
452 }
453
454 pub fn bytes_iter(&self) -> TLVBytesIter<'a, &TLVTag, &TLVValue<'a>> {
456 TLVBytesIter {
457 control: core::iter::once(
458 TLVControl::new(self.tag.tag_type(), self.value.value_type()).as_raw(),
459 ),
460 tag: self.tag.iter(),
461 value: self.value.iter(),
462 }
463 }
464
465 pub fn into_bytes_iter(self) -> TLVBytesIter<'a, TLVTag, TLVValue<'a>> {
467 TLVBytesIter {
468 control: core::iter::once(
469 TLVControl::new(self.tag.tag_type(), self.value.value_type()).as_raw(),
470 ),
471 tag: self.tag.into_iterator(),
472 value: self.value.into_iterator(),
473 }
474 }
475
476 pub fn result_into_bytes_iter(
478 result: Result<Self, Error>,
479 ) -> TLVResultBytesIter<'a, TLVTag, TLVValue<'a>> {
480 TLVResultBytesIter::new(result)
481 }
482}
483
484impl<'a> IntoIterator for TLV<'a> {
485 type Item = u8;
486 type IntoIter = TLVBytesIter<'a, TLVTag, TLVValue<'a>>;
487
488 fn into_iter(self) -> Self::IntoIter {
489 TLV::into_bytes_iter(self)
490 }
491}
492
493impl<'s, 'a> IntoIterator for &'s TLV<'a> {
494 type Item = u8;
495 type IntoIter = TLVBytesIter<'a, &'s TLVTag, &'s TLVValue<'a>>;
496
497 fn into_iter(self) -> Self::IntoIter {
498 TLV::bytes_iter(self)
499 }
500}
501
502pub enum TLVResultBytesIter<'a, T, V>
504where
505 T: Borrow<TLVTag>,
506 V: Borrow<TLVValue<'a>>,
507{
508 Ok(TLVBytesIter<'a, T, V>),
509 Err(core::iter::Once<Result<u8, Error>>),
510}
511
512impl<'a> TLVResultBytesIter<'a, TLVTag, TLVValue<'a>> {
513 pub fn new(result: Result<TLV<'a>, Error>) -> Self {
514 match result {
515 Ok(tlv) => Self::Ok(tlv.into_bytes_iter()),
516 Err(err) => Self::Err(core::iter::once(Err(err))),
517 }
518 }
519}
520
521impl<'a, T, V> Iterator for TLVResultBytesIter<'a, T, V>
522where
523 T: Borrow<TLVTag>,
524 V: Borrow<TLVValue<'a>>,
525{
526 type Item = Result<u8, Error>;
527
528 fn next(&mut self) -> Option<Self::Item> {
529 match self {
530 Self::Ok(iter) => iter.next().map(Ok),
531 Self::Err(iter) => iter.next(),
532 }
533 }
534}
535
536pub struct TLVBytesIter<'a, T, V>
538where
539 T: Borrow<TLVTag>,
540 V: Borrow<TLVValue<'a>>,
541{
542 control: Once<u8>,
543 tag: TLVTagIter<T>,
544 value: TLVValueIter<'a, V>,
545}
546
547impl<'a, T, V> Iterator for TLVBytesIter<'a, T, V>
548where
549 T: Borrow<TLVTag>,
550 V: Borrow<TLVValue<'a>>,
551{
552 type Item = u8;
553
554 fn next(&mut self) -> Option<Self::Item> {
555 self.control
556 .next()
557 .or_else(|| self.tag.next())
558 .or_else(|| self.value.next())
559 }
560}
561
562pub type OnceTLVIter<'s> = core::iter::Once<Result<TLV<'s>, Error>>;
564
565pub type TagType = TLVTag;
567
568#[derive(Clone, Debug, PartialEq, Eq, Hash)]
572#[cfg_attr(feature = "defmt", derive(defmt::Format))]
573pub enum TLVTag {
574 Anonymous,
575 Context(u8),
576 CommonPrf16(u16),
577 CommonPrf32(u32),
578 ImplPrf16(u16),
579 ImplPrf32(u32),
580 FullQual48 {
581 vendor_id: u16,
582 profile: u16,
583 tag: u16,
584 },
585 FullQual64 {
586 vendor_id: u16,
587 profile: u16,
588 tag: u32,
589 },
590}
591
592impl TLVTag {
593 pub const fn tag_type(&self) -> TLVTagType {
595 match self {
596 Self::Anonymous => TLVTagType::Anonymous,
597 Self::Context(_) => TLVTagType::Context,
598 Self::CommonPrf16(_) => TLVTagType::CommonPrf16,
599 Self::CommonPrf32(_) => TLVTagType::CommonPrf32,
600 Self::ImplPrf16(_) => TLVTagType::ImplPrf16,
601 Self::ImplPrf32(_) => TLVTagType::ImplPrf32,
602 Self::FullQual48 { .. } => TLVTagType::FullQual48,
603 Self::FullQual64 { .. } => TLVTagType::FullQual64,
604 }
605 }
606
607 pub fn iter(&self) -> TLVTagIter<&Self> {
609 TLVTagIter {
610 value: self,
611 index: 0,
612 }
613 }
614
615 pub fn into_iterator(self) -> TLVTagIter<Self> {
617 TLVTagIter {
618 value: self,
619 index: 0,
620 }
621 }
622
623 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
624 match self {
625 TLVTag::Anonymous => Ok(()),
626 TLVTag::Context(tag) => write!(f, "{tag}"),
627 TLVTag::CommonPrf16(tag) => write!(f, "CommonPrf16({tag})"),
628 TLVTag::CommonPrf32(tag) => write!(f, "CommonPrf32({tag})"),
629 TLVTag::ImplPrf16(tag) => write!(f, "ImplPrf16({tag})"),
630 TLVTag::ImplPrf32(tag) => write!(f, "ImplPrf32({tag})"),
631 TLVTag::FullQual48 {
632 vendor_id,
633 profile,
634 tag,
635 } => write!(f, "FullQual48(VID:{vendor_id} PRF:{profile} {tag})"),
636 TLVTag::FullQual64 {
637 vendor_id,
638 profile,
639 tag,
640 } => write!(f, "FullQual64(VID:{vendor_id} PRF:{profile} {tag})"),
641 }
642 }
643}
644
645impl IntoIterator for TLVTag {
646 type Item = u8;
647 type IntoIter = TLVTagIter<Self>;
648
649 fn into_iter(self) -> Self::IntoIter {
650 TLVTag::into_iterator(self)
651 }
652}
653
654impl IntoIterator for &TLVTag {
655 type Item = u8;
656 type IntoIter = TLVTagIter<Self>;
657
658 fn into_iter(self) -> Self::IntoIter {
659 TLVTag::iter(self)
660 }
661}
662
663pub struct TLVTagIter<T>
665where
666 T: Borrow<TLVTag>,
667{
668 value: T,
669 index: usize,
670}
671
672impl<T> TLVTagIter<T>
673where
674 T: Borrow<TLVTag>,
675{
676 fn next_byte(&mut self, bytes: &[u8]) -> Option<u8> {
677 self.next_byte_offset(0, bytes)
678 }
679
680 fn next_byte_offset(&mut self, offset: usize, bytes: &[u8]) -> Option<u8> {
681 if self.index - offset < bytes.len() {
682 let byte = bytes[self.index - offset];
683
684 self.index += 1;
685
686 Some(byte)
687 } else {
688 None
689 }
690 }
691}
692
693impl<T> Iterator for TLVTagIter<T>
694where
695 T: Borrow<TLVTag>,
696{
697 type Item = u8;
698
699 fn next(&mut self) -> Option<Self::Item> {
700 match self.value.borrow() {
701 TLVTag::Anonymous => None,
702 TLVTag::Context(tag) => self.next_byte(&tag.to_le_bytes()),
703 TLVTag::CommonPrf16(tag) => self.next_byte(&tag.to_le_bytes()),
704 TLVTag::CommonPrf32(tag) => self.next_byte(&tag.to_le_bytes()),
705 TLVTag::ImplPrf16(tag) => self.next_byte(&tag.to_le_bytes()),
706 TLVTag::ImplPrf32(tag) => self.next_byte(&tag.to_le_bytes()),
707 TLVTag::FullQual48 {
708 vendor_id,
709 profile,
710 tag,
711 } => {
712 if self.index < 2 {
713 self.next_byte(&vendor_id.to_le_bytes())
714 } else if self.index < 4 {
715 self.next_byte_offset(2, &profile.to_le_bytes())
716 } else {
717 self.next_byte_offset(4, &tag.to_le_bytes())
718 }
719 }
720 TLVTag::FullQual64 {
721 vendor_id,
722 profile,
723 tag,
724 } => {
725 if self.index < 2 {
726 self.next_byte(&vendor_id.to_le_bytes())
727 } else if self.index < 4 {
728 self.next_byte_offset(2, &profile.to_le_bytes())
729 } else {
730 self.next_byte_offset(4, &tag.to_le_bytes())
731 }
732 }
733 }
734 }
735}
736
737impl fmt::Display for TLVTag {
738 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
739 match self {
740 TLVTag::Anonymous => write!(f, "Anonymous"),
741 TLVTag::Context(tag) => write!(f, "Context({})", tag),
742 _ => self.fmt(f),
743 }
744 }
745}
746
747pub type ElementType<'a> = TLVValue<'a>;
749
750#[derive(Debug, Clone, PartialEq)]
760#[cfg_attr(feature = "defmt", derive(defmt::Format))]
761pub enum TLVValue<'a> {
762 S8(i8),
763 S16(i16),
764 S32(i32),
765 S64(i64),
766 U8(u8),
767 U16(u16),
768 U32(u32),
769 U64(u64),
770 False,
771 True,
772 F32(f32),
773 F64(f64),
774 Utf8l(&'a str),
775 Utf16l(&'a str),
776 Utf32l(&'a str),
777 Utf64l(&'a str),
778 Str8l(&'a [u8]),
779 Str16l(&'a [u8]),
780 Str32l(&'a [u8]),
781 Str64l(&'a [u8]),
782 Null,
783 Struct,
784 Array,
785 List,
786 EndCnt,
787}
788
789impl<'a> TLVValue<'a> {
790 pub const fn value_type(&self) -> TLVValueType {
792 match self {
793 Self::S8(_) => TLVValueType::S8,
794 Self::S16(_) => TLVValueType::S16,
795 Self::S32(_) => TLVValueType::S32,
796 Self::S64(_) => TLVValueType::S64,
797 Self::U8(_) => TLVValueType::U8,
798 Self::U16(_) => TLVValueType::U16,
799 Self::U32(_) => TLVValueType::U32,
800 Self::U64(_) => TLVValueType::U64,
801 Self::False => TLVValueType::False,
802 Self::True => TLVValueType::True,
803 Self::F32(_) => TLVValueType::F32,
804 Self::F64(_) => TLVValueType::F64,
805 Self::Utf8l(_) => TLVValueType::Utf8l,
806 Self::Utf16l(_) => TLVValueType::Utf16l,
807 Self::Utf32l(_) => TLVValueType::Utf32l,
808 Self::Utf64l(_) => TLVValueType::Utf64l,
809 Self::Str8l(_) => TLVValueType::Str8l,
810 Self::Str16l(_) => TLVValueType::Str16l,
811 Self::Str32l(_) => TLVValueType::Str32l,
812 Self::Str64l(_) => TLVValueType::Str64l,
813 Self::Null => TLVValueType::Null,
814 Self::Struct => TLVValueType::Struct,
815 Self::Array => TLVValueType::Array,
816 Self::List => TLVValueType::List,
817 Self::EndCnt => TLVValueType::EndCnt,
818 }
819 }
820
821 pub const fn i8(value: i8) -> Self {
823 Self::S8(value)
824 }
825
826 pub const fn i16(value: i16) -> Self {
829 if value >= i8::MIN as i16 && value <= i8::MAX as i16 {
830 Self::i8(value as i8)
831 } else {
832 Self::S16(value)
833 }
834 }
835
836 pub const fn i32(value: i32) -> Self {
839 if value >= i16::MIN as i32 && value <= i16::MAX as i32 {
840 Self::i16(value as i16)
841 } else {
842 Self::S32(value)
843 }
844 }
845
846 pub const fn i64(value: i64) -> Self {
849 if value >= i32::MIN as i64 && value <= i32::MAX as i64 {
850 Self::i32(value as i32)
851 } else {
852 Self::S64(value)
853 }
854 }
855
856 pub const fn u8(value: u8) -> Self {
858 Self::U8(value)
859 }
860
861 pub const fn u16(value: u16) -> Self {
864 if value <= u8::MAX as u16 {
865 Self::u8(value as u8)
866 } else {
867 Self::U16(value)
868 }
869 }
870
871 pub const fn u32(value: u32) -> Self {
874 if value <= u16::MAX as u32 {
875 Self::u16(value as u16)
876 } else {
877 Self::U32(value)
878 }
879 }
880
881 pub const fn u64(value: u64) -> Self {
884 if value <= u32::MAX as u64 {
885 Self::u32(value as u32)
886 } else {
887 Self::U64(value)
888 }
889 }
890
891 pub const fn f32(value: f32) -> Self {
893 Self::F32(value)
894 }
895
896 pub const fn f64(value: f64) -> Self {
898 Self::F64(value)
899 }
900
901 pub const fn utf8(value: &'a str) -> Self {
905 let len = value.len();
906
907 if len <= u8::MAX as usize {
908 Self::Utf8l(value)
909 } else if len <= u16::MAX as usize {
910 Self::Utf16l(value)
911 } else if len <= u32::MAX as usize {
912 Self::Utf32l(value)
913 } else {
914 Self::Utf64l(value)
915 }
916 }
917
918 pub const fn str(value: &'a [u8]) -> Self {
922 let len = value.len();
923
924 if len <= u8::MAX as usize {
925 Self::Str8l(value)
926 } else if len <= u16::MAX as usize {
927 Self::Str16l(value)
928 } else if len <= u32::MAX as usize {
929 Self::Str32l(value)
930 } else {
931 Self::Str64l(value)
932 }
933 }
934
935 pub const fn r#struct() -> Self {
937 Self::Struct
938 }
939
940 pub const fn structure() -> Self {
942 Self::Struct
943 }
944
945 pub const fn array() -> Self {
947 Self::Array
948 }
949
950 pub const fn list() -> Self {
952 Self::List
953 }
954
955 pub const fn end_container() -> Self {
957 Self::EndCnt
958 }
959
960 pub const fn null() -> Self {
962 Self::Null
963 }
964
965 pub const fn bool(value: bool) -> Self {
967 if value {
968 Self::True
969 } else {
970 Self::False
971 }
972 }
973
974 pub fn iter(&self) -> TLVValueIter<'a, &Self> {
976 TLVValueIter {
977 value: self,
978 _p: PhantomData,
979 index: 0,
980 }
981 }
982
983 pub fn into_iterator(self) -> TLVValueIter<'a, Self> {
985 TLVValueIter {
986 value: self,
987 _p: PhantomData,
988 index: 0,
989 }
990 }
991
992 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
993 match self {
994 Self::S8(a) => write!(f, "S8({a})"),
995 Self::S16(a) => write!(f, "S16({a})"),
996 Self::S32(a) => write!(f, "S32({a})"),
997 Self::S64(a) => write!(f, "S64({a})"),
998 Self::U8(a) => write!(f, "U8(0x{a:02x})"),
999 Self::U16(a) => write!(f, "U16(0x{a:04x})"),
1000 Self::U32(a) => write!(f, "U32(0x{a:08x})"),
1001 Self::U64(a) => write!(f, "U64(0x{a:016x})"),
1002 Self::F32(a) => write!(f, "F32({a})"),
1003 Self::F64(a) => write!(f, "F64({a})"),
1004 Self::Null => write!(f, "Null"),
1005 Self::Struct => write!(f, "{{"),
1006 Self::Array => write!(f, "["),
1007 Self::List => write!(f, "("),
1008 Self::True => write!(f, "True"),
1009 Self::False => write!(f, "False"),
1010 Self::Utf8l(a) | Self::Utf16l(a) | Self::Utf32l(a) | Self::Utf64l(a) => {
1011 write!(f, "\"{a}\"")
1012 }
1013 Self::Str8l(a) | Self::Str16l(a) | Self::Str32l(a) | Self::Str64l(a) => {
1014 write!(f, "({}){a:02X?}", a.len())
1015 }
1016 Self::EndCnt => write!(f, ">"),
1017 }
1018 }
1019}
1020
1021impl<'a> IntoIterator for TLVValue<'a> {
1022 type Item = u8;
1023 type IntoIter = TLVValueIter<'a, Self>;
1024
1025 fn into_iter(self) -> Self::IntoIter {
1026 TLVValue::into_iterator(self)
1027 }
1028}
1029
1030impl<'a> IntoIterator for &TLVValue<'a> {
1031 type Item = u8;
1032 type IntoIter = TLVValueIter<'a, Self>;
1033
1034 fn into_iter(self) -> Self::IntoIter {
1035 TLVValue::iter(self)
1036 }
1037}
1038
1039pub struct TLVValueIter<'a, T>
1041where
1042 T: Borrow<TLVValue<'a>>,
1043{
1044 value: T,
1045 _p: PhantomData<&'a ()>,
1046 index: usize,
1047}
1048
1049impl<'a, T> TLVValueIter<'a, T>
1050where
1051 T: Borrow<TLVValue<'a>>,
1052{
1053 fn variable_len_len(&self) -> usize {
1054 match self.value.borrow() {
1055 TLVValue::Utf8l(_) | TLVValue::Str8l(_) => 1,
1056 TLVValue::Utf16l(_) | TLVValue::Str16l(_) => 2,
1057 TLVValue::Utf32l(_) | TLVValue::Str32l(_) => 4,
1058 TLVValue::Utf64l(_) | TLVValue::Str64l(_) => 8,
1059 _ => 0,
1060 }
1061 }
1062
1063 fn next_byte(&mut self, bytes: &[u8]) -> Option<u8> {
1064 self.next_byte_offset(0, bytes)
1065 }
1066
1067 fn next_byte_offset(&mut self, offset: usize, bytes: &[u8]) -> Option<u8> {
1068 if self.index - offset < bytes.len() {
1069 let byte = bytes[self.index - offset];
1070
1071 self.index += 1;
1072
1073 Some(byte)
1074 } else {
1075 None
1076 }
1077 }
1078}
1079
1080impl<'a, T> Iterator for TLVValueIter<'a, T>
1081where
1082 T: Borrow<TLVValue<'a>>,
1083{
1084 type Item = u8;
1085
1086 fn next(&mut self) -> Option<Self::Item> {
1087 match self.value.borrow() {
1088 TLVValue::S8(a) => self.next_byte(&a.to_le_bytes()),
1089 TLVValue::S16(a) => self.next_byte(&a.to_le_bytes()),
1090 TLVValue::S32(a) => self.next_byte(&a.to_le_bytes()),
1091 TLVValue::S64(a) => self.next_byte(&a.to_le_bytes()),
1092 TLVValue::U8(a) => self.next_byte(&a.to_le_bytes()),
1093 TLVValue::U16(a) => self.next_byte(&a.to_le_bytes()),
1094 TLVValue::U32(a) => self.next_byte(&a.to_le_bytes()),
1095 TLVValue::U64(a) => self.next_byte(&a.to_le_bytes()),
1096 TLVValue::F32(a) => self.next_byte(&a.to_le_bytes()),
1097 TLVValue::F64(a) => self.next_byte(&a.to_le_bytes()),
1098 TLVValue::Utf8l(a) | TLVValue::Utf16l(a) | TLVValue::Utf32l(a) => {
1099 let len_len = self.variable_len_len();
1100 if self.index < len_len {
1101 self.next_byte(&a.len().to_le_bytes())
1102 } else {
1103 self.next_byte_offset(len_len, a.as_bytes())
1104 }
1105 }
1106 TLVValue::Str8l(a) | TLVValue::Str16l(a) | TLVValue::Str32l(a) => {
1107 let len_len = self.variable_len_len();
1108 if self.index < len_len {
1109 self.next_byte(&a.len().to_le_bytes())
1110 } else {
1111 self.next_byte_offset(len_len, a)
1112 }
1113 }
1114 _ => None,
1115 }
1116 }
1117}
1118
1119impl fmt::Display for TLVValue<'_> {
1120 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1121 self.fmt(f)
1122 }
1123}
1124
1125pub(crate) fn pad(ident: usize, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1126 for _ in 0..ident {
1127 write!(f, " ")?;
1128 }
1129
1130 Ok(())
1131}
1132
1133pub fn get_root_node_struct(data: &[u8]) -> Result<TLVElement<'_>, Error> {
1135 let element = TLVElement::new(data);
1137
1138 element.structure()?;
1139
1140 Ok(element)
1141}