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 fn read<'a>(&'a self, data: &'a [u8], base: u64) -> Result<Reader<'a>> {
94 self.read_as(data, base, self.encoding)
95 }
96
97 pub fn read_as<'a>(
105 &'a self,
106 data: &'a [u8],
107 base: u64,
108 encoding: Encoding,
109 ) -> Result<Reader<'a>> {
110 self.read_as_in(data, base, encoding, self.memory())
111 }
112
113 fn read_as_in<'a>(
114 &'a self,
115 data: &'a [u8],
116 base: u64,
117 encoding: Encoding,
118 execution: &Memory,
119 ) -> Result<Reader<'a>> {
120 u64::try_from(data.len())
121 .ok()
122 .and_then(|length| base.checked_add(length))
123 .ok_or_else(|| Error::new(ErrorCode::OffsetTooLarge, base, Path::default()))?;
124
125 Ok(Reader {
126 data,
127 pos: 0,
128 base,
129 depth: 0,
130 next_index: 0,
131 path: Path::default(),
132 encoding,
133 parser: self,
134 execution: execution.clone(),
135 query: None,
136 })
137 }
138
139 pub fn read_nested<'a>(
154 &'a self,
155 data: &'a [u8],
156 base: u64,
157 encoding: Encoding,
158 outer: u32,
159 ) -> Result<Reader<'a>> {
160 self.read_nested_in(data, base, encoding, outer, self.memory())
161 }
162
163 pub fn read_nested_in<'a>(
168 &'a self,
169 data: &'a [u8],
170 base: u64,
171 encoding: Encoding,
172 outer: u32,
173 execution: &Memory,
174 ) -> Result<Reader<'a>> {
175 self.read_depth_in(data, base, encoding, outer.checked_add(1), execution)
176 }
177
178 pub(crate) fn read_source_in<'a>(
179 &'a self,
180 data: &'a [u8],
181 base: u64,
182 encoding: Encoding,
183 depth: u32,
184 execution: &Memory,
185 ) -> Result<Reader<'a>> {
186 self.read_depth_in(data, base, encoding, Some(depth), execution)
187 }
188
189 fn read_depth_in<'a>(
190 &'a self,
191 data: &'a [u8],
192 base: u64,
193 encoding: Encoding,
194 depth: Option<u32>,
195 execution: &Memory,
196 ) -> Result<Reader<'a>> {
197 let mut reader = self.read_as_in(data, base, encoding, execution)?;
198 let depth = depth.ok_or_else(|| {
199 Error::new(
200 ErrorCode::LimitExceeded(Limit::Depth),
201 base,
202 Path::default(),
203 )
204 })?;
205 self.budget
206 .depth(depth)
207 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
208 reader.depth = depth;
209 Ok(reader)
210 }
211
212 pub fn read_nested_query_in<'a>(
220 &'a self,
221 query: &Reader<'a>,
222 data: &'a [u8],
223 base: u64,
224 encoding: Encoding,
225 outer: u32,
226 ) -> Result<Reader<'a>> {
227 self.read_nested_operation_in(
228 data,
229 base,
230 encoding,
231 outer,
232 query.budget().operation(),
233 query.memory(),
234 )
235 }
236
237 pub fn read_query_in<'a>(
247 &'a self,
248 query: &Reader<'a>,
249 data: &'a [u8],
250 base: u64,
251 encoding: Encoding,
252 depth: u32,
253 ) -> Result<Reader<'a>> {
254 self.read_query_budget_in(
255 data,
256 base,
257 encoding,
258 depth,
259 query.budget().operation(),
260 query.memory(),
261 )
262 }
263
264 pub(crate) fn read_nested_operation_in<'a>(
265 &'a self,
266 data: &'a [u8],
267 base: u64,
268 encoding: Encoding,
269 outer: u32,
270 operation: &'a Budget,
271 execution: &Memory,
272 ) -> Result<Reader<'a>> {
273 let depth = nested_depth(outer, base)?;
274 self.read_query_budget_in(data, base, encoding, depth, operation, execution)
275 }
276
277 pub(crate) fn read_query_budget_in<'a>(
278 &'a self,
279 data: &'a [u8],
280 base: u64,
281 encoding: Encoding,
282 depth: u32,
283 operation: &'a Budget,
284 execution: &Memory,
285 ) -> Result<Reader<'a>> {
286 self.read_scoped_source_in(data, base, encoding, depth, Some(operation), execution)
287 }
288
289 pub(crate) fn read_scoped_source_in<'source: 'operation, 'operation>(
290 &'source self,
291 data: &'source [u8],
292 base: u64,
293 encoding: Encoding,
294 depth: u32,
295 operation: Option<&'operation Budget>,
296 execution: &Memory,
297 ) -> Result<ScopedReader<'source, 'operation>> {
298 let Some(operation) = operation else {
299 return self.read_depth_in(data, base, encoding, Some(depth), execution);
300 };
301 let budget = BudgetView::query(&self.budget, operation);
302 budget
303 .depth(depth)
304 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
305 budget
306 .work_in(1, execution)
307 .map_err(|limit| Error::new(ErrorCode::LimitExceeded(limit), base, Path::default()))?;
308 let reader = self.read_as_in(data, base, encoding, execution)?;
309 Ok(ScopedReader {
310 data: reader.data,
311 pos: reader.pos,
312 base: reader.base,
313 depth,
314 next_index: reader.next_index,
315 path: reader.path,
316 encoding: reader.encoding,
317 parser: reader.parser,
318 execution: reader.execution,
319 query: Some(operation),
320 })
321 }
322}
323
324fn nested_depth(outer: u32, base: u64) -> Result<u32> {
325 outer.checked_add(1).ok_or_else(|| {
326 Error::new(
327 ErrorCode::LimitExceeded(Limit::Depth),
328 base,
329 Path::default(),
330 )
331 })
332}
333
334#[derive(Debug, Clone, Copy, PartialEq, Eq)]
336pub struct Span {
337 pub start: u64,
339 pub length: u64,
341}
342
343impl Span {
344 #[must_use]
350 pub fn end(self) -> u64 {
351 self.start + self.length
352 }
353}
354
355#[derive(Debug, Clone, Copy)]
357pub struct Element<'a> {
358 tag: Tag,
359 contents: &'a [u8],
360 bytes: &'a [u8],
361 contents_span: Span,
362 whole: Span,
363 indefinite: bool,
364 index: u32,
365}
366
367impl<'a> Element<'a> {
368 #[must_use]
370 pub fn tag(self) -> Tag {
371 self.tag
372 }
373
374 #[must_use]
379 pub fn contents(self) -> &'a [u8] {
380 self.contents
381 }
382
383 #[must_use]
392 pub fn as_bytes(self) -> &'a [u8] {
393 self.bytes
394 }
395
396 #[must_use]
398 pub fn contents_span(self) -> Span {
399 self.contents_span
400 }
401
402 #[must_use]
407 pub fn span(self) -> Span {
408 self.whole
409 }
410
411 #[must_use]
413 pub fn is_indefinite(self) -> bool {
414 self.indefinite
415 }
416
417 #[must_use]
419 pub fn index(self) -> u32 {
420 self.index
421 }
422}
423
424#[derive(Debug)]
430pub struct ScopedReader<'a: 'operation, 'operation> {
431 data: &'a [u8],
432 pos: usize,
433 base: u64,
434 depth: u32,
435 next_index: u32,
436 path: Path,
437 encoding: Encoding,
438 parser: &'a Parser,
439 execution: Memory,
440 query: Option<&'operation Budget>,
441}
442
443pub type Reader<'a> = ScopedReader<'a, 'a>;
447
448impl<'a: 'operation, 'operation> ScopedReader<'a, 'operation> {
449 #[must_use]
451 pub fn memory(&self) -> &Memory {
452 &self.execution
453 }
454
455 #[must_use]
475 pub fn execution(&self) -> crate::memory::Execution<'_> {
476 crate::memory::Execution::new(self.memory(), self.budget())
477 }
478
479 #[must_use]
485 pub fn execution_in<'work>(&self, memory: &'work Memory) -> crate::memory::Execution<'work>
486 where
487 'a: 'work,
488 'operation: 'work,
489 {
490 crate::memory::Execution::new(memory, self.budget())
491 }
492
493 #[must_use]
502 pub fn execution_query<'query>(
503 &self,
504 query: &'query Reader<'_>,
505 ) -> crate::memory::Execution<'query>
506 where
507 'a: 'query,
508 {
509 crate::memory::Execution::new(
510 query.memory(),
511 BudgetView::query(&self.parser.budget, query.budget().operation()),
512 )
513 }
514
515 #[must_use]
519 pub fn with_execution(mut self, execution: &Memory) -> Self {
520 self.execution = execution.clone();
521 self
522 }
523
524 pub fn with_query<'query>(self, query: &Reader<'query>) -> Result<Reader<'query>>
529 where
530 'a: 'query,
531 {
532 let operation = query.budget().operation();
533 let budget = BudgetView::query(&self.parser.budget, operation);
534 budget.depth(self.depth).map_err(|limit| {
535 Error::new(
536 ErrorCode::LimitExceeded(limit),
537 self.offset(),
538 Path::default(),
539 )
540 })?;
541 budget.work_in(1, query.memory()).map_err(|limit| {
542 Error::new(
543 ErrorCode::LimitExceeded(limit),
544 self.offset(),
545 Path::default(),
546 )
547 })?;
548 Ok(ScopedReader {
549 data: self.data,
550 pos: self.pos,
551 base: self.base,
552 depth: self.depth,
553 next_index: self.next_index,
554 path: self.path,
555 encoding: self.encoding,
556 parser: self.parser,
557 execution: query.memory().clone(),
558 query: Some(operation),
559 })
560 }
561
562 pub fn try_clone(&self) -> Result<Self> {
564 self.admit_path(0)
565 .map_err(|reason| Error::resource(reason, self.offset()))?;
566 Ok(Self {
567 data: self.data,
568 pos: self.pos,
569 base: self.base,
570 depth: self.depth,
571 next_index: self.next_index,
572 path: self
573 .path
574 .try_copy_in(self.memory())
575 .map_err(|reason| Error::resource(reason, self.offset()))?,
576 encoding: self.encoding,
577 parser: self.parser,
578 execution: self.execution.clone(),
579 query: self.query,
580 })
581 }
582 #[must_use]
584 pub fn is_empty(&self) -> bool {
585 self.pos >= self.data.len()
586 }
587
588 #[must_use]
592 pub fn parser(&self) -> &'a Parser {
593 self.parser
594 }
595
596 fn budget(&self) -> BudgetView<'operation> {
598 match self.query {
599 Some(operation) => BudgetView::query(&self.parser.budget, operation),
600 None => BudgetView::root(&self.parser.budget),
601 }
602 }
603
604 pub fn charge(&self, amount: u64) -> Result<()> {
611 self.budget()
612 .work_in(amount, self.memory())
613 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), self.offset()))
614 }
615
616 #[must_use]
620 pub fn depth(&self) -> u32 {
621 self.depth
622 }
623
624 #[must_use]
629 pub fn offset(&self) -> u64 {
630 self.base + self.pos as u64
631 }
632
633 #[must_use]
635 pub fn remaining(&self) -> &'a [u8] {
636 &self.data[self.pos.min(self.data.len())..]
637 }
638
639 #[must_use]
641 pub fn path(&self) -> &Path {
642 &self.path
643 }
644
645 #[must_use]
648 pub fn encoding(&self) -> Encoding {
649 self.encoding
650 }
651
652 pub fn reread(&self, element: &Element<'a>, encoding: Encoding) -> Result<Self> {
663 self.admit_path(0)
664 .map_err(|reason| Error::resource(reason, element.whole.start))?;
665 Ok(Self {
666 data: element.bytes,
667 pos: 0,
668 base: element.whole.start,
669 depth: self.depth,
670 next_index: 0,
671 path: self
672 .path
673 .try_copy_in(self.memory())
674 .map_err(|reason| Error::resource(reason, element.whole.start))?,
675 encoding,
676 parser: self.parser,
677 execution: self.execution.clone(),
678 query: self.query,
679 })
680 }
681
682 pub fn next_element(&mut self) -> Result<Option<Element<'a>>> {
684 if self.is_empty() {
685 return Ok(None);
686 }
687
688 let header = self.read_header()?;
689
690 if header.tag.is_end_of_contents() {
694 return Err(self.fail_at(ErrorCode::MalformedEndOfContents, header.start));
695 }
696
697 self.finish(header).map(Some)
698 }
699
700 pub fn expect(&mut self, tag: Tag) -> Result<Element<'a>> {
702 let offset = self.offset();
703 match self.next_element()? {
704 Some(element) if element.tag == tag => Ok(element),
705 Some(element) => Err(self.fail_under(ErrorCode::UnexpectedTag, &element)),
710 None => Err(self.fail_at(ErrorCode::UnexpectedEnd, offset)),
711 }
712 }
713
714 pub fn skip(&mut self) -> Result<bool> {
720 Ok(self.next_element()?.is_some())
721 }
722
723 pub fn enter(&self, element: &Element<'a>) -> Result<Self> {
730 if !element.tag.is_constructed() {
731 return Err(self.fail_under(ErrorCode::WrongConstruction, element));
732 }
733
734 let depth = self.depth.checked_add(1).ok_or_else(|| {
737 self.fail_under_at(
738 ErrorCode::LimitExceeded(Limit::Depth),
739 element,
740 element.contents_span.start,
741 )
742 })?;
743 self.budget().depth(depth).map_err(|limit| {
744 self.fail_under_at(
745 ErrorCode::LimitExceeded(limit),
746 element,
747 element.contents_span.start,
748 )
749 })?;
750 self.admit_path(1)
751 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
752 let mut path = self
753 .path
754 .try_copy_in(self.memory())
755 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
756 path.push(self.memory(), element.index)
757 .map_err(|reason| Error::resource(reason, element.contents_span.start))?;
758
759 Ok(Self {
760 data: element.contents,
761 pos: 0,
762 base: element.contents_span.start,
763 depth,
764 next_index: 0,
765 path,
766 encoding: self.encoding,
767 parser: self.parser,
768 execution: self.execution.clone(),
769 query: self.query,
770 })
771 }
772
773 pub fn oid(&self, element: &Element<'a>) -> Result<Oid<'a>> {
775 self.primitive(element)?;
776 self.budget()
780 .work_in(element.contents.len() as u64, self.memory())
781 .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
782 value::oid(element.contents).map_err(|code| self.fail_under(code, element))
783 }
784
785 pub fn integer(&self, element: &Element<'a>) -> Result<Integer<'a>> {
787 self.primitive(element)?;
788 value::integer(element.contents).map_err(|code| self.fail_under(code, element))
789 }
790
791 pub fn bit_string(&self, element: &Element<'a>) -> Result<BitString<'a>> {
798 self.primitive(element)?;
799 value::bit_string(element.contents, self.encoding)
800 .map_err(|code| self.fail_under(code, element))
801 }
802
803 pub fn boolean(&self, element: &Element<'a>) -> Result<bool> {
805 self.primitive(element)?;
806 value::boolean(element.contents, self.encoding)
807 .map_err(|code| self.fail_under(code, element))
808 }
809
810 pub fn null(&self, element: &Element<'a>) -> Result<()> {
812 self.primitive(element)?;
813 value::null(element.contents).map_err(|code| self.fail_under(code, element))
814 }
815
816 pub fn real(&self, element: &Element<'a>) -> Result<()> {
823 self.primitive(element)?;
824 self.budget()
828 .work_in(element.contents.len() as u64, self.memory())
829 .map_err(|limit| self.fail_under(ErrorCode::LimitExceeded(limit), element))?;
830 value::real(element.contents, self.encoding).map_err(|code| self.fail_under(code, element))
831 }
832
833 pub fn read_oid(&mut self) -> Result<Oid<'a>> {
835 let element = self.expect(Tag::primitive(universal::OID))?;
836 self.oid(&element)
837 }
838
839 pub fn read_integer(&mut self) -> Result<Integer<'a>> {
841 let element = self.expect(Tag::primitive(universal::INTEGER))?;
842 self.integer(&element)
843 }
844
845 pub fn read_bit_string(&mut self) -> Result<BitString<'a>> {
847 let element = self.expect(Tag::primitive(universal::BIT_STRING))?;
848 self.bit_string(&element)
849 }
850
851 pub fn read_boolean(&mut self) -> Result<bool> {
853 let element = self.expect(Tag::primitive(universal::BOOLEAN))?;
854 self.boolean(&element)
855 }
856
857 fn primitive(&self, element: &Element<'a>) -> Result<()> {
858 if element.tag.is_constructed() {
859 return Err(self.fail_under(ErrorCode::WrongConstruction, element));
860 }
861 Ok(())
862 }
863
864 #[must_use]
866 pub fn fail_under(&self, code: ErrorCode, element: &Element<'a>) -> Error {
867 self.fail_under_at(code, element, element.whole.start)
868 }
869
870 fn fail_under_at(&self, code: ErrorCode, element: &Element<'a>, offset: u64) -> Error {
871 match self.path_into(element.index, &[]) {
872 Ok(path) => Error::new(code, offset, path),
873 Err(reason) => Error::resource(reason, offset),
874 }
875 }
876
877 fn fail_at(&self, code: ErrorCode, offset: u64) -> Error {
878 if let Err(reason) = self.admit_path(0) {
879 return Error::resource(reason, offset);
880 }
881 match self.path.try_copy_in(self.memory()) {
882 Ok(path) => Error::new(code, offset, path),
883 Err(reason) => Error::resource(reason, offset),
884 }
885 }
886
887 fn read_header(&mut self) -> Result<Header> {
888 let start = self.offset();
889 self.budget()
890 .element()
891 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), start))?;
892
893 let rest = &self.data[self.pos..];
894 header_at(rest, self.encoding, start, self.budget(), self.memory())
895 .map_err(|(code, at)| self.fail_at(code, at))
896 }
897
898 fn finish(&mut self, header: Header) -> Result<Element<'a>> {
899 let contents_at = self.pos + header.len;
900 let contents_start = header.start + header.len as u64;
901
902 let (contents_len, total_len, indefinite) = match header.length {
903 Length::Definite(length) => {
904 self.budget()
905 .length(length)
906 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
907
908 let length = usize::try_from(length)
909 .map_err(|_| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
910
911 let end = contents_at
912 .checked_add(length)
913 .ok_or_else(|| self.fail_at(ErrorCode::LengthTooLarge, header.start))?;
914
915 if end > self.data.len() {
916 return Err(self.fail_at(ErrorCode::UnexpectedEnd, header.start));
917 }
918
919 (length, header.len + length, false)
920 }
921 Length::Indefinite => {
922 if !header.tag.is_constructed() {
923 return Err(self.fail_at(ErrorCode::WrongConstruction, header.start));
924 }
925 let contents_len =
926 self.scan_to_end_of_contents(contents_at, contents_start, self.next_index)?;
927
928 self.budget()
933 .length(contents_len as u64)
934 .map_err(|limit| self.fail_at(ErrorCode::LimitExceeded(limit), header.start))?;
935
936 (contents_len, header.len + contents_len + 2, true)
939 }
940 };
941
942 let contents = &self.data[contents_at..contents_at + contents_len];
943 let bytes = &self.data[self.pos..self.pos + total_len];
946 let index = self.next_index;
947
948 self.pos += total_len;
949 self.next_index = self
950 .next_index
951 .checked_add(1)
952 .ok_or_else(|| self.fail_at(ErrorCode::LimitExceeded(Limit::Elements), header.start))?;
953
954 Ok(Element {
955 tag: header.tag,
956 contents,
957 bytes,
958 contents_span: Span {
959 start: contents_start,
960 length: contents_len as u64,
961 },
962 whole: Span {
963 start: header.start,
964 length: total_len as u64,
965 },
966 indefinite,
967 index,
968 })
969 }
970
971 fn scan_to_end_of_contents(
981 &self,
982 from: usize,
983 from_offset: u64,
984 own_index: u32,
985 ) -> Result<usize> {
986 let mut cursor = from;
987 let mut offset = from_offset;
988
989 let mut trail = self.execution().vector::<u32>();
993 let mut index: u32 = 0;
994
995 let fail = |code: ErrorCode, at: u64, trail: &[u32]| match self.path_into(own_index, trail)
999 {
1000 Ok(path) => Error::new(code, at, path),
1001 Err(reason) => Error::resource(reason, at),
1002 };
1003 let spent =
1004 |limit: Limit, at: u64, trail: &[u32]| fail(ErrorCode::LimitExceeded(limit), at, trail);
1005
1006 loop {
1007 let depth = u32::try_from(trail.len())
1008 .ok()
1009 .and_then(|nested| self.depth.checked_add(nested))
1010 .and_then(|depth| depth.checked_add(1))
1011 .ok_or_else(|| spent(Limit::Depth, offset, &trail))?;
1012 self.budget()
1013 .depth(depth)
1014 .map_err(|limit| spent(limit, offset, &trail))?;
1015
1016 let rest = self
1017 .data
1018 .get(cursor..)
1019 .filter(|rest| !rest.is_empty())
1020 .ok_or_else(|| fail(ErrorCode::UnterminatedContents, from_offset, &trail))?;
1021
1022 let header = header_at(rest, self.encoding, offset, self.budget(), self.memory())
1023 .map_err(|(code, at)| fail(code, at, &trail))?;
1024 let inner_tag = header.tag;
1025 let inner_length = header.length;
1026 let header_len = header.len;
1027
1028 if inner_tag.is_end_of_contents() {
1029 if header_len != 2 || !matches!(inner_length, Length::Definite(0)) {
1034 return Err(fail(ErrorCode::MalformedEndOfContents, offset, &trail));
1035 }
1036 match trail.pop() {
1037 None => return Ok(cursor - from),
1039 Some(outer) => {
1041 index = outer
1042 .checked_add(1)
1043 .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
1044 }
1045 }
1046 cursor += header_len;
1047 offset += header_len as u64;
1048 continue;
1049 }
1050
1051 let step = match inner_length {
1052 Length::Indefinite => {
1053 if !inner_tag.is_constructed() {
1054 return Err(fail(ErrorCode::WrongConstruction, offset, &trail));
1055 }
1056 trail
1059 .try_push(index)
1060 .map_err(|reason| Error::resource(reason, offset))?;
1061 index = 0;
1062 header_len
1063 }
1064 Length::Definite(length) => {
1065 self.budget()
1066 .length(length)
1067 .map_err(|limit| spent(limit, offset, &trail))?;
1068 let length = usize::try_from(length)
1069 .map_err(|_| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
1070 index = index
1071 .checked_add(1)
1072 .ok_or_else(|| spent(Limit::Elements, offset, &trail))?;
1073 header_len
1074 .checked_add(length)
1075 .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?
1076 }
1077 };
1078
1079 cursor = cursor
1080 .checked_add(step)
1081 .ok_or_else(|| fail(ErrorCode::LengthTooLarge, offset, &trail))?;
1082 if cursor > self.data.len() {
1083 return Err(fail(ErrorCode::UnexpectedEnd, offset, &trail));
1084 }
1085 offset += step as u64;
1086 }
1087 }
1088
1089 fn path_into(
1093 &self,
1094 own_index: u32,
1095 trail: &[u32],
1096 ) -> core::result::Result<Path, crate::memory::MemoryError> {
1097 let additional = trail
1098 .len()
1099 .checked_add(1)
1100 .ok_or(crate::memory::MemoryError::WorkExceeded)?;
1101 self.admit_path(additional)?;
1102 let mut path = self.path.try_copy_in(self.memory())?;
1103 path.push(self.memory(), own_index)?;
1104 for index in trail {
1105 path.push(self.memory(), *index)?;
1106 }
1107 Ok(path)
1108 }
1109
1110 fn admit_path(
1111 &self,
1112 additional: usize,
1113 ) -> core::result::Result<(), crate::memory::MemoryError> {
1114 let work = self.path.copy_work(additional)?;
1115 self.budget()
1116 .local_work(work)
1117 .map_err(|_| crate::memory::MemoryError::WorkExceeded)
1118 }
1119}
1120
1121#[derive(Clone, Copy)]
1122struct Header {
1123 tag: Tag,
1124 length: Length,
1125 start: u64,
1126 len: usize,
1127}
1128
1129fn header_at(
1131 input: &[u8],
1132 encoding: Encoding,
1133 start: u64,
1134 budget: BudgetView<'_>,
1135 execution: &Memory,
1136) -> core::result::Result<Header, (ErrorCode, u64)> {
1137 budget
1140 .work_in(2, execution)
1141 .map_err(|limit| (ErrorCode::LimitExceeded(limit), start))?;
1142 let mut credit = 2;
1143 let mut charge = |amount: u64| {
1144 if amount <= credit {
1145 credit -= amount;
1146 return Ok(());
1147 }
1148 let additional = amount - credit;
1149 credit = 0;
1150 budget
1151 .work_in(additional, execution)
1152 .map_err(ErrorCode::LimitExceeded)
1153 };
1154 let (tag, tag_len) = tag::read_accounted(input, start, &mut charge)?;
1155 let (length, length_len) = length::read_accounted(
1156 &input[tag_len..],
1157 encoding,
1158 start + tag_len as u64,
1159 &mut charge,
1160 )?;
1161 Ok(Header {
1162 tag,
1163 length,
1164 start,
1165 len: tag_len + length_len,
1166 })
1167}
1168
1169#[cfg(test)]
1170mod tests;