sark_json/segment/document/
project.rs1use std::{num::NonZero, task::Poll};
2
3use crate::segment::{Admitted, Document, Outcome, input::Split};
4
5pub struct Project<'d> {
7 pub(in crate::segment) doc: Document<'d>,
8 parts: Option<Split<'d>>,
9 field: usize,
10 error: Option<Result<(), crate::parsing::Error<'d>>>,
11}
12
13impl<'d> Project<'d> {
14 pub(in crate::segment) fn new(doc: Document<'d>, field: usize) -> Self {
15 Self {
16 doc,
17 parts: None,
18 field,
19 error: None,
20 }
21 }
22
23 pub(in crate::segment) fn with_parts(doc: Document<'d>, parts: Split<'d>) -> Self {
24 Self {
25 doc,
26 parts: Some(parts),
27 field: 0,
28 error: None,
29 }
30 }
31
32 pub fn release(&mut self, budget: &mut usize) -> Poll<()> {
33 self.error.get_or_insert(Ok(()));
34 if let Some(parts) = &mut self.parts
35 && parts.release(budget).is_pending()
36 {
37 return Poll::Pending;
38 }
39 self.doc.retire(budget)
40 }
41
42 pub fn step(
43 mut self,
44 budget: NonZero<usize>,
45 ) -> Outcome<'d, Self, (Document<'d>, Admitted<'d>)> {
46 let mut left = budget.get();
47 if self.error.is_some() {
48 if self.release(&mut left).is_pending() {
49 return Outcome::Pending(self);
50 }
51 if let Some(Err(error)) = self.error {
52 return Outcome::Failed(error);
53 }
54 return Outcome::Pending(self);
55 }
56 match self.try_step(&mut left) {
57 Ok(None) => Outcome::Pending(self),
58 Ok(Some(input)) => Outcome::Ready((self.doc, Admitted { input })),
59 Err(error) => {
60 self.error = Some(Err(error.into()));
61 Outcome::Pending(self)
62 }
63 }
64 }
65
66 fn try_step(
67 &mut self,
68 budget: &mut usize,
69 ) -> crate::Result<Option<super::super::input::Input<'d>>> {
70 if self.parts.is_none() {
71 let value = self.doc.field(self.field)?.ok_or(crate::Error::Invalid)?;
72 self.parts = Some(value.split()?);
73 }
74 match &mut self.parts {
75 Some(parts) => parts.step(&self.doc.input, budget),
76 None => Ok(None),
77 }
78 }
79}