matc/
tlv.rs

1//! Utilities to decode/encode matter tlv
2
3use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use core::fmt;
5use std::io::{Cursor, Read, Result, Write};
6
7/// Buffer to encode matter tlv. Create buffer, write elements then use data member which contains encoded tlv.
8/// Example how to commission device using certificates pre-created in pem directory:
9/// ```
10/// # use matc::tlv;
11/// # use anyhow::Result;
12/// # fn main() -> Result<()> {
13/// let mut tlv = tlv::TlvBuffer::new();
14/// tlv.write_struct(1)?;
15/// tlv.write_uint8(0, 100)?;
16/// tlv.write_string(0, "test")?;
17/// tlv.write_struct_end()?;
18/// // now tlv.data contains encoded tlv buffer
19/// # Ok(())
20/// # }
21/// ```
22pub struct TlvBuffer {
23    pub data: Vec<u8>,
24}
25
26const TYPE_INT_1: u8 = 0;
27const TYPE_INT_2: u8 = 1;
28const TYPE_INT_4: u8 = 2;
29const TYPE_INT_8: u8 = 3;
30const TYPE_UINT_1: u8 = 4;
31const TYPE_UINT_2: u8 = 5;
32const TYPE_UINT_4: u8 = 6;
33const TYPE_UINT_8: u8 = 7;
34const TYPE_BOOL_FALSE: u8 = 8;
35const TYPE_BOOL_TRUE: u8 = 9;
36const TYPE_UTF8_L1: u8 = 0xC;
37const TYPE_OCTET_STRING_L1: u8 = 0x10;
38const TYPE_OCTET_STRING_L2: u8 = 0x11;
39const TYPE_OCTET_STRING_L4: u8 = 0x12;
40
41const TYPE_STRUCT: u8 = 0x15;
42const TYPE_ARRAY: u8 = 0x16;
43const TYPE_LIST: u8 = 0x17;
44const TYPE_END_CONTAINER: u8 = 0x18;
45
46const CTRL_CTX_L1: u8 = 1 << 5;
47
48impl TlvBuffer {
49    pub fn new() -> Self {
50        Self {
51            data: Vec::with_capacity(1024),
52        }
53    }
54    pub fn from_vec(v: Vec<u8>) -> Self {
55        Self { data: v }
56    }
57    pub fn write_raw(&mut self, data: &[u8]) -> Result<()> {
58        self.data.write_all(data)
59    }
60    pub fn write_anon_struct(&mut self) -> Result<()> {
61        self.data.write_u8(TYPE_STRUCT)?;
62        Ok(())
63    }
64    pub fn write_anon_list(&mut self) -> Result<()> {
65        self.data.write_u8(TYPE_LIST)?;
66        Ok(())
67    }
68    pub fn write_struct(&mut self, tag: u8) -> Result<()> {
69        self.data.write_u8(CTRL_CTX_L1 | TYPE_STRUCT)?;
70        self.data.write_u8(tag)?;
71        Ok(())
72    }
73    pub fn write_array(&mut self, tag: u8) -> Result<()> {
74        self.data.write_u8(CTRL_CTX_L1 | TYPE_ARRAY)?;
75        self.data.write_u8(tag)?;
76        Ok(())
77    }
78    pub fn write_list(&mut self, tag: u8) -> Result<()> {
79        self.data.write_u8(CTRL_CTX_L1 | TYPE_LIST)?;
80        self.data.write_u8(tag)?;
81        Ok(())
82    }
83    pub fn write_struct_end(&mut self) -> Result<()> {
84        self.data.write_u8(TYPE_END_CONTAINER)?;
85        Ok(())
86    }
87    pub fn write_string(&mut self, tag: u8, data: &str) -> Result<()> {
88        let ctrl = CTRL_CTX_L1 | TYPE_UTF8_L1;
89        let bytes = data.as_bytes();
90        self.data.write_u8(ctrl)?;
91        self.data.write_u8(tag)?;
92        self.data.write_u8(bytes.len() as u8)?;
93        self.data.write_all(bytes)?;
94        Ok(())
95    }
96    pub fn write_octetstring(&mut self, tag: u8, data: &[u8]) -> Result<()> {
97        if data.len() > 0xff {
98            self.data.write_u8(CTRL_CTX_L1 | TYPE_OCTET_STRING_L2)?;
99            self.data.write_u8(tag)?;
100            self.data.write_u16::<LittleEndian>(data.len() as u16)?;
101        } else {
102            self.data.write_u8(CTRL_CTX_L1 | TYPE_OCTET_STRING_L1)?;
103            self.data.write_u8(tag)?;
104            self.data.write_u8(data.len() as u8)?;
105        }
106        self.data.write_all(data)?;
107        Ok(())
108    }
109    pub fn write_int8(&mut self, tag: u8, value: i8) -> Result<()> {
110        self.data.write_u8(CTRL_CTX_L1 | TYPE_INT_1)?;
111        self.data.write_u8(tag)?;
112        self.data.write_i8(value)
113    }
114    pub fn write_int16(&mut self, tag: u8, value: i16) -> Result<()> {
115        self.data.write_u8(CTRL_CTX_L1 | TYPE_INT_2)?;
116        self.data.write_u8(tag)?;
117        self.data.write_i16::<LittleEndian>(value)
118    }
119    pub fn write_int32(&mut self, tag: u8, value: i32) -> Result<()> {
120        self.data.write_u8(CTRL_CTX_L1 | TYPE_INT_4)?;
121        self.data.write_u8(tag)?;
122        self.data.write_i32::<LittleEndian>(value)
123    }
124    pub fn write_int64(&mut self, tag: u8, value: i64) -> Result<()> {
125        self.data.write_u8(CTRL_CTX_L1 | TYPE_INT_8)?;
126        self.data.write_u8(tag)?;
127        self.data.write_i64::<LittleEndian>(value)
128    }
129    pub fn write_uint8(&mut self, tag: u8, value: u8) -> Result<()> {
130        self.data.write_u8(CTRL_CTX_L1 | TYPE_UINT_1)?;
131        self.data.write_u8(tag)?;
132        self.data.write_u8(value)
133    }
134    pub fn write_uint8_notag(&mut self, value: u8) -> Result<()> {
135        self.data.write_u8(TYPE_UINT_1)?;
136        self.data.write_u8(value)
137    }
138    pub fn write_uint16_notag(&mut self, value: u16) -> Result<()> {
139        self.data.write_u8(TYPE_UINT_2)?;
140        self.data.write_u16::<LittleEndian>(value)
141    }
142    pub fn write_uint16(&mut self, tag: u8, value: u16) -> Result<()> {
143        self.data.write_u8(CTRL_CTX_L1 | TYPE_UINT_2)?;
144        self.data.write_u8(tag)?;
145        self.data.write_u16::<LittleEndian>(value)
146    }
147    pub fn write_uint32(&mut self, tag: u8, value: u32) -> Result<()> {
148        self.data.write_u8(CTRL_CTX_L1 | TYPE_UINT_4)?;
149        self.data.write_u8(tag)?;
150        self.data.write_u32::<LittleEndian>(value)
151    }
152    pub fn write_uint64(&mut self, tag: u8, value: u64) -> Result<()> {
153        self.data.write_u8(CTRL_CTX_L1 | TYPE_UINT_8)?;
154        self.data.write_u8(tag)?;
155        self.data.write_u64::<LittleEndian>(value)
156    }
157    pub fn write_bool(&mut self, tag: u8, value: bool) -> Result<()> {
158        if value {
159            self.data.write_u8(CTRL_CTX_L1 | TYPE_BOOL_TRUE)?;
160        } else {
161            self.data.write_u8(CTRL_CTX_L1 | TYPE_BOOL_FALSE)?;
162        }
163        self.data.write_u8(tag)
164    }
165}
166
167impl Default for TlvBuffer {
168    fn default() -> Self {
169        Self::new()
170    }
171}
172
173/// Enum containing data of decoded tlv element
174#[derive(Clone, PartialEq)]
175pub enum TlvItemValue {
176    Int(u64),
177    Bool(bool),
178    String(String),
179    OctetString(Vec<u8>),
180    List(Vec<TlvItem>),
181    Nil(),
182    Invalid(),
183}
184
185impl From<TlvItemValue> for bool {
186    fn from(value: TlvItemValue) -> Self {
187        match value {
188            TlvItemValue::Bool(b) => b,
189            _ => false,
190        }
191    }
192}
193impl From<TlvItemValue> for String {
194    fn from(value: TlvItemValue) -> Self {
195        match value {
196            TlvItemValue::String(s) => s,
197            _ => String::new(),
198        }
199    }
200}
201
202impl<'a> TryFrom<&'a TlvItemValue> for &'a [u8] {
203    type Error = &'static str;
204    fn try_from(value: &'a TlvItemValue) -> std::result::Result<Self, Self::Error> {
205        if let TlvItemValue::OctetString(ref s) = value {
206            Ok(s.as_slice())
207        } else {
208            Err("Not an octet string")
209        }
210    }
211}
212impl From<TlvItemValue> for Vec<u8> {
213    fn from(value: TlvItemValue) -> Self {
214        match value {
215            TlvItemValue::OctetString(s) => s,
216            _ => Vec::new(),
217        }
218    }
219}
220impl From<TlvItemValue> for u64 {
221    fn from(value: TlvItemValue) -> Self {
222        match value {
223            TlvItemValue::Int(i) => i,
224            _ => 0,
225        }
226    }
227}
228impl From<TlvItemValue> for Vec<TlvItem> {
229    fn from(value: TlvItemValue) -> Self {
230        match value {
231            TlvItemValue::List(lst) => lst,
232            _ => panic!("Cannot convert to Vec<TlvItem>"),
233        }
234    }
235}
236
237/// Decoded tlv element returned by [decode_tlv]
238#[derive(Debug, Clone, PartialEq)]
239pub struct TlvItem {
240    pub tag: u8,
241    pub value: TlvItemValue,
242}
243
244impl fmt::Debug for TlvItemValue {
245    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
246        match self {
247            Self::Int(arg0) => f.debug_tuple("Int").field(arg0).finish(),
248            Self::Bool(arg0) => f.debug_tuple("Bool").field(arg0).finish(),
249            Self::String(arg0) => f.debug_tuple("String").field(arg0).finish(),
250            Self::OctetString(arg0) => f
251                .debug_tuple("OctetString")
252                .field(&hex::encode(arg0))
253                .finish(),
254            Self::List(arg0) => f.debug_tuple("List").field(arg0).finish(),
255            Self::Nil() => f.debug_tuple("Nil").finish(),
256            Self::Invalid() => f.debug_tuple("Invalid").finish(),
257        }
258    }
259}
260
261impl TlvItem {
262    pub fn get(&self, tag: &[u8]) -> Option<&TlvItemValue> {
263        if !tag.is_empty() {
264            if let TlvItemValue::List(lst) = &self.value {
265                for l in lst {
266                    if l.tag == tag[0] {
267                        return l.get(&tag[1..]);
268                    };
269                }
270            }
271            None
272        } else {
273            Some(&self.value)
274        }
275    }
276    pub fn get_item(&self, tag: &[u8]) -> Option<&TlvItem> {
277        if !tag.is_empty() {
278            if let TlvItemValue::List(lst) = &self.value {
279                for l in lst {
280                    if l.tag == tag[0] {
281                        return l.get_item(&tag[1..]);
282                    };
283                }
284            }
285            None
286        } else {
287            Some(self)
288        }
289    }
290    pub fn get_int(&self, tag: &[u8]) -> Option<u64> {
291        let found = self.get(tag);
292        if let Some(TlvItemValue::Int(i)) = found {
293            Some(*i)
294        } else {
295            None
296        }
297    }
298    pub fn get_t<T>(&self, tag: &[u8]) -> Option<T>
299    where
300        T: From<TlvItemValue>,
301    {
302        self.get(tag).map(|f| f.clone().into())
303    }
304
305    pub fn get_bool(&self, tag: &[u8]) -> Option<bool> {
306        self.get(tag).map(|f| f.clone().into())
307        /*let found = self.get(tag);
308        if let Some(TlvItemValue::Bool(i)) = found {
309            Some(*i)
310        } else {
311            None
312        }*/
313    }
314    pub fn get_u8(&self, tag: &[u8]) -> Option<u8> {
315        let found = self.get(tag);
316        if let Some(TlvItemValue::Int(i)) = found {
317            Some(*i as u8)
318        } else {
319            None
320        }
321    }
322    pub fn get_u16(&self, tag: &[u8]) -> Option<u16> {
323        let found = self.get(tag);
324        if let Some(TlvItemValue::Int(i)) = found {
325            Some(*i as u16)
326        } else {
327            None
328        }
329    }
330    pub fn get_u32(&self, tag: &[u8]) -> Option<u32> {
331        let found = self.get(tag);
332        if let Some(TlvItemValue::Int(i)) = found {
333            Some(*i as u32)
334        } else {
335            None
336        }
337    }
338    pub fn get_u64(&self, tag: &[u8]) -> Option<u64> {
339        let found = self.get(tag);
340        if let Some(TlvItemValue::Int(i)) = found {
341            Some(*i)
342        } else {
343            None
344        }
345    }
346    pub fn get_octet_string(&self, tag: &[u8]) -> Option<&[u8]> {
347        let found = self.get(tag);
348        if let Some(TlvItemValue::OctetString(o)) = found {
349            Some(o)
350        } else {
351            None
352        }
353    }
354    pub fn get_octet_string_owned(&self, tag: &[u8]) -> Option<Vec<u8>> {
355        let found = self.get(tag);
356        if let Some(TlvItemValue::OctetString(o)) = found {
357            Some(o.to_owned())
358        } else {
359            None
360        }
361    }
362    pub fn get_string_owned(&self, tag: &[u8]) -> Option<String> {
363        let found = self.get(tag);
364        if let Some(TlvItemValue::String(o)) = found {
365            Some(o.clone())
366        } else {
367            None
368        }
369    }
370    pub fn dump(&self, indent: usize) {
371        match &self.value {
372            TlvItemValue::List(vec) => {
373                println!("{} {}", " ".to_owned().repeat(indent), self.tag);
374                for v in vec {
375                    v.dump(indent + 1);
376                }
377            }
378            _ => {
379                println!(
380                    "{} {} {:?}",
381                    " ".to_owned().repeat(indent),
382                    self.tag,
383                    self.value
384                );
385            }
386        }
387    }
388}
389
390fn read_tag(tagctrl: u8, cursor: &mut Cursor<&[u8]>) -> Result<u8> {
391    if tagctrl == 1 {
392        cursor.read_u8()
393    } else {
394        Ok(0)
395    }
396}
397
398fn decode(cursor: &mut Cursor<&[u8]>, container: &mut Vec<TlvItem>) -> Result<()> {
399    while cursor.position() < cursor.get_ref().len() as u64 {
400        let fb = cursor.read_u8()?;
401        let tp = fb & 0x1f;
402        let tagctrl = fb >> 5;
403        let tag = read_tag(tagctrl, cursor)?;
404        match tp {
405            TYPE_INT_1 => {
406                let value = cursor.read_u8()?;
407                let item = TlvItem {
408                    tag,
409                    value: TlvItemValue::Int(value as u64),
410                };
411                container.push(item);
412            }
413            TYPE_INT_2 => {
414                let value = cursor.read_i16::<LittleEndian>()?;
415                let item = TlvItem {
416                    tag,
417                    value: TlvItemValue::Int(value as u64),
418                };
419                container.push(item);
420            }
421            TYPE_INT_4 => {
422                let value = cursor.read_i32::<LittleEndian>()?;
423                let item = TlvItem {
424                    tag,
425                    value: TlvItemValue::Int(value as u64),
426                };
427                container.push(item);
428            }
429            TYPE_UINT_1 => {
430                let value = cursor.read_u8()?;
431                let item = TlvItem {
432                    tag,
433                    value: TlvItemValue::Int(value as u64),
434                };
435                container.push(item);
436            }
437            TYPE_UINT_2 => {
438                let value = cursor.read_u16::<LittleEndian>()?;
439                let item = TlvItem {
440                    tag,
441                    value: TlvItemValue::Int(value as u64),
442                };
443                container.push(item);
444            }
445            TYPE_UINT_4 => {
446                let value = cursor.read_u32::<LittleEndian>()?;
447                let item = TlvItem {
448                    tag,
449                    value: TlvItemValue::Int(value as u64),
450                };
451                container.push(item);
452            }
453            TYPE_UINT_8 => {
454                let value = cursor.read_u64::<LittleEndian>()?;
455                let item = TlvItem {
456                    tag,
457                    value: TlvItemValue::Int(value),
458                };
459                container.push(item);
460            }
461            TYPE_BOOL_FALSE => {
462                let item = TlvItem {
463                    tag,
464                    value: TlvItemValue::Bool(false),
465                };
466                container.push(item);
467            }
468            TYPE_BOOL_TRUE => {
469                let item = TlvItem {
470                    tag,
471                    value: TlvItemValue::Bool(true),
472                };
473                container.push(item);
474            }
475            TYPE_UTF8_L1 => {
476                // utf8 string
477                let size = cursor.read_u8()?;
478                let mut value = vec![0; size as usize];
479                cursor.read_exact(&mut value)?;
480                let str = String::from_utf8(value);
481                let typ = match str {
482                    Ok(s) => TlvItemValue::String(s),
483                    Err(_) => TlvItemValue::Invalid(),
484                };
485                let item = TlvItem { tag, value: typ };
486                container.push(item);
487            }
488            TYPE_OCTET_STRING_L1 => {
489                // octet string
490                let size = cursor.read_u8()?;
491                let mut value = vec![0; size as usize];
492                cursor.read_exact(&mut value)?;
493                let item = TlvItem {
494                    tag,
495                    value: TlvItemValue::OctetString(value),
496                };
497                container.push(item);
498            }
499            TYPE_OCTET_STRING_L2 => {
500                // octet string large
501                let size = cursor.read_u16::<LittleEndian>()?;
502                let mut value = vec![0; size as usize];
503                cursor.read_exact(&mut value)?;
504                let item = TlvItem {
505                    tag,
506                    value: TlvItemValue::OctetString(value),
507                };
508                container.push(item);
509            }
510            TYPE_OCTET_STRING_L4 => {
511                // octet string very large
512                let size = cursor.read_u32::<LittleEndian>()?;
513                let mut value = vec![0; size as usize];
514                cursor.read_exact(&mut value)?;
515                let item = TlvItem {
516                    tag,
517                    value: TlvItemValue::OctetString(value),
518                };
519                container.push(item);
520            }
521            TYPE_STRUCT => {
522                //list
523                let mut c2 = Vec::new();
524                decode(cursor, &mut c2)?;
525                let item = TlvItem {
526                    tag,
527                    value: TlvItemValue::List(c2),
528                };
529                container.push(item);
530            }
531            TYPE_ARRAY => {
532                //list
533                let mut c2 = Vec::new();
534                decode(cursor, &mut c2)?;
535                let item = TlvItem {
536                    tag,
537                    value: TlvItemValue::List(c2),
538                };
539                container.push(item);
540            }
541            TYPE_LIST => {
542                //list
543                let mut c2 = Vec::new();
544                decode(cursor, &mut c2)?;
545                let item = TlvItem {
546                    tag,
547                    value: TlvItemValue::List(c2),
548                };
549                container.push(item);
550            }
551            TYPE_END_CONTAINER => return Ok(()),
552            0x14 => {
553                let item = TlvItem {
554                    tag,
555                    value: TlvItemValue::Nil(),
556                };
557                container.push(item);
558            }
559            _ => {
560                return Err(std::io::Error::new(
561                    std::io::ErrorKind::InvalidData,
562                    format!("unknown tlv type 0x{:x}", tp),
563                ))
564            }
565        }
566    }
567    Ok(())
568}
569
570/// decode raw buffer with tlv data
571pub fn decode_tlv(data: &[u8]) -> Result<TlvItem> {
572    let mut container = Vec::new();
573    let mut cursor = std::io::Cursor::new(data);
574    decode(&mut cursor, &mut container)?;
575    if container.len() == 1 {
576        if let Some(i) = container.pop() {
577            Ok(i)
578        } else {
579            Err(std::io::Error::new(
580                std::io::ErrorKind::InvalidData,
581                "no data found",
582            ))
583        }
584    } else {
585        Ok(TlvItem {
586            tag: 0,
587            value: TlvItemValue::List(container),
588        })
589    }
590}
591
592#[derive(Debug)]
593pub enum TlvItemValueEnc {
594    Int8(i8),
595    Int16(i16),
596    Int32(i32),
597    Int64(i64),
598    UInt8(u8),
599    UInt8Anonymous(u8),
600    UInt16(u16),
601    UInt32(u32),
602    UInt64(u64),
603    Bool(bool),
604    String(String),
605    OctetString(Vec<u8>),
606    StructAnon(Vec<TlvItemEnc>),
607    StructInvisible(Vec<TlvItemEnc>),
608    Struct(Vec<TlvItemEnc>),
609    List(Vec<TlvItemEnc>),
610    Array(Vec<TlvItemEnc>),
611    Invalid(),
612}
613
614/// Structure used for document style encoding.
615///
616/// ```
617/// # use matc::tlv;
618/// let t1 = tlv::TlvItemEnc {
619///   tag: 0,
620///   value: tlv::TlvItemValueEnc::StructAnon(vec![
621///     tlv::TlvItemEnc { tag: 0, value: tlv::TlvItemValueEnc::UInt8(6) },
622///     tlv::TlvItemEnc { tag: 1, value: tlv::TlvItemValueEnc::UInt8(7) }
623///   ]),
624/// };
625/// let o = t1.encode().unwrap();
626/// ```
627#[derive(Debug)]
628pub struct TlvItemEnc {
629    pub tag: u8,
630    pub value: TlvItemValueEnc,
631}
632
633impl From<(u8, TlvItemValueEnc)> for TlvItemEnc {
634    fn from(item: (u8, TlvItemValueEnc)) -> Self {
635        TlvItemEnc {
636            tag: item.0,
637            value: item.1,
638        }
639    }
640}
641
642impl TlvItemEnc {
643    fn encode_internal(&self, buf: &mut TlvBuffer) -> Result<()> {
644        match &self.value {
645            TlvItemValueEnc::Int8(i) => {
646                buf.write_int8(self.tag, *i)?;
647            }
648            TlvItemValueEnc::Int16(i) => {
649                buf.write_int16(self.tag, *i)?;
650            }
651            TlvItemValueEnc::Int32(i) => {
652                buf.write_int32(self.tag, *i)?;
653            }
654            TlvItemValueEnc::Int64(i) => {
655                buf.write_int64(self.tag, *i)?;
656            }
657            TlvItemValueEnc::UInt8(i) => {
658                buf.write_uint8(self.tag, *i)?;
659            }
660            TlvItemValueEnc::UInt8Anonymous(i) => {
661                buf.write_uint8_notag(*i)?;
662            }
663            TlvItemValueEnc::UInt16(i) => {
664                buf.write_uint16(self.tag, *i)?;
665            }
666            TlvItemValueEnc::UInt32(i) => {
667                buf.write_uint32(self.tag, *i)?;
668            }
669            TlvItemValueEnc::UInt64(i) => {
670                buf.write_uint64(self.tag, *i)?;
671            }
672            TlvItemValueEnc::Bool(v) => {
673                buf.write_bool(self.tag, *v)?;
674            }
675            TlvItemValueEnc::String(s) => {
676                buf.write_string(self.tag, s)?;
677            }
678            TlvItemValueEnc::OctetString(vec) => {
679                buf.write_octetstring(self.tag, vec)?;
680            }
681            TlvItemValueEnc::StructAnon(vec) => {
682                buf.write_anon_struct()?;
683                for i in vec {
684                    i.encode_internal(buf)?;
685                }
686                buf.write_struct_end()?;
687            }
688            TlvItemValueEnc::Struct(vec) => {
689                buf.write_struct(self.tag)?;
690                for i in vec {
691                    i.encode_internal(buf)?;
692                }
693                buf.write_struct_end()?;
694            }
695            TlvItemValueEnc::List(vec) => {
696                buf.write_list(self.tag)?;
697                for i in vec {
698                    i.encode_internal(buf)?;
699                }
700                buf.write_struct_end()?;
701            }
702            TlvItemValueEnc::Array(vec) => {
703                buf.write_array(self.tag)?;
704                for i in vec {
705                    i.encode_internal(buf)?;
706                }
707                buf.write_struct_end()?;
708            }
709            TlvItemValueEnc::StructInvisible(vec) => {
710                for i in vec {
711                    i.encode_internal(buf)?;
712                }
713            }
714            TlvItemValueEnc::Invalid() => todo!(),
715        }
716        Ok(())
717    }
718
719    pub fn encode(&self) -> Result<Vec<u8>> {
720        let mut tlv = TlvBuffer::new();
721        self.encode_internal(&mut tlv)?;
722        Ok(tlv.data)
723    }
724}
725
726#[cfg(test)]
727mod tests {
728    use super::{decode_tlv, TlvBuffer, TlvItemEnc, TlvItemValue, TlvItemValueEnc};
729
730    #[test]
731    fn test_1() {
732        let t1 = TlvItemEnc {
733            tag: 0,
734            value: TlvItemValueEnc::StructAnon(vec![
735                TlvItemEnc {
736                    tag: 0,
737                    value: TlvItemValueEnc::UInt8(6),
738                },
739                TlvItemEnc {
740                    tag: 1,
741                    value: TlvItemValueEnc::UInt8(7),
742                },
743            ]),
744        };
745        let o = t1.encode().unwrap();
746        assert_eq!(hex::encode(o), "1524000624010718");
747
748        let mut tlv = TlvBuffer::new();
749        tlv.write_anon_struct().unwrap();
750        tlv.write_octetstring(0x1, &[1, 2, 3]).unwrap();
751        tlv.write_struct_end().unwrap();
752        assert_eq!(hex::encode(tlv.data), "1530010301020318");
753
754        let t1 = TlvItemEnc {
755            tag: 0,
756            value: TlvItemValueEnc::StructAnon(vec![TlvItemEnc {
757                tag: 1,
758                value: TlvItemValueEnc::OctetString(vec![1, 2, 3]),
759            }]),
760        }
761        .encode()
762        .unwrap();
763        assert_eq!(hex::encode(t1), "1530010301020318");
764    }
765
766    #[test]
767    fn test_decode_integers() {
768        // Test uint8
769        let mut tlv = TlvBuffer::new();
770        tlv.write_uint8(1, 42).unwrap();
771        let decoded = decode_tlv(&tlv.data).unwrap();
772        assert_eq!(decoded.get_u8(&[]), Some(42));
773
774        // Test uint16
775        let mut tlv = TlvBuffer::new();
776        tlv.write_uint16(2, 1000).unwrap();
777        let decoded = decode_tlv(&tlv.data).unwrap();
778        assert_eq!(decoded.get_u16(&[]), Some(1000));
779
780        // Test uint32
781        let mut tlv = TlvBuffer::new();
782        tlv.write_uint32(3, 100000).unwrap();
783        let decoded = decode_tlv(&tlv.data).unwrap();
784        assert_eq!(decoded.get_u32(&[]), Some(100000));
785
786        // Test uint64
787        let mut tlv = TlvBuffer::new();
788        tlv.write_uint64(4, 1000000000000).unwrap();
789        let decoded = decode_tlv(&tlv.data).unwrap();
790        assert_eq!(decoded.get_u64(&[]), Some(1000000000000));
791    }
792
793    #[test]
794    fn test_decode_booleans() {
795        // Test true
796        let mut tlv = TlvBuffer::new();
797        tlv.write_bool(1, true).unwrap();
798        let decoded = decode_tlv(&tlv.data).unwrap();
799        assert_eq!(decoded.get_bool(&[]), Some(true));
800
801        // Test false
802        let mut tlv = TlvBuffer::new();
803        tlv.write_bool(2, false).unwrap();
804        let decoded = decode_tlv(&tlv.data).unwrap();
805        assert_eq!(decoded.get_bool(&[]), Some(false));
806        assert_eq!(decoded.get_t(&[]), Some(false));
807    }
808
809    #[test]
810    fn test_decode_strings() {
811        let mut tlv = TlvBuffer::new();
812        tlv.write_string(1, "hello world").unwrap();
813        let decoded = decode_tlv(&tlv.data).unwrap();
814        assert_eq!(
815            decoded.get_string_owned(&[]),
816            Some("hello world".to_string())
817        );
818        assert_eq!(decoded.get_t(&[]), Some("hello world".to_string()));
819    }
820
821    #[test]
822    fn test_decode_octet_strings() {
823        // Test small octet string (L1)
824        let mut tlv = TlvBuffer::new();
825        let data = vec![1, 2, 3, 4, 5];
826        tlv.write_octetstring(1, &data).unwrap();
827        let decoded = decode_tlv(&tlv.data).unwrap();
828        assert_eq!(decoded.get_octet_string(&[]), Some(data.as_slice()));
829
830        // Test large octet string (L2)
831        let mut tlv = TlvBuffer::new();
832        let large_data = vec![0; 300]; // Larger than 255 bytes
833        tlv.write_octetstring(2, &large_data).unwrap();
834        let decoded = decode_tlv(&tlv.data).unwrap();
835        assert_eq!(decoded.get_octet_string(&[]), Some(large_data.as_slice()));
836        assert_eq!(
837            decoded.get_octet_string_owned(&[]),
838            Some(large_data.clone())
839        );
840    }
841
842    #[test]
843    fn test_decode_structures() {
844        let mut tlv = TlvBuffer::new();
845        tlv.write_struct(1).unwrap();
846        tlv.write_uint8(0, 100).unwrap();
847        tlv.write_string(1, "test").unwrap();
848        tlv.write_bool(2, true).unwrap();
849        tlv.write_struct_end().unwrap();
850
851        let decoded = decode_tlv(&tlv.data).unwrap();
852
853        // Test nested access
854        assert_eq!(decoded.get_u8(&[0]), Some(100));
855        assert_eq!(decoded.get_string_owned(&[1]), Some("test".to_string()));
856        assert_eq!(decoded.get_bool(&[2]), Some(true));
857
858        // Verify it's a list structure
859        if let TlvItemValue::List(items) = &decoded.value {
860            assert_eq!(items.len(), 3);
861        }
862    }
863
864    #[test]
865    fn test_decode_anonymous_structures() {
866        let mut tlv = TlvBuffer::new();
867        tlv.write_anon_struct().unwrap();
868        tlv.write_uint8_notag(42).unwrap();
869        tlv.write_uint8_notag(84).unwrap();
870        tlv.write_struct_end().unwrap();
871
872        let decoded = decode_tlv(&tlv.data).unwrap();
873
874        if let TlvItemValue::List(items) = &decoded.value {
875            assert_eq!(items.len(), 2);
876            assert_eq!(items[0].tag, 0);
877            assert_eq!(items[1].tag, 0);
878        }
879    }
880
881    #[test]
882    fn test_decode_arrays_and_lists() {
883        // Test array
884        let mut tlv = TlvBuffer::new();
885        tlv.write_array(1).unwrap();
886        tlv.write_uint8(0, 1).unwrap();
887        tlv.write_uint8(0, 2).unwrap();
888        tlv.write_uint8(0, 3).unwrap();
889        tlv.write_struct_end().unwrap();
890
891        let decoded = decode_tlv(&tlv.data).unwrap();
892        if let Some(TlvItemValue::List(items)) = decoded.get(&[]) {
893            assert_eq!(items.len(), 3);
894            assert_eq!(items[0].get_u8(&[]), Some(1));
895            assert_eq!(items[1].get_u8(&[]), Some(2));
896            assert_eq!(items[2].get_u8(&[]), Some(3));
897        } else {
898            panic!("Expected array structure");
899        }
900
901        // Test list
902        let mut tlv = TlvBuffer::new();
903        tlv.write_list(2).unwrap();
904        tlv.write_string(0, "item1").unwrap();
905        tlv.write_string(1, "item2").unwrap();
906        tlv.write_struct_end().unwrap();
907
908        let decoded = decode_tlv(&tlv.data).unwrap();
909        if let Some(TlvItemValue::List(items)) = decoded.get(&[]) {
910            assert_eq!(items.len(), 2);
911            assert_eq!(items[0].get_string_owned(&[]), Some("item1".to_string()));
912            assert_eq!(items[1].get_string_owned(&[]), Some("item2".to_string()));
913        } else {
914            panic!("Expected list structure");
915        }
916    }
917
918    #[test]
919    fn test_decode_mixed_container() {
920        let mut tlv = TlvBuffer::new();
921        tlv.write_uint8(0, 255).unwrap();
922        tlv.write_string(1, "mixed").unwrap();
923        tlv.write_bool(2, false).unwrap();
924
925        let decoded = decode_tlv(&tlv.data).unwrap();
926
927        // Should create a list with multiple items
928        if let TlvItemValue::List(items) = &decoded.value {
929            assert_eq!(items.len(), 3);
930            assert_eq!(items[0].get_u8(&[]), Some(255));
931            assert_eq!(items[1].get_string_owned(&[]), Some("mixed".to_string()));
932            assert_eq!(items[2].get_bool(&[]), Some(false));
933        } else {
934            panic!("Expected list of items");
935        }
936    }
937
938    #[test]
939    fn test_decode_nested_structures() {
940        let mut tlv = TlvBuffer::new();
941        tlv.write_struct(1).unwrap();
942        tlv.write_struct(2).unwrap();
943        tlv.write_uint8(3, 42).unwrap();
944        tlv.write_struct_end().unwrap(); // End inner struct
945        tlv.write_string(4, "outer").unwrap();
946        tlv.write_struct_end().unwrap(); // End outer struct
947
948        let decoded = decode_tlv(&tlv.data).unwrap();
949
950        // Test deep nested access
951        assert_eq!(decoded.get_u8(&[2, 3]), Some(42));
952        assert_eq!(decoded.get_string_owned(&[4]), Some("outer".to_string()));
953    }
954
955    #[test]
956    fn test_decode_getter_methods() {
957        let mut tlv = TlvBuffer::new();
958        tlv.write_struct(0).unwrap();
959        tlv.write_uint64(1, 0xFFFFFFFFFFFFFFFF).unwrap();
960        tlv.write_uint32(2, 0xFFFFFFFF).unwrap();
961        tlv.write_uint16(3, 0xFFFF).unwrap();
962        tlv.write_uint8(4, 0xFF).unwrap();
963        tlv.write_struct_end().unwrap();
964
965        let decoded = decode_tlv(&tlv.data).unwrap();
966
967        // Test type conversions
968        assert_eq!(decoded.get_u64(&[1]), Some(0xFFFFFFFFFFFFFFFF));
969        assert_eq!(decoded.get_u32(&[2]), Some(0xFFFFFFFF));
970        assert_eq!(decoded.get_u16(&[3]), Some(0xFFFF));
971        assert_eq!(decoded.get_u8(&[4]), Some(0xFF));
972
973        // Test downcasting
974        assert_eq!(decoded.get_u8(&[1]), Some(0xFF)); // u64 -> u8
975        assert_eq!(decoded.get_u16(&[1]), Some(0xFFFF)); // u64 -> u16
976    }
977
978    #[test]
979    fn test_decode_invalid_access() {
980        let mut tlv = TlvBuffer::new();
981        tlv.write_uint8(1, 42).unwrap();
982        let decoded = decode_tlv(&tlv.data).unwrap();
983
984        // Test accessing non-existent tags
985        assert_eq!(decoded.get_u8(&[99]), None);
986        assert_eq!(decoded.get_string_owned(&[1]), None); // Wrong type
987        assert_eq!(decoded.get_bool(&[1]), None); // Wrong type
988    }
989
990    #[test]
991    fn test_decode_empty_structure() {
992        let mut tlv = TlvBuffer::new();
993        tlv.write_anon_struct().unwrap();
994        tlv.write_struct_end().unwrap();
995
996        let decoded = decode_tlv(&tlv.data).unwrap();
997
998        if let TlvItemValue::List(items) = &decoded.value {
999            assert_eq!(items.len(), 0);
1000        } else {
1001            panic!("Expected empty list");
1002        }
1003    }
1004
1005    #[test]
1006    fn test_get_item_method() {
1007        let mut tlv = TlvBuffer::new();
1008        tlv.write_struct(1).unwrap();
1009        tlv.write_uint8(2, 100).unwrap();
1010        tlv.write_string(3, "test").unwrap();
1011        tlv.write_bool(4, true).unwrap();
1012        tlv.write_struct(5).unwrap();
1013        tlv.write_string(1, "inner").unwrap();
1014        tlv.write_struct_end().unwrap();
1015        tlv.write_struct_end().unwrap();
1016
1017        let decoded = decode_tlv(&tlv.data).unwrap();
1018
1019        // Test get_item returns the actual item
1020        let item = decoded.get_item(&[2]).unwrap();
1021        assert_eq!(item.tag, 2);
1022        if let TlvItemValue::Int(val) = &item.value {
1023            assert_eq!(*val, 100);
1024        } else {
1025            panic!("Expected Int value");
1026        }
1027        let item = decoded.get_item(&[3]).unwrap();
1028        assert_eq!(item.tag, 3);
1029        if let TlvItemValue::String(val) = &item.value {
1030            assert_eq!(*val, "test");
1031        } else {
1032            panic!("Expected String value");
1033        }
1034        let item = decoded.get_item(&[4]).unwrap();
1035        assert_eq!(item.tag, 4);
1036        if let TlvItemValue::Bool(val) = &item.value {
1037            assert!(*val);
1038        } else {
1039            panic!("Expected Bool value");
1040        }
1041        let item = decoded.get_item(&[5]).unwrap();
1042        assert_eq!(item.tag, 5);
1043        if let TlvItemValue::List(items) = &item.value {
1044            assert_eq!(items.len(), 1);
1045            let inner_item = &items[0];
1046            assert_eq!(inner_item.tag, 1);
1047            if let TlvItemValue::String(val) = &inner_item.value {
1048                assert_eq!(*val, "inner");
1049            } else {
1050                panic!("Expected String value");
1051            }
1052        } else {
1053            panic!("Expected List value");
1054        }
1055        let item = decoded.get_item(&[99]);
1056        assert!(item.is_none());
1057    }
1058}