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