1use super::Document;
4use crate::arena::{Arena, Kind, NodeId};
5use crate::error::{Error, ErrorKind, ReadFailure, Syntax};
6use crate::model::{admit, required, unsigned};
7use crate::object::Value;
8use crate::range::{RangeReader, RangeSource};
9use crate::source::Location;
10use crate::stream::Indirect;
11use crate::syntax::Cursor;
12use crate::xref::Target;
13use structured_asn1::{
14 Span,
15 memory::{Memory, OwnedVec, Work},
16};
17
18pub struct Reading<'s, D, G> {
21 pub(crate) value: Value<'s, D, G>,
22 pub(crate) decoded: Option<OwnedVec<u8, Memory>>,
23 pub(crate) stream: Option<Span>,
24 pub(crate) number: u64,
25 pub(crate) generation: u16,
26 pub(crate) revision: usize,
27}
28
29#[expect(
30 clippy::large_enum_variant,
31 reason = "direct values borrow their owner while indirect values transfer their existing funded reading without an additional box"
32)]
33pub(crate) enum ResolvedValue<'a, 's, D, G> {
34 Borrowed {
35 reading: &'a Reading<'s, D, G>,
36 node: NodeId,
37 },
38 Owned(Reading<'s, D, G>),
39}
40impl<'s, D, G> ResolvedValue<'_, 's, D, G> {
41 pub(crate) fn parts(&self) -> (&Reading<'s, D, G>, NodeId) {
42 match self {
43 Self::Borrowed { reading, node } => (reading, *node),
44 Self::Owned(reading) => (reading, reading.value.root),
45 }
46 }
47}
48
49impl<D: Copy + Eq, G: Copy + Eq> Reading<'_, D, G> {
50 #[must_use]
52 pub fn value(&self) -> &Value<'_, D, G> {
53 &self.value
54 }
55
56 #[must_use]
58 pub fn identity(&self) -> (u64, u16) {
59 (self.number, self.generation)
60 }
61
62 #[must_use]
64 pub fn revision(&self) -> usize {
65 self.revision
66 }
67
68 #[must_use]
70 pub fn stream(&self) -> Option<Span> {
71 self.stream
72 }
73}
74
75struct Pending<'s, D, G> {
76 reading: Reading<'s, D, G>,
77 indirect: Indirect,
78}
79
80#[expect(
81 clippy::large_enum_variant,
82 reason = "one funded iterative frame owns its suspended parsing state; per-state boxes would add allocation and rollback boundaries"
83)]
84enum State<'b, 's, D, G> {
85 Start,
86 Length(Pending<'s, D, G>),
87 Member {
88 index: u64,
89 },
90 Controls {
91 controls: super::controls::Controls<'b, 's, D, G>,
92 member: Option<(u64, u64)>,
93 },
94 Reference,
95}
96
97struct Frame<'b, 's, D, G> {
98 number: u64,
99 generation: u16,
100 state: State<'b, 's, D, G>,
101}
102
103struct Completion<'s, D, G> {
104 object: Option<Reading<'s, D, G>>,
105}
106impl<'s, D, G> Completion<'s, D, G> {
107 fn present(value: Reading<'s, D, G>) -> Self {
108 Self {
109 object: Some(value),
110 }
111 }
112}
113
114struct Resolution<'a, 'q, 'b, 's, S: RangeSource, W: Work> {
115 reader: &'a mut RangeReader<'q, S>,
116 frames: &'a mut OwnedVec<Frame<'b, 's, S::Document, S::Generation>, W>,
117 completed: &'a mut Option<Completion<'s, S::Document, S::Generation>>,
118}
119
120#[derive(Clone, Copy)]
121enum Request<'b, 's, D, G> {
122 Object {
123 number: u64,
124 generation: u16,
125 },
126 Stream {
127 reading: &'b Reading<'s, D, G>,
128 object_stream: bool,
129 },
130}
131#[expect(
132 clippy::large_enum_variant,
133 reason = "the completed iterative resolver transfers an already owned reading without allocating an output envelope"
134)]
135enum Output<'s, D, G> {
136 Object(Option<Reading<'s, D, G>>),
137 Stream(Prepared),
138}
139pub(super) struct Prepared {
140 pub(super) plans: OwnedVec<crate::stream::Step>,
141 pub(super) body: Span,
142 pub(super) layout: Option<(u64, u64)>,
143}
144pub(crate) struct Decoded {
145 pub(crate) bytes: OwnedVec<u8>,
146 pub(crate) body: Span,
147 pub(crate) layout: Option<(u64, u64)>,
148}
149
150impl<'s, S: RangeSource> Document<'s, S> {
151 pub(crate) async fn resolve_value<'a, W: Work>(
154 &self,
155 reading: &'a Reading<'s, S::Document, S::Generation>,
156 node: NodeId,
157 operation: &W,
158 ) -> Result<Option<ResolvedValue<'a, 's, S::Document, S::Generation>>, ReadFailure<S::Error>>
159 {
160 let work = self.session.query(operation);
161 let location = reading.value.root().location();
162 self.check(&work, location)?;
163 if !core::ptr::eq(reading.value.session, self.session) || reading.value.stamp != self.stamp
164 {
165 return Err(Error {
166 kind: ErrorKind::Foreign,
167 location,
168 }
169 .into());
170 }
171 admit(&work, location, 1)?;
172 match reading.value.arena.nodes[node.0].kind {
173 Kind::Null => Ok(None),
174 Kind::Reference { number, generation } => {
175 let Some(value) = self
176 .object(reading.revision, number, generation, &work)
177 .await?
178 else {
179 return Ok(None);
180 };
181 admit(&work, value.value.root().location(), 1)?;
182 if matches!(value.value.arena.nodes[value.value.root.0].kind, Kind::Null) {
183 return Ok(None);
184 }
185 Ok(Some(ResolvedValue::Owned(value)))
186 }
187 _ => Ok(Some(ResolvedValue::Borrowed { reading, node })),
188 }
189 }
190
191 pub async fn object<W: Work>(
196 &self,
197 revision: usize,
198 number: u64,
199 generation: u16,
200 operation: &W,
201 ) -> Result<Option<Reading<'s, S::Document, S::Generation>>, ReadFailure<S::Error>> {
202 match self
203 .resolve(revision, Request::Object { number, generation }, operation)
204 .await?
205 {
206 Output::Object(value) => Ok(value),
207 Output::Stream(_) => unreachable!("object resolution request"),
208 }
209 }
210
211 pub(crate) async fn stream_data<W: Work>(
212 &self,
213 reading: &Reading<'s, S::Document, S::Generation>,
214 object_stream: bool,
215 operation: &W,
216 ) -> Result<Decoded, ReadFailure<S::Error>> {
217 let prepared = self.stream_plan(reading, object_stream, operation).await?;
218 let mut reader = RangeReader::new(self.source, self.session, operation)?;
219 let location = reading.value.root().location();
220 if reader.stamp() != self.stamp {
221 return Err(crate::range::InputError::Changed { location }.into());
222 }
223 let (bytes, _) = crate::stream::execute(
224 &mut reader,
225 prepared.body,
226 &prepared.plans,
227 reading.revision,
228 true,
229 )
230 .await?;
231 reader.check(location)?;
232 Ok(Decoded {
233 bytes,
234 body: prepared.body,
235 layout: prepared.layout,
236 })
237 }
238
239 pub(super) async fn stream_plan<W: Work>(
240 &self,
241 reading: &Reading<'s, S::Document, S::Generation>,
242 object_stream: bool,
243 operation: &W,
244 ) -> Result<Prepared, ReadFailure<S::Error>> {
245 if !core::ptr::eq(reading.value.session, self.session) || reading.value.stamp != self.stamp
246 {
247 return Err(Error {
248 kind: ErrorKind::Foreign,
249 location: reading.value.root().location(),
250 }
251 .into());
252 }
253 match self
254 .resolve(
255 reading.revision,
256 Request::Stream {
257 reading,
258 object_stream,
259 },
260 operation,
261 )
262 .await?
263 {
264 Output::Stream(value) => Ok(value),
265 Output::Object(_) => unreachable!("stream resolution request"),
266 }
267 }
268
269 async fn load_file<'b, W: Work, Q: Work>(
270 &self,
271 revision: usize,
272 mut frame: Frame<'b, 's, S::Document, S::Generation>,
273 offset: u64,
274 context: Resolution<'_, '_, 'b, 's, S, W>,
275 work: &Q,
276 ) -> Result<(), ReadFailure<S::Error>> {
277 let Resolution {
278 reader,
279 frames,
280 completed,
281 } = context;
282 let mut cursor = Cursor {
283 reader: reader.fork()?,
284 at: offset,
285 };
286 let (arena, indirect) =
287 crate::stream::open(&mut cursor, Arena::new(work).into_owned()).await?;
288 if indirect.number != frame.number || indirect.generation != frame.generation {
289 return Err(cursor.failure(Syntax::Object, offset));
290 }
291 let value = Value {
292 arena,
293 root: indirect.value,
294 session: self.session,
295 stamp: self.stamp,
296 end: cursor.at,
297 };
298 let reading = Reading {
299 value,
300 decoded: None,
301 stream: None,
302 number: frame.number,
303 generation: frame.generation,
304 revision,
305 };
306 if indirect.stream.is_some() {
307 let length = required(&reading.value.arena, indirect.value, b"Length", work)?;
308 if let Kind::Reference { number, generation } = reading.value.arena.nodes[length.0].kind
309 {
310 frame.state = State::Length(Pending { reading, indirect });
311 suspend(
312 frames,
313 frame,
314 (number, generation),
315 self,
316 cursor.location(offset, 0),
317 work,
318 )?;
319 return Ok(());
320 }
321 let length = unsigned(&reading.value.arena, length, work)?;
322 *completed = Some(Completion::present(
323 finish(&mut cursor, Pending { reading, indirect }, length).await?,
324 ));
325 } else if let Some((number, generation)) = reading.value.root().reference() {
326 frame.state = State::Reference;
327 suspend(
328 frames,
329 frame,
330 (number, generation),
331 self,
332 cursor.location(offset, 0),
333 work,
334 )?;
335 return Ok(());
336 } else {
337 *completed = Some(Completion::present(reading));
338 }
339 Ok(())
340 }
341
342 async fn control<'b, W: Work>(
343 &self,
344 revision: usize,
345 (number, generation): (u64, u16),
346 mut controls: super::controls::Controls<'b, 's, S::Document, S::Generation>,
347 selected: Option<(u64, u64)>,
348 context: Resolution<'_, '_, 'b, 's, S, W>,
349 work: &impl Work,
350 ) -> Result<Option<Prepared>, ReadFailure<S::Error>> {
351 let Resolution {
352 reader,
353 frames,
354 completed,
355 } = context;
356 let mut frame = Frame {
357 number,
358 generation,
359 state: State::Start,
360 };
361 if controls.waiting() {
362 controls.supply(
363 completed
364 .take()
365 .expect("completed control dependency")
366 .object,
367 work,
368 )?;
369 }
370 match controls.advance(work) {
371 Err(crate::stream::plan::Failure::Fault(error)) => return Err(error.into()),
372 Err(crate::stream::plan::Failure::Need { number, generation }) => {
373 frame.state = State::Controls {
374 controls,
375 member: selected,
376 };
377 suspend(
378 frames,
379 frame,
380 (number, generation),
381 self,
382 reader.location(0, 0),
383 work,
384 )?;
385 return Ok(None);
386 }
387 Ok(()) => {}
388 }
389 let location = controls.container.value.root().location();
390 let body = controls.container.stream.ok_or(Error {
391 kind: ErrorKind::Syntax(Syntax::Stream),
392 location,
393 })?;
394 let plans = controls.plans();
395 let layout = controls.layout;
396 if let Some((_, selected)) = selected {
397 let (count, _) = layout.expect("object-stream controls");
398 if selected >= count {
399 return Err(Error {
400 kind: ErrorKind::Syntax(Syntax::Object),
401 location,
402 }
403 .into());
404 }
405 }
406 if let Some((number, selected)) = selected {
407 let (bytes, _) = crate::stream::execute(reader, body, &plans, revision, true).await?;
408 drop(plans);
409 let (count, first) = layout.expect("object-stream controls");
410 let reading = member(
411 self,
412 reader,
413 bytes,
414 body,
415 (count, first),
416 (number, selected),
417 revision,
418 )
419 .await?;
420 if let Some((number, generation)) = reading.value.root().reference() {
421 frame.state = State::Reference;
422 suspend(frames, frame, (number, generation), self, location, work)?;
423 return Ok(None);
424 }
425 *completed = Some(Completion::present(reading));
426 } else {
427 debug_assert!(frames.is_empty());
428 reader.check(location)?;
429 return Ok(Some(Prepared {
430 plans,
431 body,
432 layout,
433 }));
434 }
435 Ok(None)
436 }
437
438 fn compressed<'b, W: Work>(
439 &self,
440 revision: usize,
441 mut frame: Frame<'b, 's, S::Document, S::Generation>,
442 (stream, index): (u64, u64),
443 frames: &mut OwnedVec<Frame<'b, 's, S::Document, S::Generation>, W>,
444 location: Location,
445 work: &impl Work,
446 ) -> crate::Result<()> {
447 if !matches!(
448 self.target(revision, stream, 0, work)?,
449 Some(Target::File { .. })
450 ) {
451 return Err(Error {
452 kind: ErrorKind::Syntax(Syntax::Object),
453 location,
454 });
455 }
456 frame.state = State::Member { index };
457 suspend(frames, frame, (stream, 0), self, location, work)
458 }
459
460 async fn resolve<W: Work>(
461 &self,
462 revision: usize,
463 request: Request<'_, 's, S::Document, S::Generation>,
464 operation: &W,
465 ) -> Result<Output<'s, S::Document, S::Generation>, ReadFailure<S::Error>> {
466 let mut reader = self.original_reader(operation)?;
467 let work = reader.execution();
468 let mut frames = work.vector();
469 let frame = initial(request, &work);
470 push(&mut frames, frame, self, reader.location(0, 0), &work)?;
471 let mut completed = None;
472 while let Some(frame) = frames.pop() {
473 admit(&work, reader.location(0, 0), 1)?;
474 match frame.state {
475 State::Start => {
476 match self.target(revision, frame.number, frame.generation, &work)? {
477 None => completed = Some(Completion { object: None }),
478 Some(Target::File { offset, .. }) => {
479 self.load_file(
480 revision,
481 frame,
482 offset,
483 Resolution {
484 reader: &mut reader,
485 frames: &mut frames,
486 completed: &mut completed,
487 },
488 &work,
489 )
490 .await?;
491 }
492 Some(Target::Compressed { stream, index }) => {
493 self.compressed(
494 revision,
495 frame,
496 (stream, index),
497 &mut frames,
498 reader.location(0, 0),
499 &work,
500 )?;
501 continue;
502 }
503 Some(Target::Free { .. } | Target::Null) => {
504 unreachable!("filtered resolver target")
505 }
506 }
507 }
508 State::Length(pending) => {
509 completed = Some(Completion::present(
510 resolved_length(&reader, pending, completed.take(), &work).await?,
511 ));
512 }
513 State::Member { index } => {
514 member_controls(
515 frame,
516 index,
517 Resolution {
518 reader: &mut reader,
519 frames: &mut frames,
520 completed: &mut completed,
521 },
522 &work,
523 )?;
524 continue;
525 }
526 State::Controls {
527 controls,
528 member: selected,
529 } => {
530 if let Some(prepared) = self
531 .control(
532 revision,
533 (frame.number, frame.generation),
534 controls,
535 selected,
536 Resolution {
537 reader: &mut reader,
538 frames: &mut frames,
539 completed: &mut completed,
540 },
541 &work,
542 )
543 .await?
544 {
545 return Ok(Output::Stream(prepared));
546 }
547 }
548 State::Reference => {
549 debug_assert!(completed.is_some());
550 }
551 }
552 if frames.is_empty() {
553 reader.check(reader.location(0, self.stamp.length))?;
554 return Ok(Output::Object(
555 completed.expect("completed root frame").object,
556 ));
557 }
558 }
559 unreachable!("initial root frame")
560 }
561}
562
563async fn resolved_length<'s, S: RangeSource>(
564 reader: &RangeReader<'_, S>,
565 pending: Pending<'s, S::Document, S::Generation>,
566 completed: Option<Completion<'s, S::Document, S::Generation>>,
567 work: &impl Work,
568) -> Result<Reading<'s, S::Document, S::Generation>, ReadFailure<S::Error>> {
569 let Some(Completion {
570 object: Some(length),
571 }) = completed
572 else {
573 return Err(Error {
574 kind: ErrorKind::Syntax(Syntax::Stream),
575 location: pending.reading.value.root().location(),
576 }
577 .into());
578 };
579 let length = length.value.root().unsigned(work)?;
580 let mut cursor = Cursor {
581 reader: reader.fork()?,
582 at: 0,
583 };
584 finish(&mut cursor, pending, length).await
585}
586
587fn member_controls<'b, 's, S: RangeSource, W: Work>(
588 mut frame: Frame<'b, 's, S::Document, S::Generation>,
589 index: u64,
590 context: Resolution<'_, '_, 'b, 's, S, W>,
591 work: &impl Work,
592) -> Result<(), ReadFailure<S::Error>> {
593 let Resolution {
594 reader,
595 frames,
596 completed,
597 } = context;
598 let Some(Completion {
599 object: Some(container),
600 }) = completed.take()
601 else {
602 return Err(Error {
603 kind: ErrorKind::Syntax(Syntax::Object),
604 location: reader.location(0, 0),
605 }
606 .into());
607 };
608 frame.state = State::Controls {
609 controls: super::controls::Controls::new(
610 super::controls::Owner::Owned(container),
611 true,
612 work,
613 ),
614 member: Some((frame.number, index)),
615 };
616 frames
617 .try_push(frame)
618 .map_err(|cause| resource(cause, reader.location(0, 0)))?;
619 Ok(())
620}
621
622fn initial<'b, 's, D: Copy + Eq, G: Copy + Eq>(
623 request: Request<'b, 's, D, G>,
624 work: &impl Work,
625) -> Frame<'b, 's, D, G> {
626 match request {
627 Request::Object { number, generation } => Frame {
628 number,
629 generation,
630 state: State::Start,
631 },
632 Request::Stream {
633 reading,
634 object_stream,
635 } => Frame {
636 number: reading.number,
637 generation: reading.generation,
638 state: State::Controls {
639 controls: super::controls::Controls::new(
640 super::controls::Owner::Borrowed(reading),
641 object_stream,
642 work,
643 ),
644 member: None,
645 },
646 },
647 }
648}
649
650fn suspend<'b, 's, S: RangeSource, W: Work>(
651 frames: &mut OwnedVec<Frame<'b, 's, S::Document, S::Generation>, W>,
652 frame: Frame<'b, 's, S::Document, S::Generation>,
653 (number, generation): (u64, u16),
654 document: &Document<'_, S>,
655 location: Location,
656 work: &impl Work,
657) -> crate::Result<()> {
658 frames
659 .try_push(frame)
660 .map_err(|cause| resource(cause, location))?;
661 push(
662 frames,
663 Frame {
664 number,
665 generation,
666 state: State::Start,
667 },
668 document,
669 location,
670 work,
671 )
672}
673
674fn resource(cause: structured_asn1::memory::MemoryError, location: Location) -> Error {
675 Error {
676 kind: ErrorKind::Resource(cause),
677 location,
678 }
679}
680
681fn push<'b, 's, S: RangeSource, W: Work>(
682 frames: &mut OwnedVec<Frame<'b, 's, S::Document, S::Generation>, W>,
683 frame: Frame<'b, 's, S::Document, S::Generation>,
684 document: &Document<'_, S>,
685 location: Location,
686 work: &impl Work,
687) -> crate::Result<()> {
688 if frames.len() >= 512
691 || frames.len() as u64 >= u64::from(document.session.limits().processing.max_depth)
692 {
693 return Err(Error {
694 kind: ErrorKind::Limit(crate::error::Limit::Depth),
695 location,
696 });
697 }
698 for prior in frames.iter() {
699 admit(work, location, 1)?;
700 if prior.number == frame.number && prior.generation == frame.generation {
701 return Err(Error {
702 kind: ErrorKind::Syntax(Syntax::Cycle),
703 location,
704 });
705 }
706 }
707 frames
708 .try_push(frame)
709 .map_err(|cause| resource(cause, location))
710}
711
712async fn finish<'s, S: RangeSource>(
713 cursor: &mut Cursor<'_, S>,
714 mut pending: Pending<'s, S::Document, S::Generation>,
715 length: u64,
716) -> Result<Reading<'s, S::Document, S::Generation>, ReadFailure<S::Error>> {
717 let body = crate::stream::close(
718 cursor,
719 pending.indirect.stream.expect("pending stream"),
720 length,
721 )
722 .await?;
723 pending.reading.stream = Some(body);
724 pending.reading.value.end = cursor.at;
725 Ok(pending.reading)
726}
727
728async fn member<'s, S: RangeSource>(
729 document: &Document<'s, S>,
730 reader: &mut RangeReader<'_, S>,
731 decoded: OwnedVec<u8>,
732 body: Span,
733 (count, first): (u64, u64),
734 (number, selected): (u64, u64),
735 revision: usize,
736) -> Result<Reading<'s, S::Document, S::Generation>, ReadFailure<S::Error>> {
737 let work = reader.execution();
738 let location = reader.location(body.start, body.length);
739 if selected >= count || count > first / 4 {
740 return Err(Error {
741 kind: ErrorKind::Syntax(Syntax::Object),
742 location,
743 }
744 .into());
745 }
746 let slots = super::members::directory(
747 document.session,
748 document.stamp,
749 &decoded,
750 body,
751 (count, first),
752 revision,
753 &work,
754 )
755 .await
756 .map_err(convert)?;
757 let ordinal = usize::try_from(selected).expect("parsed object-stream directory length");
758 let slot = &slots[ordinal];
759 if slot.number != number {
760 return Err(Error {
761 kind: ErrorKind::Syntax(Syntax::Object),
762 location,
763 }
764 .into());
765 }
766 let value = super::members::selected(
767 document.session,
768 document.stamp,
769 &decoded,
770 body,
771 slot,
772 revision,
773 &work,
774 )
775 .await
776 .map_err(convert)?;
777 Ok(Reading {
778 value,
779 decoded: Some(decoded),
780 stream: None,
781 number,
782 generation: 0,
783 revision,
784 })
785}
786
787pub(crate) fn convert<E>(error: ReadFailure<core::convert::Infallible>) -> ReadFailure<E> {
788 match error {
789 ReadFailure::Format(error) => ReadFailure::Format(error),
790 ReadFailure::Input(error) => ReadFailure::Input(match error {
791 crate::range::InputError::Resource { location, cause } => {
792 crate::range::InputError::Resource { location, cause }
793 }
794 crate::range::InputError::Changed { location } => {
795 crate::range::InputError::Changed { location }
796 }
797 crate::range::InputError::Contract { location } => {
798 crate::range::InputError::Contract { location }
799 }
800 crate::range::InputError::Cause { cause, .. } => match cause {},
801 }),
802 }
803}