1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
4use core::fmt;
5use std::io::{Cursor, Read, Result, Write};
6
7pub 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#[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#[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 }
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 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 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 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 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 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 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
529pub 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#[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 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 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 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 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 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 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 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 let mut tlv = TlvBuffer::new();
751 let large_data = vec![0; 300]; 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 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 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 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 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 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(); tlv.write_string(4, "outer").unwrap();
865 tlv.write_struct_end().unwrap(); let decoded = decode_tlv(&tlv.data).unwrap();
868
869 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 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 assert_eq!(decoded.get_u8(&[1]), Some(0xFF)); assert_eq!(decoded.get_u16(&[1]), Some(0xFFFF)); }
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 assert_eq!(decoded.get_u8(&[99]), None);
905 assert_eq!(decoded.get_string_owned(&[1]), None); assert_eq!(decoded.get_bool(&[1]), None); }
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 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}