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