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