Skip to main content

sark_json/segment/
nested.rs

1use std::{iter, num::NonZero, ops::ControlFlow, task::Poll};
2
3use o3::{
4    alloc,
5    buffer::{resident, storage},
6};
7
8use crate::{
9    Error, Nesting,
10    input::Taken,
11    segment::{
12        Admitted, Cursor, Decode, Decoder, End, Outcome, Progress,
13        input::{Input, Split},
14    },
15};
16
17/// Cooperative materialization of a JSON array whose elements are generated
18/// JSON objects.
19pub struct Nested<'d, T: Decode<C>, C: Copy = ()> {
20    input: Input<'d>,
21    cursor: Cursor,
22    state: State<'d, T, C>,
23    context: C,
24    values: Vec<T>,
25    error: Option<Result<(), crate::parsing::Error<'d>>>,
26}
27
28enum State<'d, T: Decode<C>, C: Copy> {
29    Leading,
30    Element { end: End },
31    Group { start: usize, nesting: Nesting },
32    Projecting(Split<'d>),
33    Starting(Admitted<'d>),
34    Decoding(Box<Decoder<'d, T, C>>),
35    Delimiter,
36    Trailing,
37    Release,
38}
39
40impl<'d, T: Decode> Nested<'d, T> {
41    pub fn one(input: storage::Shared) -> crate::Result<Self> {
42        Self::new(iter::once(input))
43    }
44
45    pub fn new<I, O>(input: I) -> crate::Result<Self>
46    where
47        I: IntoIterator<Item = O>,
48        I::IntoIter: ExactSizeIterator,
49        resident::Shared<'d>: From<O>,
50    {
51        Ok(Self::with_input(Input::new(input)?, ()))
52    }
53}
54
55impl<'d, T: Decode<C>, C: Copy> Nested<'d, T, C> {
56    pub fn admitted(input: Admitted<'d>, context: C) -> Self {
57        Self::with_input(input.input, context)
58    }
59
60    fn with_input(input: Input<'d>, context: C) -> Self {
61        Self {
62            input,
63            cursor: Cursor::new(),
64            state: State::Leading,
65            values: Vec::new(),
66            context,
67            error: None,
68        }
69    }
70
71    pub fn release(&mut self, budget: &mut usize) -> Poll<()> {
72        self.error.get_or_insert(Ok(()));
73        let state = match &mut self.state {
74            State::Projecting(parts) => parts.release(budget),
75            State::Starting(input) => input.release(budget),
76            State::Decoding(worker) => worker.release(budget),
77            State::Leading
78            | State::Element { .. }
79            | State::Group { .. }
80            | State::Delimiter
81            | State::Trailing
82            | State::Release => Poll::Ready(()),
83        };
84        if state.is_pending() {
85            return Poll::Pending;
86        }
87        while let Some(value) = self.values.last_mut() {
88            if *budget == 0 || <T as Decode<C>>::release(value, budget).is_pending() {
89                return Poll::Pending;
90            }
91            if *budget == 0 {
92                return Poll::Pending;
93            }
94            drop(self.values.pop());
95            *budget -= 1;
96        }
97        self.input.release(budget).0
98    }
99
100    pub fn step(mut self, budget: NonZero<usize>) -> Outcome<'d, Self, Vec<T>> {
101        if self.error.is_some() {
102            let mut left = budget.get();
103            if self.release(&mut left).is_pending() {
104                return Outcome::Pending(self);
105            }
106            if let Some(Err(error)) = self.error {
107                return Outcome::Failed(error);
108            }
109            return Outcome::Pending(self);
110        }
111        match self.try_step(budget) {
112            Ok(ControlFlow::Continue(())) => Outcome::Pending(self),
113            Ok(ControlFlow::Break(values)) => Outcome::Ready(values),
114            Err(error) => {
115                self.error = Some(Err(error));
116                Outcome::Pending(self)
117            }
118        }
119    }
120
121    fn try_step(
122        &mut self,
123        budget: NonZero<usize>,
124    ) -> Result<ControlFlow<Vec<T>>, crate::parsing::Error<'d>> {
125        let mut left = budget.get();
126        while let Some(work) = NonZero::new(left) {
127            let input = &self.input;
128            match &mut self.state {
129                State::Leading => {
130                    if self.cursor.take_ws(input) == Taken::Yes {
131                        left -= 1;
132                    } else {
133                        if self.cursor.take(input, b'[') == Taken::No {
134                            return Err(Error::Invalid.into());
135                        }
136                        left -= 1;
137                        self.state = State::Element { end: End::Allowed };
138                    }
139                }
140                State::Element { end } => {
141                    if self.cursor.take_ws(input) == Taken::Yes {
142                        left -= 1;
143                    } else if *end == End::Allowed && self.cursor.take(input, b']') == Taken::Yes {
144                        left -= 1;
145                        self.state = State::Trailing;
146                    } else {
147                        let (byte, advance) = self.cursor.read(input).ok_or(Error::Invalid)?;
148                        if !matches!(byte, b'{' | b'[') {
149                            return Err(Error::Invalid.into());
150                        }
151                        let nesting = if input.is_admitted() {
152                            Nesting::admitted()
153                        } else {
154                            Nesting::start(byte)?
155                        };
156                        let start = self.cursor.absolute;
157                        self.cursor.advance(advance);
158                        left -= 1;
159                        self.state = State::Group { start, nesting };
160                    }
161                }
162                State::Group { start, nesting } => {
163                    let (byte, advance) = self.cursor.read(input).ok_or(Error::Invalid)?;
164                    let done = nesting.step(byte)?;
165                    self.cursor.advance(advance);
166                    left -= 1;
167                    if done {
168                        let parts = Split::new(input, *start..self.cursor.absolute)?;
169                        alloc::VecExt::try_reserve(&mut self.values, 1)
170                            .map_err(Error::Allocation)?;
171                        self.state = State::Projecting(parts);
172                    }
173                }
174                State::Projecting(parts) => {
175                    let ready = parts.step(input, &mut left)?;
176                    if let Some(input) = ready {
177                        self.state = State::Starting(Admitted { input });
178                    }
179                }
180                State::Starting(input) => {
181                    let worker = Decoder::try_admitted(input, self.context)?;
182                    self.state = State::Decoding(worker);
183                }
184                State::Decoding(worker) => match worker.poll(work) {
185                    Progress::NeedInput => return Err(Error::Invalid.into()),
186                    Progress::Pending => return Ok(ControlFlow::Continue(())),
187                    Progress::Ready(value) => {
188                        // SAFETY: Group reserved this slot; projection and decoding preserve it.
189                        (unsafe { alloc::raw::VecExt::vacancy(&mut self.values) })(value);
190                        self.state = State::Delimiter;
191                        return Ok(ControlFlow::Continue(()));
192                    }
193                    Progress::Failed(error) => return Err(error),
194                },
195                State::Delimiter => {
196                    if self.cursor.take_ws(input) == Taken::Yes {
197                        left -= 1;
198                    } else if self.cursor.take(input, b',') == Taken::Yes {
199                        left -= 1;
200                        self.state = State::Element {
201                            end: End::Forbidden,
202                        };
203                    } else if self.cursor.take(input, b']') == Taken::Yes {
204                        left -= 1;
205                        self.state = State::Trailing;
206                    } else {
207                        return Err(Error::Invalid.into());
208                    }
209                }
210                State::Trailing => {
211                    if self.cursor.take_ws(input) == Taken::Yes {
212                        left -= 1;
213                    } else if self.cursor.absolute == input.len() {
214                        self.state = State::Release;
215                    } else {
216                        return Err(Error::Invalid.into());
217                    }
218                }
219                State::Release => {
220                    if self.input.release(&mut left).0.is_ready() {
221                        return Ok(ControlFlow::Break(std::mem::take(&mut self.values)));
222                    }
223                }
224            }
225        }
226        Ok(ControlFlow::Continue(()))
227    }
228}