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 fn read<'a>(&'a self, data: &'a [u8], base: u64) -> Result<Reader<'a>> {
86 self.read_as(data, base, self.encoding)
87 }
88
89 pub fn read_as<'a>(
97 &'a self,
98 data: &'a [u8],
99 base: u64,
100 encoding: Encoding,
101 ) -> Result<Reader<'a>> {
102 self.read_as_in(data, base, encoding, self.memory())
103 }
104
105 fn read_as_in<'a>(
106 &'a self,
107 data: &'a [u8],
108 base: u64,
109 encoding: Encoding,
110 execution: &Memory,
111 ) -> Result<Reader<'a>> {
112 u64::try_from(data.len())
113 .ok()
114 .and_then(|length| base.checked_add(length))
115 .ok_or_else(|| Error::new(ErrorCode::OffsetTooLarge, base, Path::default()))?;
116
117 Ok(Reader {
118 data,
119 pos: 0,
120 base,
121 depth: 0,
122 next_index: 0,
123 path: Path::default(),
124 encoding,
125 parser: self,
126 execution: execution.clone(),
127 query: None,
128 })
129 }
130
131 pub fn read_nested<'a>(
146 &'a self,
147 data: &'a [u8],
148 base: u64,
149 encoding: Encoding,
150 outer: u32,
151 ) -> Result<Reader<'a>> {
152 self.read_nested_in(data, base, encoding, outer, self.memory())
153 }
154
155 pub fn read_nested_in<'a>(
160 &'a self,
161 data: &'a [u8],
162 base: u64,
163 encoding: Encoding,
164 outer: u32,
165 execution: &Memory,
166 ) -> Result<Reader<'a>> {
167 self.read_depth_in(data, base, encoding, outer.checked_add(1), execution)
168 }
169
170 pub(crate) fn read_source_in<'a>(
171 &'a self,
172 data: &'a [u8],
173 base: u64,
174 encoding: Encoding,
175 depth: u32,
176 execution: &Memory,
177 ) -> Result<Reader<'a>> {
178 self.read_depth_in(data, base, encoding, Some(depth), execution)
179 }
180
181 fn read_depth_in<'a>(
182 &'a self,
183 data: &'a [u8],
184 base: u64,
185 encoding: Encoding,
186 depth: Option<u32>,
187 execution: &Memory,
188 ) -> Result<Reader<'a>> {
189 let mut reader = self.read_as_in(data, base, encoding, execution)?;
190 let depth = depth.ok_or_else(|| {
191 Error::new(
192 ErrorCode::LimitExceeded(Limit::Depth),
193 base,
194 Path::default(),
195 )
196 })?;
197 self.budget
198 .depth(depth)
199 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
200 reader.depth = depth;
201 Ok(reader)
202 }
203
204 pub fn read_nested_query_in<'a>(
212 &'a self,
213 query: &Reader<'a>,
214 data: &'a [u8],
215 base: u64,
216 encoding: Encoding,
217 outer: u32,
218 ) -> Result<Reader<'a>> {
219 self.read_nested_operation_in(
220 data,
221 base,
222 encoding,
223 outer,
224 query.budget().operation(),
225 query.memory(),
226 )
227 }
228
229 pub fn read_query_in<'a>(
239 &'a self,
240 query: &Reader<'a>,
241 data: &'a [u8],
242 base: u64,
243 encoding: Encoding,
244 depth: u32,
245 ) -> Result<Reader<'a>> {
246 self.read_query_budget_in(
247 data,
248 base,
249 encoding,
250 depth,
251 query.budget().operation(),
252 query.memory(),
253 )
254 }
255
256 pub(crate) fn read_nested_operation_in<'a>(
257 &'a self,
258 data: &'a [u8],
259 base: u64,
260 encoding: Encoding,
261 outer: u32,
262 operation: &'a Budget,
263 execution: &Memory,
264 ) -> Result<Reader<'a>> {
265 let depth = nested_depth(outer, base)?;
266 self.read_query_budget_in(data, base, encoding, depth, operation, execution)
267 }
268
269 pub(crate) fn read_query_budget_in<'a>(
270 &'a self,
271 data: &'a [u8],
272 base: u64,
273 encoding: Encoding,
274 depth: u32,
275 operation: &'a Budget,
276 execution: &Memory,
277 ) -> Result<Reader<'a>> {
278 self.read_scoped_source_in(data, base, encoding, depth, Some(operation), execution)
279 }
280
281 pub(crate) fn read_scoped_source_in<'source: 'operation, 'operation>(
282 &'source self,
283 data: &'source [u8],
284 base: u64,
285 encoding: Encoding,
286 depth: u32,
287 operation: Option<&'operation Budget>,
288 execution: &Memory,
289 ) -> Result<ScopedReader<'source, 'operation>> {
290 let Some(operation) = operation else {
291 return self.read_depth_in(data, base, encoding, Some(depth), execution);
292 };
293 let budget = BudgetView::query(&self.budget, operation);
294 budget
295 .depth(depth)
296 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
297 budget
298 .work_in(1, execution)
299 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
300 let reader = self.read_as_in(data, base, encoding, execution)?;
301 Ok(ScopedReader {
302 data: reader.data,
303 pos: reader.pos,
304 base: reader.base,
305 depth,
306 next_index: reader.next_index,
307 path: reader.path,
308 encoding: reader.encoding,
309 parser: reader.parser,
310 execution: reader.execution,
311 query: Some(operation),
312 })
313 }
314}
315
316fn nested_depth(outer: u32, base: u64) -> Result<u32> {
317 outer.checked_add(1).ok_or_else(|| {
318 Error::new(
319 ErrorCode::LimitExceeded(Limit::Depth),
320 base,
321 Path::default(),
322 )
323 })
324}
325
326#[derive(Debug, Clone, Copy, PartialEq, Eq)]
328pub struct Span {
329 pub start: u64,
331 pub length: u64,
333}
334
335impl Span {
336 #[must_use]
342 pub fn end(self) -> u64 {
343 self.start + self.length
344 }
345}
346
347#[derive(Debug, Clone, Copy)]
349pub struct Element<'a> {
350 tag: Tag,
351 contents: &'a [u8],
352 bytes: &'a [u8],
353 contents_span: Span,
354 whole: Span,
355 indefinite: bool,
356 index: u32,
357}
358
359impl<'a> Element<'a> {
360 #[must_use]
362 pub fn tag(self) -> Tag {
363 self.tag
364 }
365
366 #[must_use]
371 pub fn contents(self) -> &'a [u8] {
372 self.contents
373 }
374
375 #[must_use]
384 pub fn as_bytes(self) -> &'a [u8] {
385 self.bytes
386 }
387
388 #[must_use]
390 pub fn contents_span(self) -> Span {
391 self.contents_span
392 }
393
394 #[must_use]
399 pub fn span(self) -> Span {
400 self.whole
401 }
402
403 #[must_use]
405 pub fn is_indefinite(self) -> bool {
406 self.indefinite
407 }
408
409 #[must_use]
411 pub fn index(self) -> u32 {
412 self.index
413 }
414}
415
416#[derive(Debug)]
422pub struct ScopedReader<'a: 'operation, 'operation> {
423 data: &'a [u8],
424 pos: usize,
425 base: u64,
426 depth: u32,
427 next_index: u32,
428 path: Path,
429 encoding: Encoding,
430 parser: &'a Parser,
431 execution: Memory,
432 query: Option<&'operation Budget>,
433}
434
435pub type Reader<'a> = ScopedReader<'a, 'a>;
439
440impl<'a: 'operation, 'operation> ScopedReader<'a, 'operation> {
441 #[must_use]
443 pub fn memory(&self) -> &Memory {
444 &self.execution
445 }
446
447 #[must_use]
467 pub fn execution(&self) -> crate::memory::Execution<'_> {
468 crate::memory::Execution::new(self.memory(), self.budget())
469 }
470
471 #[must_use]
477 pub fn execution_in<'work>(&self, memory: &'work Memory) -> crate::memory::Execution<'work>
478 where
479 'a: 'work,
480 'operation: 'work,
481 {
482 crate::memory::Execution::new(memory, self.budget())
483 }
484
485 #[must_use]
494 pub fn execution_query<'query>(
495 &self,
496 query: &'query Reader<'_>,
497 ) -> crate::memory::Execution<'query>
498 where
499 'a: 'query,
500 {
501 crate::memory::Execution::new(
502 query.memory(),
503 BudgetView::query(&self.parser.budget, query.budget().operation()),
504 )
505 }
506
507 #[must_use]
511 pub fn with_execution(mut self, execution: &Memory) -> Self {
512 self.execution = execution.clone();
513 self
514 }
515
516 pub fn with_query<'query>(self, query: &Reader<'query>) -> Result<Reader<'query>>
521 where
522 'a: 'query,
523 {
524 let operation = query.budget().operation();
525 let budget = BudgetView::query(&self.parser.budget, operation);
526 budget.depth(self.depth).map_err(|limit| {
527 Error::new(
528 ErrorCode::LimitExceeded(limit),
529 self.offset(),
530 Path::default(),
531 )
532 })?;
533 budget.work_in(1, query.memory()).map_err(|limit| {
534 Error::new(
535 ErrorCode::LimitExceeded(limit),
536 self.offset(),
537 Path::default(),
538 )
539 })?;
540 Ok(ScopedReader {
541 data: self.data,
542 pos: self.pos,
543 base: self.base,
544 depth: self.depth,
545 next_index: self.next_index,
546 path: self.path,
547 encoding: self.encoding,
548 parser: self.parser,
549 execution: query.memory().clone(),
550 query: Some(operation),
551 })
552 }
553
554 pub fn try_clone(&self) -> Result<Self> {
556 self.admit_path(0)
557 .map_err(|reason| Error::resource(reason, self.offset()))?;
558 Ok(Self {
559 data: self.data,
560 pos: self.pos,
561 base: self.base,
562 depth: self.depth,
563 next_index: self.next_index,
564 path: self
565 .path
566 .try_copy_in(self.memory())
567 .map_err(|reason| Error::resource(reason, self.offset()))?,
568 encoding: self.encoding,
569 parser: self.parser,
570 execution: self.execution.clone(),
571 query: self.query,
572 })
573 }
574 #[must_use]
576 pub fn is_empty(&self) -> bool {
577 self.pos >= self.data.len()
578 }
579
580 #[must_use]
584 pub fn parser(&self) -> &'a Parser {
585 self.parser
586 }
587
588 fn budget(&self) -> BudgetView<'operation> {
590 match self.query {
591 Some(operation) => BudgetView::query(&self.parser.budget, operation),
592 None => BudgetView::root(&self.parser.budget),
593 }
594 }
595
596 pub fn charge(&self, amount: u64) -> Result<()> {
603 self.budget()
604 .work_in(amount, self.memory())
605 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), self.offset()))
606 }
607
608 #[must_use]
612 pub fn depth(&self) -> u32 {
613 self.depth
614 }
615
616 #[must_use]
621 pub fn offset(&self) -> u64 {
622 self.base + self.pos as u64
623 }
624
625 #[must_use]
627 pub fn remaining(&self) -> &'a [u8] {
628 &self.data[self.pos.min(self.data.len())..]
629 }
630
631 #[must_use]
633 pub fn path(&self) -> &Path {
634 &self.path
635 }
636
637 #[must_use]
640 pub fn encoding(&self) -> Encoding {
641 self.encoding
642 }
643
644 pub fn reread(&self, element: &Element<'a>, encoding: Encoding) -> Result<Self> {
655 self.admit_path(0)
656 .map_err(|reason| Error::resource(reason, element.whole.start))?;
657 Ok(Self {
658 data: element.bytes,
659 pos: 0,
660 base: element.whole.start,
661 depth: self.depth,
662 next_index: 0,
663 path: self
664 .path
665 .try_copy_in(self.memory())
666 .map_err(|reason| Error::resource(reason, element.whole.start))?,
667 encoding,
668 parser: self.parser,
669 execution: self.execution.clone(),
670 query: self.query,
671 })
672 }
673
674 pub fn next_element(&mut self) -> Result<Option<Element<'a>>> {
676 if self.is_empty() {
677 return Ok(None);
678 }
679
680 let header = self.read_header()?;
681
682 if header.tag.is_end_of_contents() {
686 return Err(self.fail_at(ErrorCode::MalformedEndOfContents, header.start));
687 }
688
689 self.finish(header).map(Some)
690 }
691
692 pub fn expect(&mut self, tag: Tag) -> Result<Element<'a>> {
694 let offset = self.offset();
695 match self.next_element()? {
696 Some(element) if element.tag == tag => Ok(element),
697 Some(element) => Err(self.fail_under(ErrorCode::UnexpectedTag, &element)),
702 None => Err(self.fail_at(ErrorCode::UnexpectedEnd, offset)),
703 }
704 }
705
706 pub fn skip(&mut self) -> Result<bool> {
712 Ok(self.next_element()?.is_some())
713 }
714
715 pub fn enter(&self, element: &Element<'a>) -> Result<Self> {
722 if !element.tag.is_constructed() {
723 return Err(self.fail_under(ErrorCode::WrongConstruction, element));
724 }
725
726 let depth = self.depth.checked_add(1).ok_or_else(|| {
729 self.fail_under_at(
730 ErrorCode::LimitExceeded(Limit::Depth),
731 element,
732 element.contents_span.start,
733 )
734 })?;
735 self.budget().depth(depth).map_err(|limit| {
736 self.fail_under_at(
737 ErrorCode::LimitExceeded(limit),
738 element,
739 element.contents_span.start,
740 )
741 })?;
742 self.admit_path(1)
743 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
744 let mut path = self
745 .path
746 .try_copy_in(self.memory())
747 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
748 path.push(self.memory(), element.index)
749 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
750
751 Ok(Self {
752 data: element.contents,
753 pos: 0,
754 base: element.contents_span.start,
755 depth,
756 next_index: 0,
757 path,
758 encoding: self.encoding,
759 parser: self.parser,
760 execution: self.execution.clone(),
761 query: self.query,
762 })
763 }
764
765 pub fn oid(&self, element: &Element<'a>) -> Result<Oid<'a>> {
767 self.primitive(element)?;
768 self.budget()
772 .work_in(element.contents.len() as u64, self.memory())
773 .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
774 value::oid(element.contents).map_err(|code| self.fail_under(code, element))
775 }
776
777 pub fn integer(&self, element: &Element<'a>) -> Result<Integer<'a>> {
779 self.primitive(element)?;
780 value::integer(element.contents).map_err(|code| self.fail_under(code, element))
781 }
782
783 pub fn bit_string(&self, element: &Element<'a>) -> Result<BitString<'a>> {
790 self.primitive(element)?;
791 value::bit_string(element.contents, self.encoding)
792 .map_err(|code| self.fail_under(code, element))
793 }
794
795 pub fn boolean(&self, element: &Element<'a>) -> Result<bool> {
797 self.primitive(element)?;
798 value::boolean(element.contents, self.encoding)
799 .map_err(|code| self.fail_under(code, element))
800 }
801
802 pub fn null(&self, element: &Element<'a>) -> Result<()> {
804 self.primitive(element)?;
805 value::null(element.contents).map_err(|code| self.fail_under(code, element))
806 }
807
808 pub fn real(&self, element: &Element<'a>) -> Result<()> {
815 self.primitive(element)?;
816 self.budget()
820 .work_in(element.contents.len() as u64, self.memory())
821 .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
822 value::real(element.contents, self.encoding).map_err(|code| self.fail_under(code, element))
823 }
824
825 pub fn read_oid(&mut self) -> Result<Oid<'a>> {
827 let element = self.expect(Tag::primitive(universal::OID))?;
828 self.oid(&element)
829 }
830
831 pub fn read_integer(&mut self) -> Result<Integer<'a>> {
833 let element = self.expect(Tag::primitive(universal::INTEGER))?;
834 self.integer(&element)
835 }
836
837 pub fn read_bit_string(&mut self) -> Result<BitString<'a>> {
839 let element = self.expect(Tag::primitive(universal::BIT_STRING))?;
840 self.bit_string(&element)
841 }
842
843 pub fn read_boolean(&mut self) -> Result<bool> {
845 let element = self.expect(Tag::primitive(universal::BOOLEAN))?;
846 self.boolean(&element)
847 }
848
849 fn primitive(&self, element: &Element<'a>) -> Result<()> {
850 if element.tag.is_constructed() {
851 return Err(self.fail_under(ErrorCode::WrongConstruction, element));
852 }
853 Ok(())
854 }
855
856 #[must_use]
858 pub fn fail_under(&self, code: ErrorCode, element: &Element<'a>) -> Error {
859 self.fail_under_at(code, element, element.whole.start)
860 }
861
862 fn fail_under_at(&self, code: ErrorCode, element: &Element<'a>, offset: u64) -> Error {
863 match self.path_into(element.index, &[]) {
864 Ok(path) => Error::new(code, offset, path),
865 Err(reason) => Error::resource(reason, offset),
866 }
867 }
868
869 fn fail_at(&self, code: ErrorCode, offset: u64) -> Error {
870 if let Err(reason) = self.admit_path(0) {
871 return Error::resource(reason, offset);
872 }
873 match self.path.try_copy_in(self.memory()) {
874 Ok(path) => Error::new(code, offset, path),
875 Err(reason) => Error::resource(reason, offset),
876 }
877 }
878
879 fn read_header(&mut self) -> Result<Header> {
880 let start = self.offset();
881 self.budget()
882 .element()
883 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), start))?;
884
885 let rest = &self.data[self.pos..];
886 header_at(rest, self.encoding, start, self.budget(), self.memory())
887 .map_err(|(code, at)| self.fail_at(code, at))
888 }
889
890 fn finish(&mut self, header: Header) -> Result<Element<'a>> {
891 let contents_at = self.pos + header.len;
892 let contents_start = header.start + header.len as u64;
893
894 let (contents_len, total_len, indefinite) = match header.length {
895 Length::Definite(length) => {
896 self.budget()
897 .length(length)
898 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
899
900 let length = usize::try_from(length)
901 .map_err(|_| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
902
903 let end = contents_at
904 .checked_add(length)
905 .ok_or_else(|| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
906
907 if end > self.data.len() {
908 return Err(self.fail_at(ErrorCode::UnexpectedEnd, header.start));
909 }
910
911 (length, header.len + length, false)
912 }
913 Length::Indefinite => {
914 if !header.tag.is_constructed() {
915 return Err(self.fail_at(ErrorCode::WrongConstruction, header.start));
916 }
917 let contents_len =
918 self.scan_to_end_of_contents(contents_at, contents_start, self.next_index)?;
919
920 self.budget()
925 .length(contents_len as u64)
926 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
927
928 (contents_len, header.len + contents_len + 2, true)
931 }
932 };
933
934 let contents = &self.data[contents_at..contents_at + contents_len];
935 let bytes = &self.data[self.pos..self.pos + total_len];
938 let index = self.next_index;
939
940 self.pos += total_len;
941 self.next_index = self
942 .next_index
943 .checked_add(1)
944 .ok_or_else(|| self.fail_at(ErrorCode::LimitExceeded(Limit::Elements), header.start))?;
945
946 Ok(Element {
947 tag: header.tag,
948 contents,
949 bytes,
950 contents_span: Span {
951 start: contents_start,
952 length: contents_len as u64,
953 },
954 whole: Span {
955 start: header.start,
956 length: total_len as u64,
957 },
958 indefinite,
959 index,
960 })
961 }
962
963 fn scan_to_end_of_contents(
973 &self,
974 from: usize,
975 from_offset: u64,
976 own_index: u32,
977 ) -> Result<usize> {
978 let mut cursor = from;
979 let mut offset = from_offset;
980
981 let mut trail = self.execution().vector::<u32>();
985 let mut index: u32 = 0;
986
987 let fail = |code: ErrorCode, at: u64, trail: &[u32]| match self.path_into(own_index, trail)
991 {
992 Ok(path) => Error::new(code, at, path),
993 Err(reason) => Error::resource(reason, at),
994 };
995 let spent =
996 |limit: Limit, at: u64, trail: &[u32]| fail(ErrorCode::LimitExceeded(limit), at, trail);
997
998 loop {
999 let depth = u32::try_from(trail.len())
1000 .ok()
1001 .and_then(|nested| self.depth.checked_add(nested))
1002 .and_then(|depth| depth.checked_add(1))
1003 .ok_or_else(|| spent(Limit::Depth, offset, &trail))?;
1004 self.budget()
1005 .depth(depth)
1006 .map_err(|limit| spent(limit, offset, &trail))?;
1007
1008 let rest = self
1009 .data
1010 .get(cursor..)
1011 .filter(|rest| !rest.is_empty())
1012 .ok_or_else(|| fail(ErrorCode::UnterminatedContents, from_offset, &trail))?;
1013
1014 let header = header_at(rest, self.encoding, offset, self.budget(), self.memory())
1015 .map_err(|(code, at)| fail(code, at, &trail))?;
1016 let inner_tag = header.tag;
1017 let inner_length = header.length;
1018 let header_len = header.len;
1019
1020 if inner_tag.is_end_of_contents() {
1021 if header_len != 2 || !matches!(inner_length, Length::Definite(0)) {
1026 return Err(fail(ErrorCode::MalformedEndOfContents, offset, &trail));
1027 }
1028 match trail.pop() {
1029 None => return Ok(cursor - from),
1031 Some(outer) => {
1033 index = outer
1034 .checked_add(1)
1035 .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
1036 }
1037 }
1038 cursor += header_len;
1039 offset += header_len as u64;
1040 continue;
1041 }
1042
1043 let step = match inner_length {
1044 Length::Indefinite => {
1045 if !inner_tag.is_constructed() {
1046 return Err(fail(ErrorCode::WrongConstruction, offset, &trail));
1047 }
1048 trail
1051 .try_push(index)
1052 .map_err(|reason| Error::resource(reason, offset))?;
1053 index = 0;
1054 header_len
1055 }
1056 Length::Definite(length) => {
1057 self.budget()
1058 .length(length)
1059 .map_err(|limit| spent(limit, offset, &trail))?;
1060 let length = usize::try_from(length)
1061 .map_err(|_| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
1062 index = index
1063 .checked_add(1)
1064 .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
1065 header_len
1066 .checked_add(length)
1067 .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?
1068 }
1069 };
1070
1071 cursor = cursor
1072 .checked_add(step)
1073 .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
1074 if cursor > self.data.len() {
1075 return Err(fail(ErrorCode::UnexpectedEnd, offset, &trail));
1076 }
1077 offset += step as u64;
1078 }
1079 }
1080
1081 fn path_into(
1085 &self,
1086 own_index: u32,
1087 trail: &[u32],
1088 ) -> core::result::Result<Path, crate::memory::MemoryError> {
1089 let additional = trail
1090 .len()
1091 .checked_add(1)
1092 .ok_or(crate::memory::MemoryError::WorkExceeded)?;
1093 self.admit_path(additional)?;
1094 let mut path = self.path.try_copy_in(self.memory())?;
1095 path.push(self.memory(), own_index)?;
1096 for index in trail {
1097 path.push(self.memory(), *index)?;
1098 }
1099 Ok(path)
1100 }
1101
1102 fn admit_path(
1103 &self,
1104 additional: usize,
1105 ) -> core::result::Result<(), crate::memory::MemoryError> {
1106 let work = self.path.copy_work(additional)?;
1107 self.budget()
1108 .local_work(work)
1109 .map_err(|_| crate::memory::MemoryError::WorkExceeded)
1110 }
1111}
1112
1113#[derive(Clone, Copy)]
1114struct Header {
1115 tag: Tag,
1116 length: Length,
1117 start: u64,
1118 len: usize,
1119}
1120
1121fn header_at(
1123 input: &[u8],
1124 encoding: Encoding,
1125 start: u64,
1126 budget: BudgetView<'_>,
1127 execution: &Memory,
1128) -> core::result::Result<Header, (ErrorCode, u64)> {
1129 budget
1132 .work_in(2, execution)
1133 .map_err(|limit| (ErrorCode::LimitExceeded(limit), start))?;
1134 let mut credit = 2;
1135 let mut charge = |amount: u64| {
1136 if amount <= credit {
1137 credit -= amount;
1138 return Ok(());
1139 }
1140 let additional = amount - credit;
1141 credit = 0;
1142 budget
1143 .work_in(additional, execution)
1144 .map_err(ErrorCode::LimitExceeded)
1145 };
1146 let (tag, tag_len) = tag::read_accounted(input, start, &mut charge)?;
1147 let (length, length_len) = length::read_accounted(
1148 &input[tag_len..],
1149 encoding,
1150 start + tag_len as u64,
1151 &mut charge,
1152 )?;
1153 Ok(Header {
1154 tag,
1155 length,
1156 start,
1157 len: tag_len + length_len,
1158 })
1159}
1160
1161#[cfg(test)]
1162mod tests;