1use crate::error::{Error, Result};
10use crate::tag::Tag;
11use crate::value::Value;
12use crate::{element_type as et, tag_control as tc};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17#[non_exhaustive]
18pub enum ContainerKind {
19 Structure,
21 Array,
23 List,
25}
26
27#[derive(Debug, Clone, PartialEq)]
29#[non_exhaustive]
30pub enum Element {
31 Scalar {
33 tag: Tag,
35 value: Value,
37 },
38
39 ContainerStart {
43 tag: Tag,
45 kind: ContainerKind,
47 },
48
49 ContainerEnd,
51}
52
53pub const MAX_DEPTH: usize = 32;
57
58pub const DEFAULT_ELEMENT_BUDGET: usize = 1 << 20;
74
75pub struct TlvReader<'a> {
77 bytes: &'a [u8],
78 pos: usize,
79 depth: usize,
80 element_budget: usize,
89}
90
91impl<'a> TlvReader<'a> {
92 pub fn new(bytes: &'a [u8]) -> Self {
95 Self {
96 bytes,
97 pos: 0,
98 depth: 0,
99 element_budget: DEFAULT_ELEMENT_BUDGET,
100 }
101 }
102
103 pub fn with_element_budget(bytes: &'a [u8], budget: usize) -> Self {
111 Self {
112 bytes,
113 pos: 0,
114 depth: 0,
115 element_budget: budget,
116 }
117 }
118
119 pub fn is_empty(&self) -> bool {
121 self.pos >= self.bytes.len()
122 }
123
124 #[allow(clippy::should_implement_trait)] pub fn next(&mut self) -> Result<Option<Element>> {
147 if self.is_empty() {
148 return Ok(None);
149 }
150 let control = self.next_byte()?;
151 let elem_type = control & et::ELEMENT_TYPE_MASK;
152
153 if elem_type == et::END_OF_CONTAINER {
155 if control & tc::TAG_CONTROL_MASK != tc::ANONYMOUS {
156 return Err(Error::InvalidTagControl(control & tc::TAG_CONTROL_MASK));
157 }
158 if self.depth == 0 {
159 return Err(Error::UnexpectedEndOfContainer);
160 }
161 self.depth -= 1;
162 return Ok(Some(Element::ContainerEnd));
163 }
164
165 let tag = self.read_tag(control)?;
166
167 let kind = match elem_type {
169 et::STRUCTURE => Some(ContainerKind::Structure),
170 et::ARRAY => Some(ContainerKind::Array),
171 et::LIST => Some(ContainerKind::List),
172 _ => None,
173 };
174 if let Some(kind) = kind {
175 if self.depth >= MAX_DEPTH {
176 return Err(Error::ContainerTooDeep);
177 }
178 self.depth += 1;
179 return Ok(Some(Element::ContainerStart { tag, kind }));
180 }
181
182 let value = self.read_value_body(elem_type)?;
183 Ok(Some(Element::Scalar { tag, value }))
184 }
185
186 pub fn skip_container(&mut self) -> Result<()> {
230 let mut depth = 1usize;
231 while depth > 0 {
232 match self.next()? {
233 Some(Element::ContainerStart { .. }) => depth += 1,
234 Some(Element::ContainerEnd) => depth -= 1,
235 Some(Element::Scalar { .. }) => {}
236 None => return Err(Error::UnclosedContainer),
237 }
238 }
239 Ok(())
240 }
241
242 pub fn read_value(&mut self) -> Result<(Tag, Value)> {
259 let remaining_input = self.bytes.len().saturating_sub(self.pos);
277 if remaining_input <= self.element_budget {
278 self.read_value_inner::<false>()
279 } else {
280 self.read_value_inner::<true>()
281 }
282 }
283
284 fn read_value_inner<const CHARGE: bool>(&mut self) -> Result<(Tag, Value)> {
289 match self.next()? {
290 Some(Element::Scalar { tag, value }) => {
291 if CHARGE {
292 self.charge_element()?;
293 }
294 Ok((tag, value))
295 }
296 Some(Element::ContainerStart { tag, kind }) => {
297 if CHARGE {
298 self.charge_element()?;
299 }
300 let value = self.read_container_body::<CHARGE>(kind)?;
301 Ok((tag, value))
302 }
303 Some(Element::ContainerEnd) => Err(Error::UnexpectedEndOfContainer),
304 None => Err(Error::UnexpectedEof),
305 }
306 }
307
308 fn charge_element(&mut self) -> Result<()> {
314 self.element_budget = self
315 .element_budget
316 .checked_sub(1)
317 .ok_or(Error::ElementBudgetExceeded)?;
318 Ok(())
319 }
320
321 fn read_container_body<const CHARGE: bool>(&mut self, kind: ContainerKind) -> Result<Value> {
349 match kind {
354 ContainerKind::Array => {
355 let mut elements: Vec<Value> = Vec::new();
356 let mut budget = self.element_budget;
357 loop {
358 match self.next()? {
359 None => return Err(Error::UnclosedContainer),
360 Some(Element::ContainerEnd) => break,
361 Some(Element::Scalar { tag, value }) => {
362 if tag != Tag::Anonymous {
365 return Err(Error::NonAnonymousArrayTag);
366 }
367 if CHARGE {
368 budget =
369 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
370 }
371 elements.push(value);
372 }
373 Some(Element::ContainerStart {
374 tag,
375 kind: inner_kind,
376 }) => {
377 if tag != Tag::Anonymous {
378 return Err(Error::NonAnonymousArrayTag);
379 }
380 if CHARGE {
381 budget =
382 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
383 self.element_budget = budget;
384 }
385 elements.push(self.read_container_body::<CHARGE>(inner_kind)?);
386 if CHARGE {
387 budget = self.element_budget;
388 }
389 }
390 }
391 }
392 if CHARGE {
393 self.element_budget = budget;
394 }
395 Ok(Value::Array(elements))
396 }
397 ContainerKind::Structure | ContainerKind::List => {
398 let mut members: Vec<(Tag, Value)> = Vec::new();
399 let mut budget = self.element_budget;
400 loop {
401 match self.next()? {
402 None => return Err(Error::UnclosedContainer),
403 Some(Element::ContainerEnd) => break,
404 Some(Element::Scalar { tag, value }) => {
405 if CHARGE {
406 budget =
407 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
408 }
409 members.push((tag, value));
410 }
411 Some(Element::ContainerStart {
412 tag,
413 kind: inner_kind,
414 }) => {
415 if CHARGE {
416 budget =
417 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
418 self.element_budget = budget;
419 }
420 let inner = self.read_container_body::<CHARGE>(inner_kind)?;
421 members.push((tag, inner));
422 if CHARGE {
423 budget = self.element_budget;
424 }
425 }
426 }
427 }
428 if CHARGE {
429 self.element_budget = budget;
430 }
431 Ok(match kind {
432 ContainerKind::List => Value::List(members),
433 _ => Value::Structure(members),
435 })
436 }
437 }
438 }
439
440 fn next_byte(&mut self) -> Result<u8> {
441 let b = *self.bytes.get(self.pos).ok_or(Error::UnexpectedEof)?;
442 self.pos += 1;
443 Ok(b)
444 }
445
446 fn next_bytes(&mut self, n: usize) -> Result<&'a [u8]> {
447 let end = self.pos.checked_add(n).ok_or(Error::LengthOverflow)?;
448 let slice = self.bytes.get(self.pos..end).ok_or(Error::UnexpectedEof)?;
449 self.pos = end;
450 Ok(slice)
451 }
452
453 fn read_tag(&mut self, control: u8) -> Result<Tag> {
454 match control & tc::TAG_CONTROL_MASK {
455 tc::ANONYMOUS => Ok(Tag::Anonymous),
456 tc::CONTEXT => {
457 let n = self.next_byte()?;
458 Ok(Tag::Context(n))
459 }
460 tc::COMMON_PROFILE_2 => {
461 let raw: [u8; 2] = self
462 .next_bytes(2)?
463 .try_into()
464 .map_err(|_| Error::InternalSliceConversion)?;
465 Ok(Tag::CommonProfile(u32::from(u16::from_le_bytes(raw))))
466 }
467 tc::COMMON_PROFILE_4 => {
468 let raw: [u8; 4] = self
469 .next_bytes(4)?
470 .try_into()
471 .map_err(|_| Error::InternalSliceConversion)?;
472 Ok(Tag::CommonProfile(u32::from_le_bytes(raw)))
473 }
474 tc::IMPLICIT_PROFILE_2 => {
475 let raw: [u8; 2] = self
476 .next_bytes(2)?
477 .try_into()
478 .map_err(|_| Error::InternalSliceConversion)?;
479 Ok(Tag::ImplicitProfile(u32::from(u16::from_le_bytes(raw))))
480 }
481 tc::IMPLICIT_PROFILE_4 => {
482 let raw: [u8; 4] = self
483 .next_bytes(4)?
484 .try_into()
485 .map_err(|_| Error::InternalSliceConversion)?;
486 Ok(Tag::ImplicitProfile(u32::from_le_bytes(raw)))
487 }
488 tc::FULLY_QUALIFIED_6 => {
489 let vendor = self.read_u16_le()?;
490 let profile = self.read_u16_le()?;
491 let tag = u32::from(self.read_u16_le()?);
492 Ok(Tag::FullyQualified {
493 vendor,
494 profile,
495 tag,
496 })
497 }
498 tc::FULLY_QUALIFIED_8 => {
499 let vendor = self.read_u16_le()?;
500 let profile = self.read_u16_le()?;
501 let tag = self.read_u32_le()?;
502 Ok(Tag::FullyQualified {
503 vendor,
504 profile,
505 tag,
506 })
507 }
508 other => Err(Error::InvalidTagControl(other)),
512 }
513 }
514
515 fn read_u16_le(&mut self) -> Result<u16> {
516 let raw: [u8; 2] = self
517 .next_bytes(2)?
518 .try_into()
519 .map_err(|_| Error::InternalSliceConversion)?;
520 Ok(u16::from_le_bytes(raw))
521 }
522
523 fn read_u32_le(&mut self) -> Result<u32> {
524 let raw: [u8; 4] = self
525 .next_bytes(4)?
526 .try_into()
527 .map_err(|_| Error::InternalSliceConversion)?;
528 Ok(u32::from_le_bytes(raw))
529 }
530
531 #[allow(clippy::cast_possible_wrap)] fn read_value_body(&mut self, elem_type: u8) -> Result<Value> {
533 match elem_type {
534 et::BOOL_FALSE => Ok(Value::Bool(false)),
535 et::BOOL_TRUE => Ok(Value::Bool(true)),
536 et::NULL => Ok(Value::Null),
537 et::UINT8 => Ok(Value::Uint(u64::from(self.next_byte()?))),
538 et::UINT16 => {
539 let raw: [u8; 2] = self
540 .next_bytes(2)?
541 .try_into()
542 .map_err(|_| Error::InternalSliceConversion)?;
543 Ok(Value::Uint(u64::from(u16::from_le_bytes(raw))))
544 }
545 et::UINT32 => {
546 let raw: [u8; 4] = self
547 .next_bytes(4)?
548 .try_into()
549 .map_err(|_| Error::InternalSliceConversion)?;
550 Ok(Value::Uint(u64::from(u32::from_le_bytes(raw))))
551 }
552 et::UINT64 => {
553 let raw: [u8; 8] = self
554 .next_bytes(8)?
555 .try_into()
556 .map_err(|_| Error::InternalSliceConversion)?;
557 Ok(Value::Uint(u64::from_le_bytes(raw)))
558 }
559 et::INT8 => {
560 let b = self.next_byte()?;
561 Ok(Value::Int(i64::from(b as i8)))
562 }
563 et::INT16 => {
564 let raw: [u8; 2] = self
565 .next_bytes(2)?
566 .try_into()
567 .map_err(|_| Error::InternalSliceConversion)?;
568 Ok(Value::Int(i64::from(i16::from_le_bytes(raw))))
569 }
570 et::INT32 => {
571 let raw: [u8; 4] = self
572 .next_bytes(4)?
573 .try_into()
574 .map_err(|_| Error::InternalSliceConversion)?;
575 Ok(Value::Int(i64::from(i32::from_le_bytes(raw))))
576 }
577 et::INT64 => {
578 let raw: [u8; 8] = self
579 .next_bytes(8)?
580 .try_into()
581 .map_err(|_| Error::InternalSliceConversion)?;
582 Ok(Value::Int(i64::from_le_bytes(raw)))
583 }
584 et::FLOAT32 => {
585 let raw: [u8; 4] = self
586 .next_bytes(4)?
587 .try_into()
588 .map_err(|_| Error::InternalSliceConversion)?;
589 Ok(Value::Float(f32::from_le_bytes(raw)))
590 }
591 et::FLOAT64 => {
592 let raw: [u8; 8] = self
593 .next_bytes(8)?
594 .try_into()
595 .map_err(|_| Error::InternalSliceConversion)?;
596 Ok(Value::Double(f64::from_le_bytes(raw)))
597 }
598 et::UTF8_LEN8 | et::UTF8_LEN16 | et::UTF8_LEN32 | et::UTF8_LEN64 => {
599 let len = self.read_payload_len(elem_type)?;
600 self.read_utf8(len)
601 }
602 et::BYTES_LEN8 | et::BYTES_LEN16 | et::BYTES_LEN32 | et::BYTES_LEN64 => {
603 let len = self.read_payload_len(elem_type)?;
604 self.read_bytes(len)
605 }
606 other => Err(Error::InvalidElementType(other)),
607 }
608 }
609
610 fn read_payload_len(&mut self, elem_type: u8) -> Result<usize> {
614 match elem_type & 0b11 {
615 0b00 => Ok(usize::from(self.next_byte()?)),
616 0b01 => Ok(usize::from(self.read_u16_le()?)),
617 0b10 => usize::try_from(self.read_u32_le()?).map_err(|_| Error::LengthOverflow),
618 _ => usize::try_from(self.read_u64_le()?).map_err(|_| Error::LengthOverflow),
619 }
620 }
621
622 fn read_u64_le(&mut self) -> Result<u64> {
623 let raw: [u8; 8] = self
624 .next_bytes(8)?
625 .try_into()
626 .map_err(|_| Error::InternalSliceConversion)?;
627 Ok(u64::from_le_bytes(raw))
628 }
629
630 fn read_utf8(&mut self, len: usize) -> Result<Value> {
631 let bytes = self.next_bytes(len)?;
632 let s = core::str::from_utf8(bytes)?;
642 let text = match s.find('\u{1F}') {
645 Some(i) => &s[..i],
646 None => s,
647 };
648 Ok(Value::Utf8(String::from(text)))
649 }
650
651 fn read_bytes(&mut self, len: usize) -> Result<Value> {
652 let bytes = self.next_bytes(len)?;
653 Ok(Value::Bytes(bytes.to_vec()))
654 }
655}
656
657#[cfg(test)]
658#[allow(clippy::unwrap_used)] mod tests {
660 use super::*;
661
662 #[test]
663 fn next_returns_none_on_empty_input() {
664 let mut r = TlvReader::new(&[]);
665 assert!(r.is_empty());
666 assert_eq!(r.next().unwrap(), None);
667 }
668
669 #[test]
670 fn next_decodes_bool_true_anonymous_vector_0001() {
671 let mut r = TlvReader::new(&[0x09]);
672 let el = r.next().unwrap().unwrap();
673 assert_eq!(
674 el,
675 Element::Scalar {
676 tag: Tag::Anonymous,
677 value: Value::Bool(true)
678 }
679 );
680 assert!(r.is_empty());
681 }
682
683 #[test]
684 fn next_decodes_bool_false() {
685 let mut r = TlvReader::new(&[0x08]);
686 let el = r.next().unwrap().unwrap();
687 assert_eq!(
688 el,
689 Element::Scalar {
690 tag: Tag::Anonymous,
691 value: Value::Bool(false)
692 }
693 );
694 }
695
696 #[test]
697 fn next_decodes_null_vector_implied() {
698 let mut r = TlvReader::new(&[0x14]);
699 let el = r.next().unwrap().unwrap();
700 assert_eq!(
701 el,
702 Element::Scalar {
703 tag: Tag::Anonymous,
704 value: Value::Null
705 }
706 );
707 }
708
709 #[test]
710 fn next_decodes_uint8_42_vector_0003() {
711 let mut r = TlvReader::new(&[0x04, 0x2A]);
712 let el = r.next().unwrap().unwrap();
713 assert_eq!(
714 el,
715 Element::Scalar {
716 tag: Tag::Anonymous,
717 value: Value::Uint(42)
718 }
719 );
720 }
721
722 #[test]
723 fn next_decodes_uint16_0x1234() {
724 let mut r = TlvReader::new(&[0x05, 0x34, 0x12]);
725 let el = r.next().unwrap().unwrap();
726 assert_eq!(
727 el,
728 Element::Scalar {
729 tag: Tag::Anonymous,
730 value: Value::Uint(0x1234)
731 }
732 );
733 }
734
735 #[test]
736 fn next_decodes_uint32_0xcafebabe() {
737 let mut r = TlvReader::new(&[0x06, 0xBE, 0xBA, 0xFE, 0xCA]);
738 let el = r.next().unwrap().unwrap();
739 assert_eq!(
740 el,
741 Element::Scalar {
742 tag: Tag::Anonymous,
743 value: Value::Uint(0xCAFE_BABE)
744 }
745 );
746 }
747
748 #[test]
749 fn next_decodes_uint64_big() {
750 let bytes = [0x07, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01];
751 let mut r = TlvReader::new(&bytes);
752 let el = r.next().unwrap().unwrap();
753 assert_eq!(
754 el,
755 Element::Scalar {
756 tag: Tag::Anonymous,
757 value: Value::Uint(0x0123_4567_89AB_CDEF),
758 }
759 );
760 }
761
762 #[test]
763 fn next_decodes_int8_neg17_vector_0008() {
764 let mut r = TlvReader::new(&[0x00, 0xEF]);
765 let el = r.next().unwrap().unwrap();
766 assert_eq!(
767 el,
768 Element::Scalar {
769 tag: Tag::Anonymous,
770 value: Value::Int(-17)
771 }
772 );
773 }
774
775 #[test]
776 fn next_decodes_int16_neg129() {
777 let mut r = TlvReader::new(&[0x01, 0x7F, 0xFF]);
778 let el = r.next().unwrap().unwrap();
779 assert_eq!(
780 el,
781 Element::Scalar {
782 tag: Tag::Anonymous,
783 value: Value::Int(-129)
784 }
785 );
786 }
787
788 #[test]
789 fn next_decodes_int32_min() {
790 let mut r = TlvReader::new(&[0x02, 0x00, 0x00, 0x00, 0x80]);
791 let el = r.next().unwrap().unwrap();
792 assert_eq!(
793 el,
794 Element::Scalar {
795 tag: Tag::Anonymous,
796 value: Value::Int(i64::from(i32::MIN))
797 }
798 );
799 }
800
801 #[test]
802 fn next_decodes_int64_min() {
803 let bytes = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80];
804 let mut r = TlvReader::new(&bytes);
805 let el = r.next().unwrap().unwrap();
806 assert_eq!(
807 el,
808 Element::Scalar {
809 tag: Tag::Anonymous,
810 value: Value::Int(i64::MIN)
811 }
812 );
813 }
814
815 #[test]
816 fn next_decodes_float32_zero_vector_0013() {
817 let mut r = TlvReader::new(&[0x0A, 0x00, 0x00, 0x00, 0x00]);
818 let el = r.next().unwrap().unwrap();
819 assert_eq!(
820 el,
821 Element::Scalar {
822 tag: Tag::Anonymous,
823 value: Value::Float(0.0)
824 }
825 );
826 }
827
828 #[test]
829 fn next_decodes_float64_zero_vector_0014() {
830 let bytes = [0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
831 let mut r = TlvReader::new(&bytes);
832 let el = r.next().unwrap().unwrap();
833 assert_eq!(
834 el,
835 Element::Scalar {
836 tag: Tag::Anonymous,
837 value: Value::Double(0.0)
838 }
839 );
840 }
841
842 #[test]
843 fn next_decodes_uint_with_context_tag_5() {
844 let mut r = TlvReader::new(&[0x24, 0x05, 0x2A]);
845 let el = r.next().unwrap().unwrap();
846 assert_eq!(
847 el,
848 Element::Scalar {
849 tag: Tag::Context(5),
850 value: Value::Uint(42)
851 }
852 );
853 }
854
855 #[test]
856 fn next_errors_on_unexpected_eof_in_payload() {
857 let mut r = TlvReader::new(&[0x05]); assert!(matches!(r.next(), Err(Error::UnexpectedEof)));
859 }
860
861 #[test]
862 fn next_decodes_uint_with_common_profile_2_byte_tag() {
863 let mut r = TlvReader::new(&[0x44, 0x07, 0x00, 0x2A]);
864 let el = r.next().unwrap().unwrap();
865 assert_eq!(
866 el,
867 Element::Scalar {
868 tag: Tag::CommonProfile(7),
869 value: Value::Uint(42)
870 }
871 );
872 }
873
874 #[test]
875 fn next_decodes_uint_with_common_profile_4_byte_tag() {
876 let mut r = TlvReader::new(&[0x64, 0x45, 0x23, 0x01, 0x00, 0x2A]);
877 let el = r.next().unwrap().unwrap();
878 assert_eq!(
879 el,
880 Element::Scalar {
881 tag: Tag::CommonProfile(0x0001_2345),
882 value: Value::Uint(42)
883 }
884 );
885 }
886
887 #[test]
888 fn next_decodes_uint_with_implicit_profile_2_byte_tag() {
889 let mut r = TlvReader::new(&[0x84, 0x07, 0x00, 0x2A]);
890 let el = r.next().unwrap().unwrap();
891 assert_eq!(
892 el,
893 Element::Scalar {
894 tag: Tag::ImplicitProfile(7),
895 value: Value::Uint(42)
896 }
897 );
898 }
899
900 #[test]
901 fn next_decodes_uint_with_implicit_profile_4_byte_tag() {
902 let mut r = TlvReader::new(&[0xA4, 0x45, 0x23, 0x01, 0x00, 0x2A]);
903 let el = r.next().unwrap().unwrap();
904 assert_eq!(
905 el,
906 Element::Scalar {
907 tag: Tag::ImplicitProfile(0x0001_2345),
908 value: Value::Uint(42)
909 }
910 );
911 }
912
913 #[test]
914 fn next_decodes_uint_with_fully_qualified_6_byte() {
915 let mut r = TlvReader::new(&[0xC4, 0xF1, 0xFF, 0x06, 0x00, 0x05, 0x00, 0x2A]);
916 let el = r.next().unwrap().unwrap();
917 assert_eq!(
918 el,
919 Element::Scalar {
920 tag: Tag::FullyQualified {
921 vendor: 0xFFF1,
922 profile: 0x0006,
923 tag: 5
924 },
925 value: Value::Uint(42),
926 }
927 );
928 }
929
930 #[test]
931 fn next_decodes_uint_with_fully_qualified_8_byte() {
932 let mut r = TlvReader::new(&[0xE4, 0xF1, 0xFF, 0x06, 0x00, 0x45, 0x23, 0x01, 0x00, 0x2A]);
933 let el = r.next().unwrap().unwrap();
934 assert_eq!(
935 el,
936 Element::Scalar {
937 tag: Tag::FullyQualified {
938 vendor: 0xFFF1,
939 profile: 0x0006,
940 tag: 0x0001_2345
941 },
942 value: Value::Uint(42),
943 }
944 );
945 }
946
947 #[test]
948 fn read_value_returns_tag_and_value_for_scalar() {
949 let mut r = TlvReader::new(&[0x24, 0x05, 0x2A]);
950 let (tag, value) = r.read_value().unwrap();
951 assert_eq!(tag, Tag::Context(5));
952 assert_eq!(value, Value::Uint(42));
953 }
954
955 #[test]
956 fn read_value_errors_on_empty_input() {
957 let mut r = TlvReader::new(&[]);
958 assert!(matches!(r.read_value(), Err(Error::UnexpectedEof)));
959 }
960
961 #[test]
962 fn next_decodes_utf8_hello_vector_0015() {
963 let bytes = [0x0C, 0x06, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21];
964 let mut r = TlvReader::new(&bytes);
965 let el = r.next().unwrap().unwrap();
966 assert_eq!(
967 el,
968 Element::Scalar {
969 tag: Tag::Anonymous,
970 value: Value::Utf8(String::from("Hello!")),
971 }
972 );
973 }
974
975 #[test]
976 fn next_decodes_utf8_empty_vector_0016() {
977 let bytes = [0x0C, 0x00];
978 let mut r = TlvReader::new(&bytes);
979 let el = r.next().unwrap().unwrap();
980 assert_eq!(
981 el,
982 Element::Scalar {
983 tag: Tag::Anonymous,
984 value: Value::Utf8(String::new()),
985 }
986 );
987 }
988
989 #[test]
990 fn next_decodes_utf8_len16_path() {
991 let mut bytes = vec![0x0D, 0x00, 0x01]; bytes.extend(std::iter::repeat_n(b'a', 256));
993 let mut r = TlvReader::new(&bytes);
994 let el = r.next().unwrap().unwrap();
995 let Element::Scalar {
996 value: Value::Utf8(s),
997 ..
998 } = el
999 else {
1000 panic!("wrong variant")
1001 };
1002 assert_eq!(s.len(), 256);
1003 assert!(s.bytes().all(|b| b == b'a'));
1004 }
1005
1006 #[test]
1007 fn next_decodes_bytes_five_bytes_vector_0017() {
1008 let bytes = [0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04];
1009 let mut r = TlvReader::new(&bytes);
1010 let el = r.next().unwrap().unwrap();
1011 assert_eq!(
1012 el,
1013 Element::Scalar {
1014 tag: Tag::Anonymous,
1015 value: Value::Bytes(vec![0x00, 0x01, 0x02, 0x03, 0x04]),
1016 }
1017 );
1018 }
1019
1020 #[test]
1021 fn next_decodes_bytes_empty_vector_0018() {
1022 let bytes = [0x10, 0x00];
1023 let mut r = TlvReader::new(&bytes);
1024 let el = r.next().unwrap().unwrap();
1025 assert_eq!(
1026 el,
1027 Element::Scalar {
1028 tag: Tag::Anonymous,
1029 value: Value::Bytes(Vec::new()),
1030 }
1031 );
1032 }
1033
1034 #[test]
1035 fn next_errors_on_invalid_utf8() {
1036 let bytes = [0x0C, 0x01, 0xFF];
1037 let mut r = TlvReader::new(&bytes);
1038 assert!(matches!(r.next(), Err(Error::InvalidUtf8(_))));
1039 }
1040
1041 #[test]
1042 fn next_errors_on_truncated_utf8_payload() {
1043 let bytes = [0x0C, 0x05, b'H', b'i']; let mut r = TlvReader::new(&bytes);
1045 assert!(matches!(r.next(), Err(Error::UnexpectedEof)));
1046 }
1047
1048 #[test]
1051 fn next_decodes_structure_start_and_end_vector_0019() {
1052 let mut r = TlvReader::new(&[0x15, 0x18]);
1053 let el = r.next().unwrap().unwrap();
1054 assert_eq!(
1055 el,
1056 Element::ContainerStart {
1057 tag: Tag::Anonymous,
1058 kind: ContainerKind::Structure,
1059 }
1060 );
1061 let el = r.next().unwrap().unwrap();
1062 assert_eq!(el, Element::ContainerEnd);
1063 assert!(r.next().unwrap().is_none());
1064 }
1065
1066 #[test]
1067 fn next_decodes_array_start_and_end_vector_0020() {
1068 let mut r = TlvReader::new(&[0x16, 0x18]);
1069 assert_eq!(
1070 r.next().unwrap().unwrap(),
1071 Element::ContainerStart {
1072 tag: Tag::Anonymous,
1073 kind: ContainerKind::Array,
1074 }
1075 );
1076 assert_eq!(r.next().unwrap().unwrap(), Element::ContainerEnd);
1077 }
1078
1079 #[test]
1080 fn next_decodes_list_start_and_end() {
1081 let mut r = TlvReader::new(&[0x17, 0x18]);
1082 assert_eq!(
1083 r.next().unwrap().unwrap(),
1084 Element::ContainerStart {
1085 tag: Tag::Anonymous,
1086 kind: ContainerKind::List,
1087 }
1088 );
1089 assert_eq!(r.next().unwrap().unwrap(), Element::ContainerEnd);
1090 }
1091
1092 #[test]
1093 fn next_decodes_structure_with_child_streaming() {
1094 let mut r = TlvReader::new(&[0x15, 0x24, 0x00, 0x2A, 0x18]);
1095 assert_eq!(
1096 r.next().unwrap().unwrap(),
1097 Element::ContainerStart {
1098 tag: Tag::Anonymous,
1099 kind: ContainerKind::Structure,
1100 }
1101 );
1102 assert_eq!(
1103 r.next().unwrap().unwrap(),
1104 Element::Scalar {
1105 tag: Tag::Context(0),
1106 value: Value::Uint(42),
1107 }
1108 );
1109 assert_eq!(r.next().unwrap().unwrap(), Element::ContainerEnd);
1110 assert!(r.next().unwrap().is_none());
1111 }
1112
1113 #[test]
1114 fn next_errors_on_end_of_container_at_top_level() {
1115 let mut r = TlvReader::new(&[0x18]);
1116 assert!(matches!(r.next(), Err(Error::UnexpectedEndOfContainer)));
1117 }
1118
1119 #[test]
1120 fn next_errors_on_end_of_container_with_non_anonymous_tag_form() {
1121 let mut r = TlvReader::new(&[0x38, 0x05]);
1123 assert!(matches!(r.next(), Err(Error::InvalidTagControl(_))));
1124 }
1125
1126 #[test]
1127 fn next_errors_on_excessive_nesting() {
1128 let bytes: Vec<u8> = std::iter::repeat_n(0x15u8, 33).collect();
1129 let mut r = TlvReader::new(&bytes);
1130 for _ in 0..32 {
1131 assert!(matches!(
1132 r.next().unwrap().unwrap(),
1133 Element::ContainerStart {
1134 kind: ContainerKind::Structure,
1135 ..
1136 },
1137 ));
1138 }
1139 assert!(matches!(r.next(), Err(Error::ContainerTooDeep)));
1140 }
1141
1142 #[test]
1143 fn depth_returns_to_zero_after_balanced_close() {
1144 {
1147 let mut r = TlvReader::new(&[0x15, 0x18]);
1148 let _ = r.next(); let _ = r.next(); }
1151 let mut r2 = TlvReader::new(&[0x18]);
1152 assert!(matches!(r2.next(), Err(Error::UnexpectedEndOfContainer)));
1153 }
1154
1155 #[test]
1158 fn read_value_returns_empty_structure_vector_0019() {
1159 let mut r = TlvReader::new(&[0x15, 0x18]);
1160 let (tag, value) = r.read_value().unwrap();
1161 assert_eq!(tag, Tag::Anonymous);
1162 assert_eq!(value, Value::Structure(Vec::new()));
1163 }
1164
1165 #[test]
1166 fn read_value_returns_empty_array_vector_0020() {
1167 let mut r = TlvReader::new(&[0x16, 0x18]);
1168 let (tag, value) = r.read_value().unwrap();
1169 assert_eq!(tag, Tag::Anonymous);
1170 assert_eq!(value, Value::Array(Vec::new()));
1171 }
1172
1173 #[test]
1174 fn read_value_returns_structure_with_ctx_member_vector_0021() {
1175 let mut r = TlvReader::new(&[0x15, 0x24, 0x00, 0x2A, 0x18]);
1176 let (tag, value) = r.read_value().unwrap();
1177 assert_eq!(tag, Tag::Anonymous);
1178 assert_eq!(
1179 value,
1180 Value::Structure(vec![(Tag::Context(0), Value::Uint(42))])
1181 );
1182 }
1183
1184 #[test]
1185 fn read_value_returns_array_of_three_uint8_vector_0022() {
1186 let mut r = TlvReader::new(&[0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18]);
1187 let (tag, value) = r.read_value().unwrap();
1188 assert_eq!(tag, Tag::Anonymous);
1189 assert_eq!(
1190 value,
1191 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1192 );
1193 }
1194
1195 #[test]
1196 fn read_value_returns_structure_with_bool_at_ctx7_vector_0023() {
1197 let mut r = TlvReader::new(&[0x15, 0x29, 0x07, 0x18]);
1198 let (tag, value) = r.read_value().unwrap();
1199 assert_eq!(tag, Tag::Anonymous);
1200 assert_eq!(
1201 value,
1202 Value::Structure(vec![(Tag::Context(7), Value::Bool(true))])
1203 );
1204 }
1205
1206 #[test]
1207 fn read_value_returns_empty_list() {
1208 let mut r = TlvReader::new(&[0x17, 0x18]);
1209 let (tag, value) = r.read_value().unwrap();
1210 assert_eq!(tag, Tag::Anonymous);
1211 assert_eq!(value, Value::List(Vec::new()));
1212 }
1213
1214 #[test]
1215 fn read_value_handles_nested_structure() {
1216 let mut r = TlvReader::new(&[0x15, 0x35, 0x00, 0x24, 0x00, 0x2A, 0x18, 0x18]);
1217 let (tag, value) = r.read_value().unwrap();
1218 assert_eq!(tag, Tag::Anonymous);
1219 let inner = Value::Structure(vec![(Tag::Context(0), Value::Uint(42))]);
1220 let outer = Value::Structure(vec![(Tag::Context(0), inner)]);
1221 assert_eq!(value, outer);
1222 }
1223
1224 #[test]
1225 fn read_value_errors_on_unclosed_container() {
1226 let mut r = TlvReader::new(&[0x15]);
1227 assert!(matches!(r.read_value(), Err(Error::UnclosedContainer)));
1228 }
1229
1230 #[test]
1231 fn read_value_errors_on_dangling_end_of_container() {
1232 let mut r = TlvReader::new(&[0x18]);
1233 assert!(matches!(
1234 r.read_value(),
1235 Err(Error::UnexpectedEndOfContainer)
1236 ));
1237 }
1238
1239 #[test]
1242 fn read_value_rejects_array_with_context_tagged_child() {
1243 let mut r = TlvReader::new(&[0x16, 0x24, 0x00, 0x2A, 0x18]);
1247 assert!(matches!(r.read_value(), Err(Error::NonAnonymousArrayTag)));
1248 }
1249
1250 #[test]
1251 fn read_value_rejects_array_with_context_tagged_container_child() {
1252 let mut r = TlvReader::new(&[0x16, 0x35, 0x00, 0x18, 0x18]);
1255 assert!(matches!(r.read_value(), Err(Error::NonAnonymousArrayTag)));
1256 }
1257
1258 #[test]
1259 fn read_value_accepts_array_with_anonymous_children() {
1260 let mut r = TlvReader::new(&[0x16, 0x04, 0x01, 0x04, 0x02, 0x18]);
1263 let (tag, value) = r.read_value().unwrap();
1264 assert_eq!(tag, Tag::Anonymous);
1265 assert_eq!(value, Value::Array(vec![Value::Uint(1), Value::Uint(2)]));
1266 }
1267
1268 #[test]
1269 fn read_value_errors_when_element_budget_is_exceeded() {
1270 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1276 let mut r = TlvReader::with_element_budget(&bytes, 3);
1277 assert!(matches!(r.read_value(), Err(Error::ElementBudgetExceeded)));
1278 }
1279
1280 #[test]
1281 fn read_value_fast_path_at_budget_equal_to_input_len() {
1282 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1286 let mut r = TlvReader::with_element_budget(&bytes, bytes.len());
1287 let (_, value) = r.read_value().unwrap();
1288 assert_eq!(
1289 value,
1290 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1291 );
1292 }
1293
1294 #[test]
1295 fn read_value_charged_path_at_budget_one_below_input_len() {
1296 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1299 let mut r = TlvReader::with_element_budget(&bytes, 7);
1300 let (_, value) = r.read_value().unwrap();
1301 assert_eq!(
1302 value,
1303 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1304 );
1305 }
1306
1307 #[test]
1308 fn read_value_succeeds_at_exactly_the_element_budget() {
1309 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1311 let mut r = TlvReader::with_element_budget(&bytes, 4);
1312 let (_, value) = r.read_value().unwrap();
1313 assert_eq!(
1314 value,
1315 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1316 );
1317 }
1318
1319 #[test]
1320 fn read_value_budget_counts_a_single_scalar() {
1321 let mut r = TlvReader::with_element_budget(&[0x04, 0x2A], 0);
1323 assert!(matches!(r.read_value(), Err(Error::ElementBudgetExceeded)));
1324 let mut r = TlvReader::with_element_budget(&[0x04, 0x2A], 1);
1325 assert_eq!(r.read_value().unwrap(), (Tag::Anonymous, Value::Uint(42)));
1326 }
1327
1328 #[test]
1329 fn fixed_width_int_decode_still_works() {
1330 let mut r = TlvReader::new(&[0x05, 0x34, 0x12]);
1335 assert_eq!(
1336 r.next().unwrap().unwrap(),
1337 Element::Scalar {
1338 tag: Tag::Anonymous,
1339 value: Value::Uint(0x1234),
1340 }
1341 );
1342 }
1343
1344 fn struct_with_nested() -> Vec<u8> {
1349 let mut buf = Vec::new();
1350 let mut w = crate::writer::TlvWriter::new(&mut buf);
1351 w.start_structure(Tag::Anonymous).unwrap();
1352 w.put_uint(Tag::Context(0), 7).unwrap();
1353 w.start_structure(Tag::Context(9)).unwrap();
1354 w.put_uint(Tag::Context(0), 1).unwrap();
1355 w.end_container().unwrap();
1356 w.put_uint(Tag::Context(1), 42).unwrap();
1357 w.end_container().unwrap();
1358 buf
1359 }
1360
1361 #[test]
1362 fn read_utf8_truncates_at_is1_separator() {
1363 fn decode_str(s: &str) -> String {
1367 let mut buf = Vec::new();
1368 let mut w = crate::writer::TlvWriter::new(&mut buf);
1369 w.put_utf8(Tag::Anonymous, s).unwrap();
1370 match TlvReader::new(&buf).next().unwrap().unwrap() {
1371 Element::Scalar {
1372 value: Value::Utf8(t),
1373 ..
1374 } => t,
1375 other => panic!("expected Utf8 scalar, got {other:?}"),
1376 }
1377 }
1378 assert_eq!(
1381 decode_str("This is a test case #1\u{1F}suffix"),
1382 "This is a test case #1"
1383 );
1384 assert_eq!(decode_str("\u{1F} abc \u{1F} def"), "");
1385 assert_eq!(decode_str("Kitchen"), "Kitchen");
1387 assert_eq!(decode_str("Kitchen\u{1F}0409"), "Kitchen");
1388 }
1389
1390 #[test]
1391 fn skip_container_drains_nested_struct_and_positions_after() {
1392 let buf = struct_with_nested();
1393 let mut r = TlvReader::new(&buf);
1394 assert!(matches!(
1396 r.next().unwrap(),
1397 Some(Element::ContainerStart {
1398 kind: ContainerKind::Structure,
1399 ..
1400 })
1401 ));
1402 assert!(matches!(r.next().unwrap(), Some(Element::Scalar { .. })));
1404 assert!(matches!(
1406 r.next().unwrap(),
1407 Some(Element::ContainerStart {
1408 kind: ContainerKind::Structure,
1409 ..
1410 })
1411 ));
1412 r.skip_container().unwrap();
1413 match r.next().unwrap() {
1415 Some(Element::Scalar {
1416 tag: Tag::Context(1),
1417 value: Value::Uint(v),
1418 }) => {
1419 assert_eq!(v, 42);
1420 }
1421 other => panic!("expected ctx1=42 after skip, got {other:?}"),
1422 }
1423 assert!(matches!(r.next().unwrap(), Some(Element::ContainerEnd)));
1425 assert!(r.next().unwrap().is_none());
1426 }
1427
1428 #[test]
1429 fn skip_container_handles_array_and_list_and_empty() {
1430 for kind_byte in ["array", "list", "empty"] {
1431 let mut buf = Vec::new();
1432 let mut w = crate::writer::TlvWriter::new(&mut buf);
1433 w.start_structure(Tag::Anonymous).unwrap();
1434 match kind_byte {
1435 "array" => {
1436 w.start_array(Tag::Context(0)).unwrap();
1437 w.put_uint(Tag::Anonymous, 1).unwrap();
1438 w.put_uint(Tag::Anonymous, 2).unwrap();
1439 w.end_container().unwrap();
1440 }
1441 "list" => {
1442 w.start_list(Tag::Context(0)).unwrap();
1443 w.put_uint(Tag::Context(5), 9).unwrap();
1444 w.end_container().unwrap();
1445 }
1446 _ => {
1447 w.start_structure(Tag::Context(0)).unwrap();
1448 w.end_container().unwrap();
1449 }
1450 }
1451 w.put_uint(Tag::Context(1), 99).unwrap();
1452 w.end_container().unwrap();
1453
1454 let mut r = TlvReader::new(&buf);
1455 assert!(matches!(
1456 r.next().unwrap(),
1457 Some(Element::ContainerStart { .. })
1458 ));
1459 assert!(matches!(
1460 r.next().unwrap(),
1461 Some(Element::ContainerStart { .. })
1462 ));
1463 r.skip_container().unwrap();
1464 match r.next().unwrap() {
1465 Some(Element::Scalar {
1466 tag: Tag::Context(1),
1467 value: Value::Uint(v),
1468 }) => {
1469 assert_eq!(v, 99, "kind {kind_byte}");
1470 }
1471 other => panic!("kind {kind_byte}: expected ctx1=99, got {other:?}"),
1472 }
1473 }
1474 }
1475
1476 #[test]
1477 fn skip_container_unclosed_is_error() {
1478 let mut buf = Vec::new();
1480 {
1481 let mut w = crate::writer::TlvWriter::new(&mut buf);
1482 w.start_structure(Tag::Anonymous).unwrap();
1483 w.start_structure(Tag::Context(0)).unwrap();
1484 w.put_uint(Tag::Anonymous, 1).unwrap();
1485 }
1487 let mut r = TlvReader::new(&buf);
1488 assert!(matches!(
1489 r.next().unwrap(),
1490 Some(Element::ContainerStart { .. })
1491 ));
1492 assert!(matches!(
1493 r.next().unwrap(),
1494 Some(Element::ContainerStart { .. })
1495 ));
1496 assert!(matches!(r.skip_container(), Err(Error::UnclosedContainer)));
1497 }
1498}