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