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