1use crate::error::{Error, Result};
13use crate::tag::Tag;
14use crate::value::{Value, ValueRef};
15use crate::{element_type as et, tag_control as tc};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20#[non_exhaustive]
21pub enum ContainerKind {
22 Structure,
24 Array,
26 List,
28}
29
30#[derive(Debug, Clone, PartialEq)]
32#[non_exhaustive]
33pub enum Element {
34 Scalar {
36 tag: Tag,
38 value: Value,
40 },
41
42 ContainerStart {
46 tag: Tag,
48 kind: ContainerKind,
50 },
51
52 ContainerEnd,
54}
55
56#[derive(Debug, Clone, Copy, PartialEq)]
61#[non_exhaustive]
62pub enum ElementRef<'a> {
63 Scalar {
65 tag: Tag,
67 value: ValueRef<'a>,
69 },
70 ContainerStart {
72 tag: Tag,
74 kind: ContainerKind,
76 },
77 ContainerEnd,
79}
80
81impl From<ElementRef<'_>> for Element {
82 #[inline]
83 fn from(e: ElementRef<'_>) -> Self {
84 match e {
85 ElementRef::Scalar { tag, value } => Element::Scalar {
86 tag,
87 value: Value::from(value),
88 },
89 ElementRef::ContainerStart { tag, kind } => Element::ContainerStart { tag, kind },
90 ElementRef::ContainerEnd => Element::ContainerEnd,
91 }
92 }
93}
94
95pub const MAX_DEPTH: usize = 32;
99
100pub const DEFAULT_ELEMENT_BUDGET: usize = 1 << 20;
116
117#[derive(Debug, Clone, Copy, PartialEq, Eq)]
135pub struct ElementSpan {
136 start: usize,
137 body_start: usize,
138 end: usize,
139}
140
141impl ElementSpan {
142 #[must_use]
144 pub fn full(&self) -> core::ops::Range<usize> {
145 self.start..self.end
146 }
147
148 #[must_use]
153 pub fn body(&self) -> core::ops::Range<usize> {
154 self.body_start..self.end
155 }
156}
157
158pub struct TlvReader<'a> {
160 bytes: &'a [u8],
161 pos: usize,
162 depth: usize,
163 element_budget: usize,
172 last_span: Option<ElementSpan>,
176 last_was_container_start: bool,
183}
184
185impl<'a> TlvReader<'a> {
186 #[inline]
189 pub fn new(bytes: &'a [u8]) -> Self {
190 Self {
191 bytes,
192 pos: 0,
193 depth: 0,
194 element_budget: DEFAULT_ELEMENT_BUDGET,
195 last_span: None,
196 last_was_container_start: false,
197 }
198 }
199
200 #[inline]
208 pub fn with_element_budget(bytes: &'a [u8], budget: usize) -> Self {
209 Self {
210 bytes,
211 pos: 0,
212 depth: 0,
213 element_budget: budget,
214 last_span: None,
215 last_was_container_start: false,
216 }
217 }
218
219 #[inline]
221 pub fn is_empty(&self) -> bool {
222 self.pos >= self.bytes.len()
223 }
224
225 #[allow(clippy::should_implement_trait)] #[inline]
253 pub fn next(&mut self) -> Result<Option<Element>> {
254 Ok(self.next_ref()?.map(Element::from))
255 }
256
257 #[inline]
274 pub fn next_ref(&mut self) -> Result<Option<ElementRef<'a>>> {
275 if self.is_empty() {
276 return Ok(None);
277 }
278 let start = self.pos;
279 let control = self.next_byte()?;
280 let elem_type = control & et::ELEMENT_TYPE_MASK;
281
282 if elem_type == et::END_OF_CONTAINER {
284 if control & tc::TAG_CONTROL_MASK != tc::ANONYMOUS {
285 return Err(Error::InvalidTagControl(control & tc::TAG_CONTROL_MASK));
286 }
287 if self.depth == 0 {
288 return Err(Error::UnexpectedEndOfContainer);
289 }
290 self.depth -= 1;
291 self.last_span = Some(ElementSpan {
292 start,
293 body_start: self.pos,
294 end: self.pos,
295 });
296 self.last_was_container_start = false;
297 return Ok(Some(ElementRef::ContainerEnd));
298 }
299
300 let tag = self.read_tag(control)?;
301 let body_start = self.pos;
302
303 let kind = match elem_type {
305 et::STRUCTURE => Some(ContainerKind::Structure),
306 et::ARRAY => Some(ContainerKind::Array),
307 et::LIST => Some(ContainerKind::List),
308 _ => None,
309 };
310 if let Some(kind) = kind {
311 if self.depth >= MAX_DEPTH {
312 return Err(Error::ContainerTooDeep);
313 }
314 self.depth += 1;
315 self.last_span = Some(ElementSpan {
316 start,
317 body_start,
318 end: self.pos,
319 });
320 self.last_was_container_start = true;
321 return Ok(Some(ElementRef::ContainerStart { tag, kind }));
322 }
323
324 let value = self.read_value_body_ref(elem_type)?;
325 self.last_span = Some(ElementSpan {
326 start,
327 body_start,
328 end: self.pos,
329 });
330 self.last_was_container_start = false;
331 Ok(Some(ElementRef::Scalar { tag, value }))
332 }
333
334 pub fn skip_container(&mut self) -> Result<()> {
393 self.skip_container_body()?;
394 if let Some(h) = self.last_span {
395 self.last_span = Some(ElementSpan {
396 start: h.start,
397 body_start: h.body_start,
398 end: self.pos,
399 });
400 }
401 self.last_was_container_start = false;
404 Ok(())
405 }
406
407 pub fn skip_container_span(&mut self) -> Result<ElementSpan> {
429 if !self.last_was_container_start {
430 return Err(Error::UnexpectedEndOfContainer);
431 }
432 let header = self.last_span.ok_or(Error::UnexpectedEndOfContainer)?;
433 self.skip_container_body()?;
434 let span = ElementSpan {
435 start: header.start,
436 body_start: header.body_start,
437 end: self.pos,
438 };
439 self.last_span = Some(span);
440 self.last_was_container_start = false;
441 Ok(span)
442 }
443
444 #[inline]
455 #[must_use]
456 pub fn element_span(&self) -> Option<ElementSpan> {
457 self.last_span
458 }
459
460 #[inline]
464 #[must_use]
465 pub fn span_bytes(&self, range: core::ops::Range<usize>) -> &'a [u8] {
466 self.bytes.get(range).unwrap_or(&[])
467 }
468
469 fn skip_container_body(&mut self) -> Result<()> {
475 let mut depth = 1usize;
476 while depth > 0 {
477 if self.is_empty() {
478 return Err(Error::UnclosedContainer);
479 }
480 let control = self.next_byte()?;
481 let elem_type = control & et::ELEMENT_TYPE_MASK;
482 if elem_type == et::END_OF_CONTAINER {
483 if control & tc::TAG_CONTROL_MASK != tc::ANONYMOUS {
484 return Err(Error::InvalidTagControl(control & tc::TAG_CONTROL_MASK));
485 }
486 if depth == 1 && self.depth == 0 {
487 return Err(Error::UnexpectedEndOfContainer);
490 }
491 depth -= 1;
492 continue;
493 }
494 let _ = self.read_tag(control)?;
497 match elem_type {
498 et::STRUCTURE | et::ARRAY | et::LIST => {
499 if self.depth + depth > MAX_DEPTH {
505 return Err(Error::ContainerTooDeep);
506 }
507 depth += 1;
508 }
509 _ => self.skip_value_body(elem_type)?,
510 }
511 }
512 self.depth -= 1;
518 Ok(())
519 }
520
521 fn skip_value_body(&mut self, elem_type: u8) -> Result<()> {
525 let n = match elem_type {
526 et::BOOL_FALSE | et::BOOL_TRUE | et::NULL => 0,
527 et::UINT8 | et::INT8 => 1,
528 et::UINT16 | et::INT16 => 2,
529 et::UINT32 | et::INT32 | et::FLOAT32 => 4,
530 et::UINT64 | et::INT64 | et::FLOAT64 => 8,
531 et::UTF8_LEN8
532 | et::UTF8_LEN16
533 | et::UTF8_LEN32
534 | et::UTF8_LEN64
535 | et::BYTES_LEN8
536 | et::BYTES_LEN16
537 | et::BYTES_LEN32
538 | et::BYTES_LEN64 => {
539 let len = self.read_payload_len(elem_type)?;
540 let _ = self.next_bytes(len)?;
541 return Ok(());
542 }
543 other => return Err(Error::InvalidElementType(other)),
544 };
545 let _ = self.next_bytes(n)?;
546 Ok(())
547 }
548
549 pub fn read_value(&mut self) -> Result<(Tag, Value)> {
566 let remaining_input = self.bytes.len().saturating_sub(self.pos);
584 if remaining_input <= self.element_budget {
585 self.read_value_inner::<false>()
586 } else {
587 self.read_value_inner::<true>()
588 }
589 }
590
591 fn read_value_inner<const CHARGE: bool>(&mut self) -> Result<(Tag, Value)> {
603 match self.next_ref()? {
604 Some(ElementRef::Scalar { tag, value }) => {
605 if CHARGE {
606 self.charge_element()?;
607 }
608 Ok((tag, Value::from(value)))
609 }
610 Some(ElementRef::ContainerStart { tag, kind }) => {
611 if CHARGE {
612 self.charge_element()?;
613 }
614 let value = self.read_container_body::<CHARGE>(kind)?;
615 Ok((tag, value))
616 }
617 Some(ElementRef::ContainerEnd) => Err(Error::UnexpectedEndOfContainer),
618 None => Err(Error::UnexpectedEof),
619 }
620 }
621
622 fn charge_element(&mut self) -> Result<()> {
628 self.element_budget = self
629 .element_budget
630 .checked_sub(1)
631 .ok_or(Error::ElementBudgetExceeded)?;
632 Ok(())
633 }
634
635 fn read_container_body<const CHARGE: bool>(&mut self, kind: ContainerKind) -> Result<Value> {
663 match kind {
672 ContainerKind::Array => {
673 let mut elements: Vec<Value> = Vec::new();
674 let mut budget = self.element_budget;
675 loop {
676 match self.next_ref()? {
677 None => return Err(Error::UnclosedContainer),
678 Some(ElementRef::ContainerEnd) => break,
679 Some(ElementRef::Scalar { tag, value }) => {
680 if tag != Tag::Anonymous {
683 return Err(Error::NonAnonymousArrayTag);
684 }
685 if CHARGE {
686 budget =
687 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
688 }
689 elements.push(Value::from(value));
690 }
691 Some(ElementRef::ContainerStart {
692 tag,
693 kind: inner_kind,
694 }) => {
695 if tag != Tag::Anonymous {
696 return Err(Error::NonAnonymousArrayTag);
697 }
698 if CHARGE {
699 budget =
700 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
701 self.element_budget = budget;
702 }
703 elements.push(self.read_container_body::<CHARGE>(inner_kind)?);
704 if CHARGE {
705 budget = self.element_budget;
706 }
707 }
708 }
709 }
710 if CHARGE {
711 self.element_budget = budget;
712 }
713 Ok(Value::Array(elements))
714 }
715 ContainerKind::Structure | ContainerKind::List => {
716 let mut members: Vec<(Tag, Value)> = Vec::new();
717 let mut budget = self.element_budget;
718 loop {
719 match self.next_ref()? {
720 None => return Err(Error::UnclosedContainer),
721 Some(ElementRef::ContainerEnd) => break,
722 Some(ElementRef::Scalar { tag, value }) => {
723 if CHARGE {
724 budget =
725 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
726 }
727 members.push((tag, Value::from(value)));
728 }
729 Some(ElementRef::ContainerStart {
730 tag,
731 kind: inner_kind,
732 }) => {
733 if CHARGE {
734 budget =
735 budget.checked_sub(1).ok_or(Error::ElementBudgetExceeded)?;
736 self.element_budget = budget;
737 }
738 let inner = self.read_container_body::<CHARGE>(inner_kind)?;
739 members.push((tag, inner));
740 if CHARGE {
741 budget = self.element_budget;
742 }
743 }
744 }
745 }
746 if CHARGE {
747 self.element_budget = budget;
748 }
749 Ok(match kind {
750 ContainerKind::List => Value::List(members),
751 _ => Value::Structure(members),
753 })
754 }
755 }
756 }
757
758 #[inline]
759 fn next_byte(&mut self) -> Result<u8> {
760 let b = *self.bytes.get(self.pos).ok_or(Error::UnexpectedEof)?;
761 self.pos += 1;
762 Ok(b)
763 }
764
765 #[inline]
766 fn next_bytes(&mut self, n: usize) -> Result<&'a [u8]> {
767 let end = self.pos.checked_add(n).ok_or(Error::LengthOverflow)?;
768 let slice = self.bytes.get(self.pos..end).ok_or(Error::UnexpectedEof)?;
769 self.pos = end;
770 Ok(slice)
771 }
772
773 #[inline]
782 fn read_tag(&mut self, control: u8) -> Result<Tag> {
783 match control & tc::TAG_CONTROL_MASK {
784 tc::ANONYMOUS => Ok(Tag::Anonymous),
785 tc::CONTEXT => {
786 let n = self.next_byte()?;
787 Ok(Tag::Context(n))
788 }
789 tc::COMMON_PROFILE_2 => {
790 let raw: [u8; 2] = self
791 .next_bytes(2)?
792 .try_into()
793 .map_err(|_| Error::InternalSliceConversion)?;
794 Ok(Tag::CommonProfile(u32::from(u16::from_le_bytes(raw))))
795 }
796 tc::COMMON_PROFILE_4 => {
797 let raw: [u8; 4] = self
798 .next_bytes(4)?
799 .try_into()
800 .map_err(|_| Error::InternalSliceConversion)?;
801 Ok(Tag::CommonProfile(u32::from_le_bytes(raw)))
802 }
803 tc::IMPLICIT_PROFILE_2 => {
804 let raw: [u8; 2] = self
805 .next_bytes(2)?
806 .try_into()
807 .map_err(|_| Error::InternalSliceConversion)?;
808 Ok(Tag::ImplicitProfile(u32::from(u16::from_le_bytes(raw))))
809 }
810 tc::IMPLICIT_PROFILE_4 => {
811 let raw: [u8; 4] = self
812 .next_bytes(4)?
813 .try_into()
814 .map_err(|_| Error::InternalSliceConversion)?;
815 Ok(Tag::ImplicitProfile(u32::from_le_bytes(raw)))
816 }
817 tc::FULLY_QUALIFIED_6 => {
818 let vendor = self.read_u16_le()?;
819 let profile = self.read_u16_le()?;
820 let tag = u32::from(self.read_u16_le()?);
821 Ok(Tag::FullyQualified {
822 vendor,
823 profile,
824 tag,
825 })
826 }
827 tc::FULLY_QUALIFIED_8 => {
828 let vendor = self.read_u16_le()?;
829 let profile = self.read_u16_le()?;
830 let tag = self.read_u32_le()?;
831 Ok(Tag::FullyQualified {
832 vendor,
833 profile,
834 tag,
835 })
836 }
837 other => Err(Error::InvalidTagControl(other)),
841 }
842 }
843
844 #[inline]
845 fn read_u16_le(&mut self) -> Result<u16> {
846 let raw: [u8; 2] = self
847 .next_bytes(2)?
848 .try_into()
849 .map_err(|_| Error::InternalSliceConversion)?;
850 Ok(u16::from_le_bytes(raw))
851 }
852
853 #[inline]
854 fn read_u32_le(&mut self) -> Result<u32> {
855 let raw: [u8; 4] = self
856 .next_bytes(4)?
857 .try_into()
858 .map_err(|_| Error::InternalSliceConversion)?;
859 Ok(u32::from_le_bytes(raw))
860 }
861
862 #[allow(clippy::cast_possible_wrap)] #[inline]
864 fn read_value_body_ref(&mut self, elem_type: u8) -> Result<ValueRef<'a>> {
865 match elem_type {
866 et::BOOL_FALSE => Ok(ValueRef::Bool(false)),
867 et::BOOL_TRUE => Ok(ValueRef::Bool(true)),
868 et::NULL => Ok(ValueRef::Null),
869 et::UINT8 => Ok(ValueRef::Uint(u64::from(self.next_byte()?))),
870 et::UINT16 => {
871 let raw: [u8; 2] = self
872 .next_bytes(2)?
873 .try_into()
874 .map_err(|_| Error::InternalSliceConversion)?;
875 Ok(ValueRef::Uint(u64::from(u16::from_le_bytes(raw))))
876 }
877 et::UINT32 => {
878 let raw: [u8; 4] = self
879 .next_bytes(4)?
880 .try_into()
881 .map_err(|_| Error::InternalSliceConversion)?;
882 Ok(ValueRef::Uint(u64::from(u32::from_le_bytes(raw))))
883 }
884 et::UINT64 => {
885 let raw: [u8; 8] = self
886 .next_bytes(8)?
887 .try_into()
888 .map_err(|_| Error::InternalSliceConversion)?;
889 Ok(ValueRef::Uint(u64::from_le_bytes(raw)))
890 }
891 et::INT8 => {
892 let b = self.next_byte()?;
893 Ok(ValueRef::Int(i64::from(b as i8)))
894 }
895 et::INT16 => {
896 let raw: [u8; 2] = self
897 .next_bytes(2)?
898 .try_into()
899 .map_err(|_| Error::InternalSliceConversion)?;
900 Ok(ValueRef::Int(i64::from(i16::from_le_bytes(raw))))
901 }
902 et::INT32 => {
903 let raw: [u8; 4] = self
904 .next_bytes(4)?
905 .try_into()
906 .map_err(|_| Error::InternalSliceConversion)?;
907 Ok(ValueRef::Int(i64::from(i32::from_le_bytes(raw))))
908 }
909 et::INT64 => {
910 let raw: [u8; 8] = self
911 .next_bytes(8)?
912 .try_into()
913 .map_err(|_| Error::InternalSliceConversion)?;
914 Ok(ValueRef::Int(i64::from_le_bytes(raw)))
915 }
916 et::FLOAT32 => {
917 let raw: [u8; 4] = self
918 .next_bytes(4)?
919 .try_into()
920 .map_err(|_| Error::InternalSliceConversion)?;
921 Ok(ValueRef::Float(f32::from_le_bytes(raw)))
922 }
923 et::FLOAT64 => {
924 let raw: [u8; 8] = self
925 .next_bytes(8)?
926 .try_into()
927 .map_err(|_| Error::InternalSliceConversion)?;
928 Ok(ValueRef::Double(f64::from_le_bytes(raw)))
929 }
930 et::UTF8_LEN8 | et::UTF8_LEN16 | et::UTF8_LEN32 | et::UTF8_LEN64 => {
931 let len = self.read_payload_len(elem_type)?;
932 self.read_utf8_ref(len)
933 }
934 et::BYTES_LEN8 | et::BYTES_LEN16 | et::BYTES_LEN32 | et::BYTES_LEN64 => {
935 let len = self.read_payload_len(elem_type)?;
936 self.read_bytes_ref(len)
937 }
938 other => Err(Error::InvalidElementType(other)),
939 }
940 }
941
942 #[inline]
946 fn read_payload_len(&mut self, elem_type: u8) -> Result<usize> {
947 match elem_type & 0b11 {
948 0b00 => Ok(usize::from(self.next_byte()?)),
949 0b01 => Ok(usize::from(self.read_u16_le()?)),
950 0b10 => usize::try_from(self.read_u32_le()?).map_err(|_| Error::LengthOverflow),
951 _ => usize::try_from(self.read_u64_le()?).map_err(|_| Error::LengthOverflow),
952 }
953 }
954
955 #[inline]
956 fn read_u64_le(&mut self) -> Result<u64> {
957 let raw: [u8; 8] = self
958 .next_bytes(8)?
959 .try_into()
960 .map_err(|_| Error::InternalSliceConversion)?;
961 Ok(u64::from_le_bytes(raw))
962 }
963
964 #[inline]
965 fn read_utf8_ref(&mut self, len: usize) -> Result<ValueRef<'a>> {
966 let bytes = self.next_bytes(len)?;
967 let s = core::str::from_utf8(bytes)?;
977 let text = match s.find('\u{1F}') {
980 Some(i) => &s[..i],
981 None => s,
982 };
983 Ok(ValueRef::Utf8(text))
984 }
985
986 #[inline]
987 fn read_bytes_ref(&mut self, len: usize) -> Result<ValueRef<'a>> {
988 Ok(ValueRef::Bytes(self.next_bytes(len)?))
989 }
990}
991
992#[cfg(test)]
993#[allow(clippy::unwrap_used)] mod tests {
995 use super::*;
996
997 #[test]
998 fn next_returns_none_on_empty_input() {
999 let mut r = TlvReader::new(&[]);
1000 assert!(r.is_empty());
1001 assert_eq!(r.next().unwrap(), None);
1002 }
1003
1004 #[test]
1005 fn next_decodes_bool_true_anonymous_vector_0001() {
1006 let mut r = TlvReader::new(&[0x09]);
1007 let el = r.next().unwrap().unwrap();
1008 assert_eq!(
1009 el,
1010 Element::Scalar {
1011 tag: Tag::Anonymous,
1012 value: Value::Bool(true)
1013 }
1014 );
1015 assert!(r.is_empty());
1016 }
1017
1018 #[test]
1019 fn next_decodes_bool_false() {
1020 let mut r = TlvReader::new(&[0x08]);
1021 let el = r.next().unwrap().unwrap();
1022 assert_eq!(
1023 el,
1024 Element::Scalar {
1025 tag: Tag::Anonymous,
1026 value: Value::Bool(false)
1027 }
1028 );
1029 }
1030
1031 #[test]
1032 fn next_decodes_null_vector_implied() {
1033 let mut r = TlvReader::new(&[0x14]);
1034 let el = r.next().unwrap().unwrap();
1035 assert_eq!(
1036 el,
1037 Element::Scalar {
1038 tag: Tag::Anonymous,
1039 value: Value::Null
1040 }
1041 );
1042 }
1043
1044 #[test]
1045 fn next_decodes_uint8_42_vector_0003() {
1046 let mut r = TlvReader::new(&[0x04, 0x2A]);
1047 let el = r.next().unwrap().unwrap();
1048 assert_eq!(
1049 el,
1050 Element::Scalar {
1051 tag: Tag::Anonymous,
1052 value: Value::Uint(42)
1053 }
1054 );
1055 }
1056
1057 #[test]
1058 fn next_decodes_uint16_0x1234() {
1059 let mut r = TlvReader::new(&[0x05, 0x34, 0x12]);
1060 let el = r.next().unwrap().unwrap();
1061 assert_eq!(
1062 el,
1063 Element::Scalar {
1064 tag: Tag::Anonymous,
1065 value: Value::Uint(0x1234)
1066 }
1067 );
1068 }
1069
1070 #[test]
1071 fn next_decodes_uint32_0xcafebabe() {
1072 let mut r = TlvReader::new(&[0x06, 0xBE, 0xBA, 0xFE, 0xCA]);
1073 let el = r.next().unwrap().unwrap();
1074 assert_eq!(
1075 el,
1076 Element::Scalar {
1077 tag: Tag::Anonymous,
1078 value: Value::Uint(0xCAFE_BABE)
1079 }
1080 );
1081 }
1082
1083 #[test]
1084 fn next_decodes_uint64_big() {
1085 let bytes = [0x07, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01];
1086 let mut r = TlvReader::new(&bytes);
1087 let el = r.next().unwrap().unwrap();
1088 assert_eq!(
1089 el,
1090 Element::Scalar {
1091 tag: Tag::Anonymous,
1092 value: Value::Uint(0x0123_4567_89AB_CDEF),
1093 }
1094 );
1095 }
1096
1097 #[test]
1098 fn next_decodes_int8_neg17_vector_0008() {
1099 let mut r = TlvReader::new(&[0x00, 0xEF]);
1100 let el = r.next().unwrap().unwrap();
1101 assert_eq!(
1102 el,
1103 Element::Scalar {
1104 tag: Tag::Anonymous,
1105 value: Value::Int(-17)
1106 }
1107 );
1108 }
1109
1110 #[test]
1111 fn next_decodes_int16_neg129() {
1112 let mut r = TlvReader::new(&[0x01, 0x7F, 0xFF]);
1113 let el = r.next().unwrap().unwrap();
1114 assert_eq!(
1115 el,
1116 Element::Scalar {
1117 tag: Tag::Anonymous,
1118 value: Value::Int(-129)
1119 }
1120 );
1121 }
1122
1123 #[test]
1124 fn next_decodes_int32_min() {
1125 let mut r = TlvReader::new(&[0x02, 0x00, 0x00, 0x00, 0x80]);
1126 let el = r.next().unwrap().unwrap();
1127 assert_eq!(
1128 el,
1129 Element::Scalar {
1130 tag: Tag::Anonymous,
1131 value: Value::Int(i64::from(i32::MIN))
1132 }
1133 );
1134 }
1135
1136 #[test]
1137 fn next_decodes_int64_min() {
1138 let bytes = [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80];
1139 let mut r = TlvReader::new(&bytes);
1140 let el = r.next().unwrap().unwrap();
1141 assert_eq!(
1142 el,
1143 Element::Scalar {
1144 tag: Tag::Anonymous,
1145 value: Value::Int(i64::MIN)
1146 }
1147 );
1148 }
1149
1150 #[test]
1151 fn next_decodes_float32_zero_vector_0013() {
1152 let mut r = TlvReader::new(&[0x0A, 0x00, 0x00, 0x00, 0x00]);
1153 let el = r.next().unwrap().unwrap();
1154 assert_eq!(
1155 el,
1156 Element::Scalar {
1157 tag: Tag::Anonymous,
1158 value: Value::Float(0.0)
1159 }
1160 );
1161 }
1162
1163 #[test]
1164 fn next_decodes_float64_zero_vector_0014() {
1165 let bytes = [0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
1166 let mut r = TlvReader::new(&bytes);
1167 let el = r.next().unwrap().unwrap();
1168 assert_eq!(
1169 el,
1170 Element::Scalar {
1171 tag: Tag::Anonymous,
1172 value: Value::Double(0.0)
1173 }
1174 );
1175 }
1176
1177 #[test]
1178 fn next_decodes_uint_with_context_tag_5() {
1179 let mut r = TlvReader::new(&[0x24, 0x05, 0x2A]);
1180 let el = r.next().unwrap().unwrap();
1181 assert_eq!(
1182 el,
1183 Element::Scalar {
1184 tag: Tag::Context(5),
1185 value: Value::Uint(42)
1186 }
1187 );
1188 }
1189
1190 #[test]
1191 fn next_errors_on_unexpected_eof_in_payload() {
1192 let mut r = TlvReader::new(&[0x05]); assert!(matches!(r.next(), Err(Error::UnexpectedEof)));
1194 }
1195
1196 #[test]
1197 fn next_decodes_uint_with_common_profile_2_byte_tag() {
1198 let mut r = TlvReader::new(&[0x44, 0x07, 0x00, 0x2A]);
1199 let el = r.next().unwrap().unwrap();
1200 assert_eq!(
1201 el,
1202 Element::Scalar {
1203 tag: Tag::CommonProfile(7),
1204 value: Value::Uint(42)
1205 }
1206 );
1207 }
1208
1209 #[test]
1210 fn next_decodes_uint_with_common_profile_4_byte_tag() {
1211 let mut r = TlvReader::new(&[0x64, 0x45, 0x23, 0x01, 0x00, 0x2A]);
1212 let el = r.next().unwrap().unwrap();
1213 assert_eq!(
1214 el,
1215 Element::Scalar {
1216 tag: Tag::CommonProfile(0x0001_2345),
1217 value: Value::Uint(42)
1218 }
1219 );
1220 }
1221
1222 #[test]
1223 fn next_decodes_uint_with_implicit_profile_2_byte_tag() {
1224 let mut r = TlvReader::new(&[0x84, 0x07, 0x00, 0x2A]);
1225 let el = r.next().unwrap().unwrap();
1226 assert_eq!(
1227 el,
1228 Element::Scalar {
1229 tag: Tag::ImplicitProfile(7),
1230 value: Value::Uint(42)
1231 }
1232 );
1233 }
1234
1235 #[test]
1236 fn next_decodes_uint_with_implicit_profile_4_byte_tag() {
1237 let mut r = TlvReader::new(&[0xA4, 0x45, 0x23, 0x01, 0x00, 0x2A]);
1238 let el = r.next().unwrap().unwrap();
1239 assert_eq!(
1240 el,
1241 Element::Scalar {
1242 tag: Tag::ImplicitProfile(0x0001_2345),
1243 value: Value::Uint(42)
1244 }
1245 );
1246 }
1247
1248 #[test]
1249 fn next_decodes_uint_with_fully_qualified_6_byte() {
1250 let mut r = TlvReader::new(&[0xC4, 0xF1, 0xFF, 0x06, 0x00, 0x05, 0x00, 0x2A]);
1251 let el = r.next().unwrap().unwrap();
1252 assert_eq!(
1253 el,
1254 Element::Scalar {
1255 tag: Tag::FullyQualified {
1256 vendor: 0xFFF1,
1257 profile: 0x0006,
1258 tag: 5
1259 },
1260 value: Value::Uint(42),
1261 }
1262 );
1263 }
1264
1265 #[test]
1266 fn next_decodes_uint_with_fully_qualified_8_byte() {
1267 let mut r = TlvReader::new(&[0xE4, 0xF1, 0xFF, 0x06, 0x00, 0x45, 0x23, 0x01, 0x00, 0x2A]);
1268 let el = r.next().unwrap().unwrap();
1269 assert_eq!(
1270 el,
1271 Element::Scalar {
1272 tag: Tag::FullyQualified {
1273 vendor: 0xFFF1,
1274 profile: 0x0006,
1275 tag: 0x0001_2345
1276 },
1277 value: Value::Uint(42),
1278 }
1279 );
1280 }
1281
1282 #[test]
1283 fn read_value_returns_tag_and_value_for_scalar() {
1284 let mut r = TlvReader::new(&[0x24, 0x05, 0x2A]);
1285 let (tag, value) = r.read_value().unwrap();
1286 assert_eq!(tag, Tag::Context(5));
1287 assert_eq!(value, Value::Uint(42));
1288 }
1289
1290 #[test]
1291 fn read_value_errors_on_empty_input() {
1292 let mut r = TlvReader::new(&[]);
1293 assert!(matches!(r.read_value(), Err(Error::UnexpectedEof)));
1294 }
1295
1296 #[test]
1297 fn next_decodes_utf8_hello_vector_0015() {
1298 let bytes = [0x0C, 0x06, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21];
1299 let mut r = TlvReader::new(&bytes);
1300 let el = r.next().unwrap().unwrap();
1301 assert_eq!(
1302 el,
1303 Element::Scalar {
1304 tag: Tag::Anonymous,
1305 value: Value::Utf8(String::from("Hello!")),
1306 }
1307 );
1308 }
1309
1310 #[test]
1311 fn next_decodes_utf8_empty_vector_0016() {
1312 let bytes = [0x0C, 0x00];
1313 let mut r = TlvReader::new(&bytes);
1314 let el = r.next().unwrap().unwrap();
1315 assert_eq!(
1316 el,
1317 Element::Scalar {
1318 tag: Tag::Anonymous,
1319 value: Value::Utf8(String::new()),
1320 }
1321 );
1322 }
1323
1324 #[test]
1325 fn next_decodes_utf8_len16_path() {
1326 let mut bytes = vec![0x0D, 0x00, 0x01]; bytes.extend(std::iter::repeat_n(b'a', 256));
1328 let mut r = TlvReader::new(&bytes);
1329 let el = r.next().unwrap().unwrap();
1330 let Element::Scalar {
1331 value: Value::Utf8(s),
1332 ..
1333 } = el
1334 else {
1335 panic!("wrong variant")
1336 };
1337 assert_eq!(s.len(), 256);
1338 assert!(s.bytes().all(|b| b == b'a'));
1339 }
1340
1341 #[test]
1342 fn next_decodes_bytes_five_bytes_vector_0017() {
1343 let bytes = [0x10, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04];
1344 let mut r = TlvReader::new(&bytes);
1345 let el = r.next().unwrap().unwrap();
1346 assert_eq!(
1347 el,
1348 Element::Scalar {
1349 tag: Tag::Anonymous,
1350 value: Value::Bytes(vec![0x00, 0x01, 0x02, 0x03, 0x04]),
1351 }
1352 );
1353 }
1354
1355 #[test]
1356 fn next_decodes_bytes_empty_vector_0018() {
1357 let bytes = [0x10, 0x00];
1358 let mut r = TlvReader::new(&bytes);
1359 let el = r.next().unwrap().unwrap();
1360 assert_eq!(
1361 el,
1362 Element::Scalar {
1363 tag: Tag::Anonymous,
1364 value: Value::Bytes(Vec::new()),
1365 }
1366 );
1367 }
1368
1369 #[test]
1370 fn next_errors_on_invalid_utf8() {
1371 let bytes = [0x0C, 0x01, 0xFF];
1372 let mut r = TlvReader::new(&bytes);
1373 assert!(matches!(r.next(), Err(Error::InvalidUtf8(_))));
1374 }
1375
1376 #[test]
1377 fn next_errors_on_truncated_utf8_payload() {
1378 let bytes = [0x0C, 0x05, b'H', b'i']; let mut r = TlvReader::new(&bytes);
1380 assert!(matches!(r.next(), Err(Error::UnexpectedEof)));
1381 }
1382
1383 #[test]
1386 fn next_decodes_structure_start_and_end_vector_0019() {
1387 let mut r = TlvReader::new(&[0x15, 0x18]);
1388 let el = r.next().unwrap().unwrap();
1389 assert_eq!(
1390 el,
1391 Element::ContainerStart {
1392 tag: Tag::Anonymous,
1393 kind: ContainerKind::Structure,
1394 }
1395 );
1396 let el = r.next().unwrap().unwrap();
1397 assert_eq!(el, Element::ContainerEnd);
1398 assert!(r.next().unwrap().is_none());
1399 }
1400
1401 #[test]
1402 fn next_decodes_array_start_and_end_vector_0020() {
1403 let mut r = TlvReader::new(&[0x16, 0x18]);
1404 assert_eq!(
1405 r.next().unwrap().unwrap(),
1406 Element::ContainerStart {
1407 tag: Tag::Anonymous,
1408 kind: ContainerKind::Array,
1409 }
1410 );
1411 assert_eq!(r.next().unwrap().unwrap(), Element::ContainerEnd);
1412 }
1413
1414 #[test]
1415 fn next_decodes_list_start_and_end() {
1416 let mut r = TlvReader::new(&[0x17, 0x18]);
1417 assert_eq!(
1418 r.next().unwrap().unwrap(),
1419 Element::ContainerStart {
1420 tag: Tag::Anonymous,
1421 kind: ContainerKind::List,
1422 }
1423 );
1424 assert_eq!(r.next().unwrap().unwrap(), Element::ContainerEnd);
1425 }
1426
1427 #[test]
1428 fn next_decodes_structure_with_child_streaming() {
1429 let mut r = TlvReader::new(&[0x15, 0x24, 0x00, 0x2A, 0x18]);
1430 assert_eq!(
1431 r.next().unwrap().unwrap(),
1432 Element::ContainerStart {
1433 tag: Tag::Anonymous,
1434 kind: ContainerKind::Structure,
1435 }
1436 );
1437 assert_eq!(
1438 r.next().unwrap().unwrap(),
1439 Element::Scalar {
1440 tag: Tag::Context(0),
1441 value: Value::Uint(42),
1442 }
1443 );
1444 assert_eq!(r.next().unwrap().unwrap(), Element::ContainerEnd);
1445 assert!(r.next().unwrap().is_none());
1446 }
1447
1448 #[test]
1449 fn next_errors_on_end_of_container_at_top_level() {
1450 let mut r = TlvReader::new(&[0x18]);
1451 assert!(matches!(r.next(), Err(Error::UnexpectedEndOfContainer)));
1452 }
1453
1454 #[test]
1455 fn next_errors_on_end_of_container_with_non_anonymous_tag_form() {
1456 let mut r = TlvReader::new(&[0x38, 0x05]);
1458 assert!(matches!(r.next(), Err(Error::InvalidTagControl(_))));
1459 }
1460
1461 #[test]
1462 fn next_errors_on_excessive_nesting() {
1463 let bytes: Vec<u8> = std::iter::repeat_n(0x15u8, 33).collect();
1464 let mut r = TlvReader::new(&bytes);
1465 for _ in 0..32 {
1466 assert!(matches!(
1467 r.next().unwrap().unwrap(),
1468 Element::ContainerStart {
1469 kind: ContainerKind::Structure,
1470 ..
1471 },
1472 ));
1473 }
1474 assert!(matches!(r.next(), Err(Error::ContainerTooDeep)));
1475 }
1476
1477 #[test]
1478 fn depth_returns_to_zero_after_balanced_close() {
1479 {
1482 let mut r = TlvReader::new(&[0x15, 0x18]);
1483 let _ = r.next(); let _ = r.next(); }
1486 let mut r2 = TlvReader::new(&[0x18]);
1487 assert!(matches!(r2.next(), Err(Error::UnexpectedEndOfContainer)));
1488 }
1489
1490 #[test]
1493 fn read_value_returns_empty_structure_vector_0019() {
1494 let mut r = TlvReader::new(&[0x15, 0x18]);
1495 let (tag, value) = r.read_value().unwrap();
1496 assert_eq!(tag, Tag::Anonymous);
1497 assert_eq!(value, Value::Structure(Vec::new()));
1498 }
1499
1500 #[test]
1501 fn read_value_returns_empty_array_vector_0020() {
1502 let mut r = TlvReader::new(&[0x16, 0x18]);
1503 let (tag, value) = r.read_value().unwrap();
1504 assert_eq!(tag, Tag::Anonymous);
1505 assert_eq!(value, Value::Array(Vec::new()));
1506 }
1507
1508 #[test]
1509 fn read_value_returns_structure_with_ctx_member_vector_0021() {
1510 let mut r = TlvReader::new(&[0x15, 0x24, 0x00, 0x2A, 0x18]);
1511 let (tag, value) = r.read_value().unwrap();
1512 assert_eq!(tag, Tag::Anonymous);
1513 assert_eq!(
1514 value,
1515 Value::Structure(vec![(Tag::Context(0), Value::Uint(42))])
1516 );
1517 }
1518
1519 #[test]
1520 fn read_value_returns_array_of_three_uint8_vector_0022() {
1521 let mut r = TlvReader::new(&[0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18]);
1522 let (tag, value) = r.read_value().unwrap();
1523 assert_eq!(tag, Tag::Anonymous);
1524 assert_eq!(
1525 value,
1526 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1527 );
1528 }
1529
1530 #[test]
1531 fn read_value_returns_structure_with_bool_at_ctx7_vector_0023() {
1532 let mut r = TlvReader::new(&[0x15, 0x29, 0x07, 0x18]);
1533 let (tag, value) = r.read_value().unwrap();
1534 assert_eq!(tag, Tag::Anonymous);
1535 assert_eq!(
1536 value,
1537 Value::Structure(vec![(Tag::Context(7), Value::Bool(true))])
1538 );
1539 }
1540
1541 #[test]
1542 fn read_value_returns_empty_list() {
1543 let mut r = TlvReader::new(&[0x17, 0x18]);
1544 let (tag, value) = r.read_value().unwrap();
1545 assert_eq!(tag, Tag::Anonymous);
1546 assert_eq!(value, Value::List(Vec::new()));
1547 }
1548
1549 #[test]
1550 fn read_value_handles_nested_structure() {
1551 let mut r = TlvReader::new(&[0x15, 0x35, 0x00, 0x24, 0x00, 0x2A, 0x18, 0x18]);
1552 let (tag, value) = r.read_value().unwrap();
1553 assert_eq!(tag, Tag::Anonymous);
1554 let inner = Value::Structure(vec![(Tag::Context(0), Value::Uint(42))]);
1555 let outer = Value::Structure(vec![(Tag::Context(0), inner)]);
1556 assert_eq!(value, outer);
1557 }
1558
1559 #[test]
1560 fn read_value_errors_on_unclosed_container() {
1561 let mut r = TlvReader::new(&[0x15]);
1562 assert!(matches!(r.read_value(), Err(Error::UnclosedContainer)));
1563 }
1564
1565 #[test]
1566 fn read_value_errors_on_dangling_end_of_container() {
1567 let mut r = TlvReader::new(&[0x18]);
1568 assert!(matches!(
1569 r.read_value(),
1570 Err(Error::UnexpectedEndOfContainer)
1571 ));
1572 }
1573
1574 #[test]
1577 fn read_value_rejects_array_with_context_tagged_child() {
1578 let mut r = TlvReader::new(&[0x16, 0x24, 0x00, 0x2A, 0x18]);
1582 assert!(matches!(r.read_value(), Err(Error::NonAnonymousArrayTag)));
1583 }
1584
1585 #[test]
1586 fn read_value_rejects_array_with_context_tagged_container_child() {
1587 let mut r = TlvReader::new(&[0x16, 0x35, 0x00, 0x18, 0x18]);
1590 assert!(matches!(r.read_value(), Err(Error::NonAnonymousArrayTag)));
1591 }
1592
1593 #[test]
1594 fn read_value_accepts_array_with_anonymous_children() {
1595 let mut r = TlvReader::new(&[0x16, 0x04, 0x01, 0x04, 0x02, 0x18]);
1598 let (tag, value) = r.read_value().unwrap();
1599 assert_eq!(tag, Tag::Anonymous);
1600 assert_eq!(value, Value::Array(vec![Value::Uint(1), Value::Uint(2)]));
1601 }
1602
1603 #[test]
1604 fn read_value_errors_when_element_budget_is_exceeded() {
1605 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1611 let mut r = TlvReader::with_element_budget(&bytes, 3);
1612 assert!(matches!(r.read_value(), Err(Error::ElementBudgetExceeded)));
1613 }
1614
1615 #[test]
1616 fn read_value_fast_path_at_budget_equal_to_input_len() {
1617 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1621 let mut r = TlvReader::with_element_budget(&bytes, bytes.len());
1622 let (_, value) = r.read_value().unwrap();
1623 assert_eq!(
1624 value,
1625 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1626 );
1627 }
1628
1629 #[test]
1630 fn read_value_charged_path_at_budget_one_below_input_len() {
1631 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1634 let mut r = TlvReader::with_element_budget(&bytes, 7);
1635 let (_, value) = r.read_value().unwrap();
1636 assert_eq!(
1637 value,
1638 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1639 );
1640 }
1641
1642 #[test]
1643 fn read_value_succeeds_at_exactly_the_element_budget() {
1644 let bytes = [0x16, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x18];
1646 let mut r = TlvReader::with_element_budget(&bytes, 4);
1647 let (_, value) = r.read_value().unwrap();
1648 assert_eq!(
1649 value,
1650 Value::Array(vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)])
1651 );
1652 }
1653
1654 #[test]
1655 fn read_value_budget_counts_a_single_scalar() {
1656 let mut r = TlvReader::with_element_budget(&[0x04, 0x2A], 0);
1658 assert!(matches!(r.read_value(), Err(Error::ElementBudgetExceeded)));
1659 let mut r = TlvReader::with_element_budget(&[0x04, 0x2A], 1);
1660 assert_eq!(r.read_value().unwrap(), (Tag::Anonymous, Value::Uint(42)));
1661 }
1662
1663 #[test]
1664 fn fixed_width_int_decode_still_works() {
1665 let mut r = TlvReader::new(&[0x05, 0x34, 0x12]);
1670 assert_eq!(
1671 r.next().unwrap().unwrap(),
1672 Element::Scalar {
1673 tag: Tag::Anonymous,
1674 value: Value::Uint(0x1234),
1675 }
1676 );
1677 }
1678
1679 fn struct_with_nested() -> Vec<u8> {
1684 let mut buf = Vec::new();
1685 let mut w = crate::writer::TlvWriter::new(&mut buf);
1686 w.start_structure(Tag::Anonymous).unwrap();
1687 w.put_uint(Tag::Context(0), 7).unwrap();
1688 w.start_structure(Tag::Context(9)).unwrap();
1689 w.put_uint(Tag::Context(0), 1).unwrap();
1690 w.end_container().unwrap();
1691 w.put_uint(Tag::Context(1), 42).unwrap();
1692 w.end_container().unwrap();
1693 buf
1694 }
1695
1696 #[test]
1697 fn read_utf8_truncates_at_is1_separator() {
1698 fn decode_str(s: &str) -> String {
1702 let mut buf = Vec::new();
1703 let mut w = crate::writer::TlvWriter::new(&mut buf);
1704 w.put_utf8(Tag::Anonymous, s).unwrap();
1705 match TlvReader::new(&buf).next().unwrap().unwrap() {
1706 Element::Scalar {
1707 value: Value::Utf8(t),
1708 ..
1709 } => t,
1710 other => panic!("expected Utf8 scalar, got {other:?}"),
1711 }
1712 }
1713 assert_eq!(
1716 decode_str("This is a test case #1\u{1F}suffix"),
1717 "This is a test case #1"
1718 );
1719 assert_eq!(decode_str("\u{1F} abc \u{1F} def"), "");
1720 assert_eq!(decode_str("Kitchen"), "Kitchen");
1722 assert_eq!(decode_str("Kitchen\u{1F}0409"), "Kitchen");
1723 }
1724
1725 #[test]
1726 fn skip_container_drains_nested_struct_and_positions_after() {
1727 let buf = struct_with_nested();
1728 let mut r = TlvReader::new(&buf);
1729 assert!(matches!(
1731 r.next().unwrap(),
1732 Some(Element::ContainerStart {
1733 kind: ContainerKind::Structure,
1734 ..
1735 })
1736 ));
1737 assert!(matches!(r.next().unwrap(), Some(Element::Scalar { .. })));
1739 assert!(matches!(
1741 r.next().unwrap(),
1742 Some(Element::ContainerStart {
1743 kind: ContainerKind::Structure,
1744 ..
1745 })
1746 ));
1747 r.skip_container().unwrap();
1748 match r.next().unwrap() {
1750 Some(Element::Scalar {
1751 tag: Tag::Context(1),
1752 value: Value::Uint(v),
1753 }) => {
1754 assert_eq!(v, 42);
1755 }
1756 other => panic!("expected ctx1=42 after skip, got {other:?}"),
1757 }
1758 assert!(matches!(r.next().unwrap(), Some(Element::ContainerEnd)));
1760 assert!(r.next().unwrap().is_none());
1761 }
1762
1763 #[test]
1764 fn skip_container_handles_array_and_list_and_empty() {
1765 for kind_byte in ["array", "list", "empty"] {
1766 let mut buf = Vec::new();
1767 let mut w = crate::writer::TlvWriter::new(&mut buf);
1768 w.start_structure(Tag::Anonymous).unwrap();
1769 match kind_byte {
1770 "array" => {
1771 w.start_array(Tag::Context(0)).unwrap();
1772 w.put_uint(Tag::Anonymous, 1).unwrap();
1773 w.put_uint(Tag::Anonymous, 2).unwrap();
1774 w.end_container().unwrap();
1775 }
1776 "list" => {
1777 w.start_list(Tag::Context(0)).unwrap();
1778 w.put_uint(Tag::Context(5), 9).unwrap();
1779 w.end_container().unwrap();
1780 }
1781 _ => {
1782 w.start_structure(Tag::Context(0)).unwrap();
1783 w.end_container().unwrap();
1784 }
1785 }
1786 w.put_uint(Tag::Context(1), 99).unwrap();
1787 w.end_container().unwrap();
1788
1789 let mut r = TlvReader::new(&buf);
1790 assert!(matches!(
1791 r.next().unwrap(),
1792 Some(Element::ContainerStart { .. })
1793 ));
1794 assert!(matches!(
1795 r.next().unwrap(),
1796 Some(Element::ContainerStart { .. })
1797 ));
1798 r.skip_container().unwrap();
1799 match r.next().unwrap() {
1800 Some(Element::Scalar {
1801 tag: Tag::Context(1),
1802 value: Value::Uint(v),
1803 }) => {
1804 assert_eq!(v, 99, "kind {kind_byte}");
1805 }
1806 other => panic!("kind {kind_byte}: expected ctx1=99, got {other:?}"),
1807 }
1808 }
1809 }
1810
1811 #[test]
1812 fn skip_container_unclosed_is_error() {
1813 let mut buf = Vec::new();
1815 {
1816 let mut w = crate::writer::TlvWriter::new(&mut buf);
1817 w.start_structure(Tag::Anonymous).unwrap();
1818 w.start_structure(Tag::Context(0)).unwrap();
1819 w.put_uint(Tag::Anonymous, 1).unwrap();
1820 }
1822 let mut r = TlvReader::new(&buf);
1823 assert!(matches!(
1824 r.next().unwrap(),
1825 Some(Element::ContainerStart { .. })
1826 ));
1827 assert!(matches!(
1828 r.next().unwrap(),
1829 Some(Element::ContainerStart { .. })
1830 ));
1831 assert!(matches!(r.skip_container(), Err(Error::UnclosedContainer)));
1832 }
1833
1834 #[test]
1837 fn skip_container_does_not_validate_skipped_utf8() {
1838 let bytes = [
1847 0x15, 0x35, 0x09, 0x0C, 0x01, 0xFF, 0x18, 0x24, 0x01, 0x2A, 0x18,
1848 ];
1849 let mut r = TlvReader::new(&bytes);
1850 r.next().unwrap(); assert!(matches!(
1852 r.next().unwrap(),
1853 Some(Element::ContainerStart { .. })
1854 ));
1855 r.skip_container().unwrap();
1858 assert!(matches!(
1859 r.next().unwrap(),
1860 Some(Element::Scalar {
1861 tag: Tag::Context(1),
1862 value: Value::Uint(42)
1863 })
1864 ));
1865 }
1866
1867 #[test]
1868 fn skip_container_truncated_string_body_is_eof() {
1869 let bytes = [0x15, 0x35, 0x09, 0x0C, 0x05, b'H', b'i'];
1871 let mut r = TlvReader::new(&bytes);
1872 r.next().unwrap();
1873 r.next().unwrap();
1874 assert!(matches!(r.skip_container(), Err(Error::UnexpectedEof)));
1875 }
1876
1877 #[test]
1878 fn skip_container_enforces_depth_cap() {
1879 let bytes: Vec<u8> = std::iter::repeat_n(0x15u8, 33).collect();
1883 let mut r = TlvReader::new(&bytes);
1884 r.next().unwrap();
1885 r.next().unwrap();
1886 assert!(matches!(r.skip_container(), Err(Error::ContainerTooDeep)));
1887 }
1888
1889 #[test]
1890 fn skip_container_rejects_tagged_end_marker() {
1891 let bytes = [0x15, 0x35, 0x09, 0x38, 0x05];
1893 let mut r = TlvReader::new(&bytes);
1894 r.next().unwrap();
1895 r.next().unwrap();
1896 assert!(matches!(
1897 r.skip_container(),
1898 Err(Error::InvalidTagControl(_))
1899 ));
1900 }
1901
1902 #[test]
1903 fn skip_container_misuse_at_top_level_errors() {
1904 let mut r = TlvReader::new(&[0x18]);
1907 assert!(matches!(
1908 r.skip_container(),
1909 Err(Error::UnexpectedEndOfContainer)
1910 ));
1911 }
1912
1913 #[test]
1916 fn next_ref_borrows_utf8_and_bytes() {
1917 let mut buf = Vec::new();
1918 let mut w = crate::writer::TlvWriter::new(&mut buf);
1919 w.put_utf8(Tag::Context(1), "Kitchen\u{1F}0409").unwrap();
1920 w.put_bytes(Tag::Context(2), &[0xDE, 0xAD]).unwrap();
1921 let mut r = TlvReader::new(&buf);
1922 match r.next_ref().unwrap().unwrap() {
1923 ElementRef::Scalar {
1924 tag: Tag::Context(1),
1925 value: ValueRef::Utf8(s),
1926 } => {
1927 assert_eq!(s, "Kitchen");
1929 }
1930 other => panic!("expected borrowed Utf8, got {other:?}"),
1931 }
1932 match r.next_ref().unwrap().unwrap() {
1933 ElementRef::Scalar {
1934 tag: Tag::Context(2),
1935 value: ValueRef::Bytes(b),
1936 } => {
1937 assert_eq!(b, &[0xDE, 0xAD]);
1938 }
1939 other => panic!("expected borrowed Bytes, got {other:?}"),
1940 }
1941 }
1942
1943 #[test]
1944 fn value_ref_converts_to_owned_value() {
1945 assert_eq!(
1946 Value::from(ValueRef::Utf8("hi")),
1947 Value::Utf8(String::from("hi"))
1948 );
1949 assert_eq!(
1950 Value::from(ValueRef::Bytes(&[1, 2])),
1951 Value::Bytes(vec![1, 2])
1952 );
1953 assert_eq!(Value::from(ValueRef::Uint(7)), Value::Uint(7));
1954 assert_eq!(Value::from(ValueRef::Null), Value::Null);
1955 }
1956
1957 #[test]
1960 fn scalar_element_span_covers_full_element_and_body_excludes_tag() {
1961 let bytes = [0x24, 0x05, 0x2A];
1963 let mut r = TlvReader::new(&bytes);
1964 assert!(r.element_span().is_none(), "no element returned yet");
1965 r.next().unwrap().unwrap();
1966 let span = r.element_span().unwrap();
1967 assert_eq!(span.full(), 0..3);
1968 assert_eq!(span.body(), 2..3);
1969 assert_eq!(r.span_bytes(span.full()), &bytes[..]);
1970 assert_eq!(r.span_bytes(span.body()), &[0x2A]);
1971 }
1972
1973 #[test]
1974 fn string_span_body_includes_length_field() {
1975 let bytes = [0x0C, 0x02, b'H', b'i'];
1977 let mut r = TlvReader::new(&bytes);
1978 r.next().unwrap().unwrap();
1979 let span = r.element_span().unwrap();
1980 assert_eq!(span.full(), 0..4);
1981 assert_eq!(span.body(), 1..4);
1982 }
1983
1984 #[test]
1985 fn skip_container_span_covers_container_and_body_excludes_header() {
1986 let buf = {
1988 let mut b = Vec::new();
1989 let mut w = crate::writer::TlvWriter::new(&mut b);
1990 w.start_structure(Tag::Anonymous).unwrap();
1991 w.start_structure(Tag::Context(9)).unwrap();
1992 w.put_uint(Tag::Context(1), 0x2A).unwrap();
1993 w.end_container().unwrap();
1994 w.put_uint(Tag::Context(2), 7).unwrap();
1995 w.end_container().unwrap();
1996 b
1997 };
1998 let mut r = TlvReader::new(&buf);
2000 r.next().unwrap(); r.next().unwrap(); let header = r.element_span().unwrap();
2003 assert_eq!(header.full(), 1..3, "header-only span after ContainerStart");
2004 let span = r.skip_container_span().unwrap();
2005 assert_eq!(span.full(), 1..7, "control+tag+children+end marker");
2006 assert_eq!(r.span_bytes(span.body()), &[0x24, 0x01, 0x2A, 0x18]);
2008 assert!(matches!(
2010 r.next().unwrap(),
2011 Some(Element::Scalar {
2012 tag: Tag::Context(2),
2013 value: Value::Uint(7)
2014 })
2015 ));
2016 }
2017
2018 #[test]
2019 fn retag_reemission_from_span_matches_writer_output() {
2020 let bytes = [0x35, 0x09, 0x25, 0x00, 0x2A, 0x00, 0x18];
2027 let mut r = TlvReader::new(&bytes);
2028 assert!(matches!(
2029 r.next().unwrap(),
2030 Some(Element::ContainerStart {
2031 kind: ContainerKind::Structure,
2032 ..
2033 })
2034 ));
2035 let span = r.skip_container_span().unwrap();
2036 let mut out = Vec::new();
2037 {
2038 let mut w = crate::writer::TlvWriter::new(&mut out);
2039 w.start_structure(Tag::Anonymous).unwrap();
2040 }
2041 out.extend_from_slice(r.span_bytes(span.body()));
2042 assert_eq!(out, [0x15, 0x25, 0x00, 0x2A, 0x00, 0x18]);
2044 }
2045
2046 #[test]
2047 fn skip_container_span_after_scalar_is_rejected() {
2048 let bytes = [0x15, 0x24, 0x01, 0x2A, 0x18];
2053 let mut r = TlvReader::new(&bytes);
2054 r.next().unwrap(); r.next().unwrap(); assert!(matches!(
2057 r.skip_container_span(),
2058 Err(Error::UnexpectedEndOfContainer)
2059 ));
2060 assert!(matches!(r.next().unwrap(), Some(Element::ContainerEnd)));
2062 }
2063
2064 #[test]
2065 fn skip_container_span_before_any_element_is_rejected() {
2066 let mut r = TlvReader::new(&[0x15, 0x18]);
2067 assert!(matches!(
2068 r.skip_container_span(),
2069 Err(Error::UnexpectedEndOfContainer)
2070 ));
2071 }
2072
2073 #[test]
2074 fn skip_container_span_twice_is_rejected() {
2075 let bytes = [0x35, 0x09, 0x24, 0x01, 0x2A, 0x18];
2078 let mut r = TlvReader::new(&bytes);
2079 r.next().unwrap(); assert!(r.skip_container_span().is_ok());
2081 assert!(matches!(
2082 r.skip_container_span(),
2083 Err(Error::UnexpectedEndOfContainer)
2084 ));
2085 }
2086
2087 #[test]
2088 fn skip_container_span_after_plain_skip_is_rejected() {
2089 let bytes = [0x15, 0x35, 0x09, 0x18, 0x24, 0x02, 0x07, 0x18];
2092 let mut r = TlvReader::new(&bytes);
2093 r.next().unwrap(); r.next().unwrap(); r.skip_container().unwrap();
2096 assert!(matches!(
2097 r.skip_container_span(),
2098 Err(Error::UnexpectedEndOfContainer)
2099 ));
2100 }
2101
2102 #[test]
2103 fn span_bytes_out_of_range_returns_empty() {
2104 let r = TlvReader::new(&[0x14]);
2105 assert_eq!(r.span_bytes(5..9), &[] as &[u8]);
2106 }
2107
2108 #[test]
2114 fn next_and_next_ref_agree_on_hostile_inputs() {
2115 let cases: &[(&[u8], &str)] = &[
2117 (
2118 &[0x0C, 0x03, 0x1F, 0x61, 0x62],
2119 "IS1 at index 0 -> empty string",
2120 ),
2121 (&[0x0C, 0x01, 0x1F], "IS1 only -> empty string"),
2122 (&[0x0C, 0x03, 0x61, 0x1F, 0xFF], "invalid UTF-8 after IS1"),
2123 (&[0x0C, 0x05, 0x61, 0x62], "truncated string payload"),
2124 (&[0x24, 0x01], "truncated scalar payload"),
2125 (&[0x18], "stray end-of-container"),
2126 (&[0x1F, 0x00], "invalid element type code"),
2127 ];
2128 for (bytes, what) in cases {
2129 let mut a = TlvReader::new(bytes);
2130 let mut b = TlvReader::new(bytes);
2131 loop {
2132 let ra = a.next();
2133 let rb = b.next_ref().map(|o| o.map(Element::from));
2134 assert_eq!(
2135 format!("{ra:?}"),
2136 format!("{rb:?}"),
2137 "next vs next_ref diverged on: {what}"
2138 );
2139 match ra {
2140 Ok(Some(_)) => {}
2141 _ => break, }
2143 }
2144 }
2145 }
2146
2147 #[test]
2150 fn next_ref_payloads_borrow_from_input_across_calls() {
2151 let mut buf = Vec::new();
2152 {
2153 let mut w = crate::writer::TlvWriter::new(&mut buf);
2154 w.put_utf8(Tag::Context(0), "abc").unwrap();
2155 w.put_bytes(Tag::Context(1), b"xyz").unwrap();
2156 }
2157 let mut r = TlvReader::new(&buf);
2158 let first = r.next_ref().unwrap().unwrap();
2159 let second = r.next_ref().unwrap().unwrap();
2160 let (
2162 ElementRef::Scalar {
2163 value: ValueRef::Utf8(a),
2164 ..
2165 },
2166 ElementRef::Scalar {
2167 value: ValueRef::Bytes(b),
2168 ..
2169 },
2170 ) = (first, second)
2171 else {
2172 panic!("unexpected shapes: {first:?} / {second:?}");
2173 };
2174 assert_eq!((a, b), ("abc", &b"xyz"[..]));
2175 }
2176
2177 #[test]
2180 fn plain_skip_container_updates_element_span_to_full_container() {
2181 let buf = struct_with_nested();
2190 let mut r = TlvReader::new(&buf);
2191 r.next().unwrap(); r.next().unwrap(); r.next().unwrap(); assert_eq!(r.element_span().unwrap().full(), 4..6);
2195 r.skip_container().unwrap();
2196 let span = r.element_span().unwrap();
2197 assert_eq!(span.full(), 4..10, "whole container incl. end marker");
2198 assert_eq!(r.span_bytes(span.body()), &[0x24, 0x00, 0x01, 0x18]);
2199 }
2200
2201 #[test]
2205 fn depth_rebalanced_after_skip_rejects_stray_end_marker() {
2206 let bytes = [0x15, 0x35, 0x09, 0x18, 0x18, 0x18];
2208 let mut r = TlvReader::new(&bytes);
2209 r.next().unwrap(); r.next().unwrap(); r.skip_container().unwrap(); assert!(matches!(r.next(), Ok(Some(Element::ContainerEnd)))); assert!(matches!(r.next(), Err(Error::UnexpectedEndOfContainer)));
2214 }
2215}