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