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