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