1use crate::error::{Error, ErrorCode, Limit, Path, Result};
9use crate::length::{self, Encoding, Length};
10use crate::limits::{Budget, BudgetView, Limits};
11use crate::memory::{Memory, Work};
12use crate::tag::{self, Tag, universal};
13use crate::value::{self, BitString, Integer, Oid};
14
15mod integer;
16pub use integer::IntegerReading;
17
18#[derive(Debug)]
20pub struct Parser {
21 budget: Budget,
22 encoding: Encoding,
23}
24
25impl Parser {
26 #[must_use]
28 pub fn new(encoding: Encoding, limits: Limits, memory: Memory) -> Self {
29 Self {
30 budget: Budget::new(limits, memory),
31 encoding,
32 }
33 }
34
35 #[must_use]
37 pub fn der(memory: Memory) -> Self {
38 Self::new(Encoding::Der, Limits::default(), memory)
39 }
40
41 #[must_use]
43 pub fn ber(memory: Memory) -> Self {
44 Self::new(Encoding::Ber, Limits::default(), memory)
45 }
46
47 #[must_use]
49 pub fn limits(&self) -> Limits {
50 self.budget.limits()
51 }
52
53 #[must_use]
58 pub fn memory(&self) -> &Memory {
59 self.budget.memory()
60 }
61
62 #[must_use]
69 pub fn execution_in<'work>(
70 &'work self,
71 memory: &'work Memory,
72 ) -> crate::memory::Execution<'work> {
73 crate::memory::Execution::new(memory, BudgetView::root(&self.budget))
74 }
75
76 pub(crate) fn execution_query_in<'work>(
77 &'work self,
78 memory: &'work Memory,
79 operation: &'work Budget,
80 ) -> crate::memory::Execution<'work> {
81 crate::memory::Execution::new(memory, BudgetView::query(&self.budget, operation))
82 }
83
84 pub(crate) fn source_budget(&self) -> &Budget {
85 &self.budget
86 }
87
88 pub fn read<'a>(&'a self, data: &'a [u8], base: u64) -> Result<Reader<'a>> {
98 self.read_as(data, base, self.encoding)
99 }
100
101 pub fn read_as<'a>(
109 &'a self,
110 data: &'a [u8],
111 base: u64,
112 encoding: Encoding,
113 ) -> Result<Reader<'a>> {
114 self.read_as_in(data, base, encoding, self.memory())
115 }
116
117 fn read_as_in<'a>(
118 &'a self,
119 data: &'a [u8],
120 base: u64,
121 encoding: Encoding,
122 execution: &Memory,
123 ) -> Result<Reader<'a>> {
124 u64::try_from(data.len())
125 .ok()
126 .and_then(|length| base.checked_add(length))
127 .ok_or_else(|| Error::new(ErrorCode::OffsetTooLarge, base, Path::default()))?;
128
129 Ok(Reader {
130 data,
131 pos: 0,
132 base,
133 depth: 0,
134 next_index: 0,
135 path: Path::default(),
136 encoding,
137 parser: self,
138 execution: execution.clone(),
139 query: None,
140 })
141 }
142
143 pub fn read_nested<'a>(
158 &'a self,
159 data: &'a [u8],
160 base: u64,
161 encoding: Encoding,
162 outer: u32,
163 ) -> Result<Reader<'a>> {
164 self.read_nested_in(data, base, encoding, outer, self.memory())
165 }
166
167 pub fn read_nested_in<'a>(
172 &'a self,
173 data: &'a [u8],
174 base: u64,
175 encoding: Encoding,
176 outer: u32,
177 execution: &Memory,
178 ) -> Result<Reader<'a>> {
179 self.read_depth_in(data, base, encoding, outer.checked_add(1), execution)
180 }
181
182 pub(crate) fn read_source_in<'a>(
183 &'a self,
184 data: &'a [u8],
185 base: u64,
186 encoding: Encoding,
187 depth: u32,
188 execution: &Memory,
189 ) -> Result<Reader<'a>> {
190 self.read_depth_in(data, base, encoding, Some(depth), execution)
191 }
192
193 fn read_depth_in<'a>(
194 &'a self,
195 data: &'a [u8],
196 base: u64,
197 encoding: Encoding,
198 depth: Option<u32>,
199 execution: &Memory,
200 ) -> Result<Reader<'a>> {
201 let mut reader = self.read_as_in(data, base, encoding, execution)?;
202 let depth = depth.ok_or_else(|| {
203 Error::new(
204 ErrorCode::LimitExceeded(Limit::Depth),
205 base,
206 Path::default(),
207 )
208 })?;
209 self.budget
210 .depth(depth)
211 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
212 reader.depth = depth;
213 Ok(reader)
214 }
215
216 pub fn read_nested_query_in<'a>(
224 &'a self,
225 query: &Reader<'a>,
226 data: &'a [u8],
227 base: u64,
228 encoding: Encoding,
229 outer: u32,
230 ) -> Result<Reader<'a>> {
231 self.read_nested_operation_in(
232 data,
233 base,
234 encoding,
235 outer,
236 query.budget().operation(),
237 query.memory(),
238 )
239 }
240
241 pub fn read_query_in<'a>(
251 &'a self,
252 query: &Reader<'a>,
253 data: &'a [u8],
254 base: u64,
255 encoding: Encoding,
256 depth: u32,
257 ) -> Result<Reader<'a>> {
258 self.read_query_budget_in(
259 data,
260 base,
261 encoding,
262 depth,
263 query.budget().operation(),
264 query.memory(),
265 )
266 }
267
268 pub(crate) fn read_nested_operation_in<'a>(
269 &'a self,
270 data: &'a [u8],
271 base: u64,
272 encoding: Encoding,
273 outer: u32,
274 operation: &'a Budget,
275 execution: &Memory,
276 ) -> Result<Reader<'a>> {
277 let depth = nested_depth(outer, base)?;
278 self.read_query_budget_in(data, base, encoding, depth, operation, execution)
279 }
280
281 pub(crate) fn read_query_budget_in<'a>(
282 &'a self,
283 data: &'a [u8],
284 base: u64,
285 encoding: Encoding,
286 depth: u32,
287 operation: &'a Budget,
288 execution: &Memory,
289 ) -> Result<Reader<'a>> {
290 self.read_scoped_source_in(data, base, encoding, depth, Some(operation), execution)
291 }
292
293 pub(crate) fn read_scoped_source_in<'source: 'operation, 'operation>(
294 &'source self,
295 data: &'source [u8],
296 base: u64,
297 encoding: Encoding,
298 depth: u32,
299 operation: Option<&'operation Budget>,
300 execution: &Memory,
301 ) -> Result<ScopedReader<'source, 'operation>> {
302 let Some(operation) = operation else {
303 return self.read_depth_in(data, base, encoding, Some(depth), execution);
304 };
305 let budget = BudgetView::query(&self.budget, operation);
306 budget
307 .depth(depth)
308 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
309 budget
310 .work_in(1, execution)
311 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
312 let reader = self.read_as_in(data, base, encoding, execution)?;
313 Ok(ScopedReader {
314 data: reader.data,
315 pos: reader.pos,
316 base: reader.base,
317 depth,
318 next_index: reader.next_index,
319 path: reader.path,
320 encoding: reader.encoding,
321 parser: reader.parser,
322 execution: reader.execution,
323 query: Some(operation),
324 })
325 }
326}
327
328fn nested_depth(outer: u32, base: u64) -> Result<u32> {
329 outer.checked_add(1).ok_or_else(|| {
330 Error::new(
331 ErrorCode::LimitExceeded(Limit::Depth),
332 base,
333 Path::default(),
334 )
335 })
336}
337
338#[derive(Debug, Clone, Copy, PartialEq, Eq)]
340pub struct Span {
341 pub start: u64,
343 pub length: u64,
345}
346
347impl Span {
348 #[must_use]
354 pub fn end(self) -> u64 {
355 self.start + self.length
356 }
357}
358
359#[derive(Debug, Clone, Copy)]
361pub struct Element<'a> {
362 tag: Tag,
363 contents: &'a [u8],
364 bytes: &'a [u8],
365 contents_span: Span,
366 whole: Span,
367 indefinite: bool,
368 index: u32,
369}
370
371impl<'a> Element<'a> {
372 #[must_use]
374 pub fn tag(self) -> Tag {
375 self.tag
376 }
377
378 #[must_use]
383 pub fn contents(self) -> &'a [u8] {
384 self.contents
385 }
386
387 #[must_use]
396 pub fn as_bytes(self) -> &'a [u8] {
397 self.bytes
398 }
399
400 #[must_use]
402 pub fn contents_span(self) -> Span {
403 self.contents_span
404 }
405
406 #[must_use]
411 pub fn span(self) -> Span {
412 self.whole
413 }
414
415 #[must_use]
417 pub fn is_indefinite(self) -> bool {
418 self.indefinite
419 }
420
421 #[must_use]
423 pub fn index(self) -> u32 {
424 self.index
425 }
426}
427
428#[derive(Debug)]
434pub struct ScopedReader<'a: 'operation, 'operation> {
435 data: &'a [u8],
436 pos: usize,
437 base: u64,
438 depth: u32,
439 next_index: u32,
440 path: Path,
441 encoding: Encoding,
442 parser: &'a Parser,
443 execution: Memory,
444 query: Option<&'operation Budget>,
445}
446
447pub type Reader<'a> = ScopedReader<'a, 'a>;
451
452impl<'a: 'operation, 'operation> ScopedReader<'a, 'operation> {
453 #[must_use]
455 pub fn memory(&self) -> &Memory {
456 &self.execution
457 }
458
459 #[must_use]
479 pub fn execution(&self) -> crate::memory::Execution<'_> {
480 crate::memory::Execution::new(self.memory(), self.budget())
481 }
482
483 #[must_use]
489 pub fn execution_in<'work>(&self, memory: &'work Memory) -> crate::memory::Execution<'work>
490 where
491 'a: 'work,
492 'operation: 'work,
493 {
494 crate::memory::Execution::new(memory, self.budget())
495 }
496
497 #[must_use]
506 pub fn execution_query<'query>(
507 &self,
508 query: &'query Reader<'_>,
509 ) -> crate::memory::Execution<'query>
510 where
511 'a: 'query,
512 {
513 crate::memory::Execution::new(
514 query.memory(),
515 BudgetView::query(&self.parser.budget, query.budget().operation()),
516 )
517 }
518
519 #[must_use]
523 pub fn with_execution(mut self, execution: &Memory) -> Self {
524 self.execution = execution.clone();
525 self
526 }
527
528 pub fn with_query<'query>(self, query: &Reader<'query>) -> Result<Reader<'query>>
533 where
534 'a: 'query,
535 {
536 let operation = query.budget().operation();
537 let budget = BudgetView::query(&self.parser.budget, operation);
538 budget.depth(self.depth).map_err(|limit| {
539 Error::new(
540 ErrorCode::LimitExceeded(limit),
541 self.offset(),
542 Path::default(),
543 )
544 })?;
545 budget.work_in(1, query.memory()).map_err(|limit| {
546 Error::new(
547 ErrorCode::LimitExceeded(limit),
548 self.offset(),
549 Path::default(),
550 )
551 })?;
552 Ok(ScopedReader {
553 data: self.data,
554 pos: self.pos,
555 base: self.base,
556 depth: self.depth,
557 next_index: self.next_index,
558 path: self.path,
559 encoding: self.encoding,
560 parser: self.parser,
561 execution: query.memory().clone(),
562 query: Some(operation),
563 })
564 }
565
566 pub fn try_clone(&self) -> Result<Self> {
568 self.admit_path(0)
569 .map_err(|reason| Error::resource(reason, self.offset()))?;
570 Ok(Self {
571 data: self.data,
572 pos: self.pos,
573 base: self.base,
574 depth: self.depth,
575 next_index: self.next_index,
576 path: self
577 .path
578 .try_copy_in(self.memory())
579 .map_err(|reason| Error::resource(reason, self.offset()))?,
580 encoding: self.encoding,
581 parser: self.parser,
582 execution: self.execution.clone(),
583 query: self.query,
584 })
585 }
586 #[must_use]
588 pub fn is_empty(&self) -> bool {
589 self.pos >= self.data.len()
590 }
591
592 #[must_use]
596 pub fn parser(&self) -> &'a Parser {
597 self.parser
598 }
599
600 fn budget(&self) -> BudgetView<'operation> {
602 match self.query {
603 Some(operation) => BudgetView::query(&self.parser.budget, operation),
604 None => BudgetView::root(&self.parser.budget),
605 }
606 }
607
608 pub fn charge(&self, amount: u64) -> Result<()> {
615 self.budget()
616 .work_in(amount, self.memory())
617 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), self.offset()))
618 }
619
620 #[must_use]
624 pub fn depth(&self) -> u32 {
625 self.depth
626 }
627
628 #[must_use]
633 pub fn offset(&self) -> u64 {
634 self.base + self.pos as u64
635 }
636
637 #[must_use]
639 pub fn remaining(&self) -> &'a [u8] {
640 &self.data[self.pos.min(self.data.len())..]
641 }
642
643 #[must_use]
645 pub fn path(&self) -> &Path {
646 &self.path
647 }
648
649 #[must_use]
652 pub fn encoding(&self) -> Encoding {
653 self.encoding
654 }
655
656 pub fn reread(&self, element: &Element<'a>, encoding: Encoding) -> Result<Self> {
667 self.admit_path(0)
668 .map_err(|reason| Error::resource(reason, element.whole.start))?;
669 Ok(Self {
670 data: element.bytes,
671 pos: 0,
672 base: element.whole.start,
673 depth: self.depth,
674 next_index: 0,
675 path: self
676 .path
677 .try_copy_in(self.memory())
678 .map_err(|reason| Error::resource(reason, element.whole.start))?,
679 encoding,
680 parser: self.parser,
681 execution: self.execution.clone(),
682 query: self.query,
683 })
684 }
685
686 pub fn next_element(&mut self) -> Result<Option<Element<'a>>> {
688 if self.is_empty() {
689 return Ok(None);
690 }
691
692 let header = self.read_header()?;
693
694 if header.tag.is_end_of_contents() {
698 return Err(self.fail_at(ErrorCode::MalformedEndOfContents, header.start));
699 }
700
701 self.finish(header).map(Some)
702 }
703
704 pub fn expect(&mut self, tag: Tag) -> Result<Element<'a>> {
706 let offset = self.offset();
707 match self.next_element()? {
708 Some(element) if element.tag == tag => Ok(element),
709 Some(element) => Err(self.fail_under(ErrorCode::UnexpectedTag, &element)),
714 None => Err(self.fail_at(ErrorCode::UnexpectedEnd, offset)),
715 }
716 }
717
718 pub fn skip(&mut self) -> Result<bool> {
724 Ok(self.next_element()?.is_some())
725 }
726
727 pub fn enter(&self, element: &Element<'a>) -> Result<Self> {
734 if !element.tag.is_constructed() {
735 return Err(self.fail_under(ErrorCode::WrongConstruction, element));
736 }
737
738 let depth = self.depth.checked_add(1).ok_or_else(|| {
741 self.fail_under_at(
742 ErrorCode::LimitExceeded(Limit::Depth),
743 element,
744 element.contents_span.start,
745 )
746 })?;
747 self.budget().depth(depth).map_err(|limit| {
748 self.fail_under_at(
749 ErrorCode::LimitExceeded(limit),
750 element,
751 element.contents_span.start,
752 )
753 })?;
754 self.admit_path(1)
755 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
756 let mut path = self
757 .path
758 .try_copy_in(self.memory())
759 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
760 path.push(self.memory(), element.index)
761 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
762
763 Ok(Self {
764 data: element.contents,
765 pos: 0,
766 base: element.contents_span.start,
767 depth,
768 next_index: 0,
769 path,
770 encoding: self.encoding,
771 parser: self.parser,
772 execution: self.execution.clone(),
773 query: self.query,
774 })
775 }
776
777 pub fn oid(&self, element: &Element<'a>) -> Result<Oid<'a>> {
779 self.primitive(element)?;
780 self.budget()
784 .work_in(element.contents.len() as u64, self.memory())
785 .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
786 value::oid(element.contents).map_err(|code| self.fail_under(code, element))
787 }
788
789 pub fn integer(&self, element: &Element<'a>) -> Result<Integer<'a>> {
791 self.primitive(element)?;
792 value::integer(element.contents).map_err(|code| self.fail_under(code, element))
793 }
794
795 pub fn bit_string(&self, element: &Element<'a>) -> Result<BitString<'a>> {
802 self.primitive(element)?;
803 value::bit_string(element.contents, self.encoding)
804 .map_err(|code| self.fail_under(code, element))
805 }
806
807 pub fn boolean(&self, element: &Element<'a>) -> Result<bool> {
809 self.primitive(element)?;
810 value::boolean(element.contents, self.encoding)
811 .map_err(|code| self.fail_under(code, element))
812 }
813
814 pub fn null(&self, element: &Element<'a>) -> Result<()> {
816 self.primitive(element)?;
817 value::null(element.contents).map_err(|code| self.fail_under(code, element))
818 }
819
820 pub fn real(&self, element: &Element<'a>) -> Result<()> {
827 self.primitive(element)?;
828 self.budget()
832 .work_in(element.contents.len() as u64, self.memory())
833 .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
834 value::real(element.contents, self.encoding).map_err(|code| self.fail_under(code, element))
835 }
836
837 pub fn read_oid(&mut self) -> Result<Oid<'a>> {
839 let element = self.expect(Tag::primitive(universal::OID))?;
840 self.oid(&element)
841 }
842
843 pub fn read_integer(&mut self) -> Result<Integer<'a>> {
845 let element = self.expect(Tag::primitive(universal::INTEGER))?;
846 self.integer(&element)
847 }
848
849 pub fn read_bit_string(&mut self) -> Result<BitString<'a>> {
851 let element = self.expect(Tag::primitive(universal::BIT_STRING))?;
852 self.bit_string(&element)
853 }
854
855 pub fn read_boolean(&mut self) -> Result<bool> {
857 let element = self.expect(Tag::primitive(universal::BOOLEAN))?;
858 self.boolean(&element)
859 }
860
861 fn primitive(&self, element: &Element<'a>) -> Result<()> {
862 if element.tag.is_constructed() {
863 return Err(self.fail_under(ErrorCode::WrongConstruction, element));
864 }
865 Ok(())
866 }
867
868 #[must_use]
870 pub fn fail_under(&self, code: ErrorCode, element: &Element<'a>) -> Error {
871 self.fail_under_at(code, element, element.whole.start)
872 }
873
874 fn fail_under_at(&self, code: ErrorCode, element: &Element<'a>, offset: u64) -> Error {
875 match self.path_into(element.index, &[]) {
876 Ok(path) => Error::new(code, offset, path),
877 Err(reason) => Error::resource(reason, offset),
878 }
879 }
880
881 fn fail_at(&self, code: ErrorCode, offset: u64) -> Error {
882 if let Err(reason) = self.admit_path(0) {
883 return Error::resource(reason, offset);
884 }
885 match self.path.try_copy_in(self.memory()) {
886 Ok(path) => Error::new(code, offset, path),
887 Err(reason) => Error::resource(reason, offset),
888 }
889 }
890
891 fn read_header(&mut self) -> Result<Header> {
892 let start = self.offset();
893 self.budget()
894 .element()
895 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), start))?;
896
897 let rest = &self.data[self.pos..];
898 header_at(rest, self.encoding, start, self.budget(), self.memory())
899 .map_err(|(code, at)| self.fail_at(code, at))
900 }
901
902 fn finish(&mut self, header: Header) -> Result<Element<'a>> {
903 let contents_at = self.pos + header.len;
904 let contents_start = header.start + header.len as u64;
905
906 let (contents_len, total_len, indefinite) = match header.length {
907 Length::Definite(length) => {
908 self.budget()
909 .length(length)
910 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
911
912 let length = usize::try_from(length)
913 .map_err(|_| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
914
915 let end = contents_at
916 .checked_add(length)
917 .ok_or_else(|| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
918
919 if end > self.data.len() {
920 return Err(self.fail_at(ErrorCode::UnexpectedEnd, header.start));
921 }
922
923 (length, header.len + length, false)
924 }
925 Length::Indefinite => {
926 if !header.tag.is_constructed() {
927 return Err(self.fail_at(ErrorCode::WrongConstruction, header.start));
928 }
929 let contents_len =
930 self.scan_to_end_of_contents(contents_at, contents_start, self.next_index)?;
931
932 self.budget()
937 .length(contents_len as u64)
938 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
939
940 (contents_len, header.len + contents_len + 2, true)
943 }
944 };
945
946 let contents = &self.data[contents_at..contents_at + contents_len];
947 let bytes = &self.data[self.pos..self.pos + total_len];
950 let index = self.next_index;
951
952 self.pos += total_len;
953 self.next_index = self
954 .next_index
955 .checked_add(1)
956 .ok_or_else(|| self.fail_at(ErrorCode::LimitExceeded(Limit::Elements), header.start))?;
957
958 Ok(Element {
959 tag: header.tag,
960 contents,
961 bytes,
962 contents_span: Span {
963 start: contents_start,
964 length: contents_len as u64,
965 },
966 whole: Span {
967 start: header.start,
968 length: total_len as u64,
969 },
970 indefinite,
971 index,
972 })
973 }
974
975 fn scan_to_end_of_contents(
985 &self,
986 from: usize,
987 from_offset: u64,
988 own_index: u32,
989 ) -> Result<usize> {
990 let mut cursor = from;
991 let mut offset = from_offset;
992
993 let mut trail = self.execution().vector::<u32>();
997 let mut index: u32 = 0;
998
999 let fail = |code: ErrorCode, at: u64, trail: &[u32]| match self.path_into(own_index, trail)
1003 {
1004 Ok(path) => Error::new(code, at, path),
1005 Err(reason) => Error::resource(reason, at),
1006 };
1007 let spent =
1008 |limit: Limit, at: u64, trail: &[u32]| fail(ErrorCode::LimitExceeded(limit), at, trail);
1009
1010 loop {
1011 let depth = u32::try_from(trail.len())
1012 .ok()
1013 .and_then(|nested| self.depth.checked_add(nested))
1014 .and_then(|depth| depth.checked_add(1))
1015 .ok_or_else(|| spent(Limit::Depth, offset, &trail))?;
1016 self.budget()
1017 .depth(depth)
1018 .map_err(|limit| spent(limit, offset, &trail))?;
1019
1020 let rest = self
1021 .data
1022 .get(cursor..)
1023 .filter(|rest| !rest.is_empty())
1024 .ok_or_else(|| fail(ErrorCode::UnterminatedContents, from_offset, &trail))?;
1025
1026 let header = header_at(rest, self.encoding, offset, self.budget(), self.memory())
1027 .map_err(|(code, at)| fail(code, at, &trail))?;
1028 let inner_tag = header.tag;
1029 let inner_length = header.length;
1030 let header_len = header.len;
1031
1032 if inner_tag.is_end_of_contents() {
1033 if header_len != 2 || !matches!(inner_length, Length::Definite(0)) {
1038 return Err(fail(ErrorCode::MalformedEndOfContents, offset, &trail));
1039 }
1040 match trail.pop() {
1041 None => return Ok(cursor - from),
1043 Some(outer) => {
1045 index = outer
1046 .checked_add(1)
1047 .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
1048 }
1049 }
1050 cursor += header_len;
1051 offset += header_len as u64;
1052 continue;
1053 }
1054
1055 let step = match inner_length {
1056 Length::Indefinite => {
1057 if !inner_tag.is_constructed() {
1058 return Err(fail(ErrorCode::WrongConstruction, offset, &trail));
1059 }
1060 trail
1063 .try_push(index)
1064 .map_err(|reason| Error::resource(reason, offset))?;
1065 index = 0;
1066 header_len
1067 }
1068 Length::Definite(length) => {
1069 self.budget()
1070 .length(length)
1071 .map_err(|limit| spent(limit, offset, &trail))?;
1072 let length = usize::try_from(length)
1073 .map_err(|_| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
1074 index = index
1075 .checked_add(1)
1076 .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
1077 header_len
1078 .checked_add(length)
1079 .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?
1080 }
1081 };
1082
1083 cursor = cursor
1084 .checked_add(step)
1085 .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
1086 if cursor > self.data.len() {
1087 return Err(fail(ErrorCode::UnexpectedEnd, offset, &trail));
1088 }
1089 offset += step as u64;
1090 }
1091 }
1092
1093 fn path_into(
1097 &self,
1098 own_index: u32,
1099 trail: &[u32],
1100 ) -> core::result::Result<Path, crate::memory::MemoryError> {
1101 let additional = trail
1102 .len()
1103 .checked_add(1)
1104 .ok_or(crate::memory::MemoryError::WorkExceeded)?;
1105 self.admit_path(additional)?;
1106 let mut path = self.path.try_copy_in(self.memory())?;
1107 path.push(self.memory(), own_index)?;
1108 for index in trail {
1109 path.push(self.memory(), *index)?;
1110 }
1111 Ok(path)
1112 }
1113
1114 fn admit_path(
1115 &self,
1116 additional: usize,
1117 ) -> core::result::Result<(), crate::memory::MemoryError> {
1118 let work = self.path.copy_work(additional)?;
1119 self.budget()
1120 .local_work(work)
1121 .map_err(|_| crate::memory::MemoryError::WorkExceeded)
1122 }
1123}
1124
1125#[derive(Clone, Copy)]
1126struct Header {
1127 tag: Tag,
1128 length: Length,
1129 start: u64,
1130 len: usize,
1131}
1132
1133fn header_at(
1135 input: &[u8],
1136 encoding: Encoding,
1137 start: u64,
1138 budget: BudgetView<'_>,
1139 execution: &Memory,
1140) -> core::result::Result<Header, (ErrorCode, u64)> {
1141 budget
1144 .work_in(2, execution)
1145 .map_err(|limit| (ErrorCode::LimitExceeded(limit), start))?;
1146 let mut credit = 2;
1147 let mut charge = |amount: u64| {
1148 if amount <= credit {
1149 credit -= amount;
1150 return Ok(());
1151 }
1152 let additional = amount - credit;
1153 credit = 0;
1154 budget
1155 .work_in(additional, execution)
1156 .map_err(ErrorCode::LimitExceeded)
1157 };
1158 let (tag, tag_len) = tag::read_accounted(input, start, &mut charge)?;
1159 let (length, length_len) = length::read_accounted(
1160 &input[tag_len..],
1161 encoding,
1162 start + tag_len as u64,
1163 &mut charge,
1164 )?;
1165 Ok(Header {
1166 tag,
1167 length,
1168 start,
1169 len: tag_len + length_len,
1170 })
1171}
1172
1173#[cfg(test)]
1174mod tests;