sark_json/segment/frames/
mod.rs1use std::{
2 marker,
3 num::NonZero,
4 ops::{self, ControlFlow},
5 task::Poll,
6};
7
8use o3::{
9 alloc,
10 buffer::{resident, storage},
11};
12use sark_http::request;
13
14use crate::{
15 Error, Nesting, Plain, Raw, Text,
16 input::Taken,
17 segment::{self, Atom, Cursor, End, Outcome, cursor::Replay, input::Input, is_delimiter},
18 source::string::Scan,
19};
20
21mod context;
22mod sealed;
23pub(super) use context::Context;
24pub(super) use sealed::Sealed;
25
26#[derive(Clone, Copy, Eq, PartialEq)]
28pub enum Mode {
29 Frame,
30 Plain,
31 Raw,
32}
33
34#[repr(transparent)]
36pub struct Captured<F> {
37 bytes: storage::Shared,
38 marker: marker::PhantomData<F>,
39}
40
41pub trait Capture<C: Context>: Sealed + Sized {
43 type Value;
44 const MODE: Mode;
45 fn bind(context: C, bytes: Captured<Self>) -> Self::Value;
46}
47
48impl Capture<()> for Text<storage::Shared> {
49 type Value = Self;
50 const MODE: Mode = Mode::Frame;
51 fn bind(_: (), bytes: Captured<Self>) -> Self::Value {
52 Self::admitted(bytes.bytes)
53 }
54}
55
56impl<'d> Capture<request::Id<'d>> for Text<storage::Shared> {
57 type Value = Text<request::Bytes<'d>>;
58 const MODE: Mode = Mode::Frame;
59 fn bind(context: request::Id<'d>, bytes: Captured<Self>) -> Self::Value {
60 Self::admitted(bytes.bytes).into_request(context)
61 }
62}
63
64impl Capture<()> for Plain<storage::Shared> {
65 type Value = Self;
66 const MODE: Mode = Mode::Plain;
67 fn bind(_: (), bytes: Captured<Self>) -> Self::Value {
68 Self::admitted(bytes.bytes)
69 }
70}
71
72impl<'d> Capture<request::Id<'d>> for Plain<storage::Shared> {
73 type Value = Plain<request::Bytes<'d>>;
74 const MODE: Mode = Mode::Plain;
75 fn bind(context: request::Id<'d>, bytes: Captured<Self>) -> Self::Value {
76 Self::admitted(bytes.bytes).into_request(context)
77 }
78}
79
80impl Capture<()> for Raw<storage::Shared> {
81 type Value = Self;
82 const MODE: Mode = Mode::Raw;
83 fn bind(_: (), bytes: Captured<Self>) -> Self::Value {
84 Self::admitted(bytes.bytes)
85 }
86}
87
88impl<'d> Capture<request::Id<'d>> for Raw<storage::Shared> {
89 type Value = Raw<request::Bytes<'d>>;
90 const MODE: Mode = Mode::Raw;
91 fn bind(context: request::Id<'d>, bytes: Captured<Self>) -> Self::Value {
92 Self::admitted(bytes.bytes).into_request(context)
93 }
94}
95
96pub struct Frames<'d, C: Context = (), F: Capture<C> = Text<storage::Shared>> {
100 input: Input<'d>,
101 cursor: Cursor,
102 state: State,
103 values: Vec<F::Value>,
104 context: C,
105 marker: marker::PhantomData<F>,
106}
107
108enum State {
109 Leading,
110 Element { end: End },
111 String { start: usize, string: Scan },
112 Atom { start: usize, atom: Atom },
113 Compound { start: usize, nesting: Nesting },
114 Copy(Replay),
115 Delimiter,
116 Trailing,
117 Release,
118 Failed(Option<crate::Error>),
119}
120
121impl<'d> Frames<'d> {
122 pub fn from_scoped(input: Vec<resident::Shared<'d>>) -> crate::Result<Self> {
123 Ok(Self::with_input(Input::new(input)?, ()))
124 }
125}
126
127impl<'d, C: Context, F: Capture<C>> Frames<'d, C, F> {
128 pub fn admitted(input: segment::Admitted<'d>, context: C) -> Self {
129 Self::with_input(input.input, context)
130 }
131
132 fn with_input(input: Input<'d>, context: C) -> Self {
133 Self {
134 input,
135 cursor: Cursor::new(),
136 state: State::Leading,
137 values: Vec::new(),
138 context,
139 marker: marker::PhantomData,
140 }
141 }
142
143 fn capture(&mut self, range: ops::Range<usize>, removed: usize) -> crate::Result<()> {
144 alloc::VecExt::try_reserve(&mut self.values, 1).map_err(Error::Allocation)?;
145 let owned = if removed == 0 {
146 self.input.try_own(range.clone())?
147 } else {
148 None
149 };
150 if let Some(shared) = owned {
151 self.store(shared);
152 } else {
153 let output =
154 alloc::VecExt::try_new(range.len() - removed).map_err(Error::Allocation)?;
155 let cursor = Cursor::at(&self.input, range.start).ok_or(Error::Invalid)?;
156 self.state = State::Copy(Replay::new(cursor, range.end, output, removed != 0));
157 }
158 Ok(())
159 }
160
161 fn store(&mut self, bytes: storage::Shared) {
162 unsafe { alloc::raw::VecExt::vacancy(&mut self.values) }.insert(F::bind(
164 self.context,
165 Captured {
166 bytes,
167 marker: marker::PhantomData,
168 },
169 ));
170 self.state = State::Delimiter;
171 }
172
173 pub fn release(&mut self, budget: &mut usize) -> Poll<()> {
174 if !matches!(self.state, State::Failed(_)) {
175 self.state = State::Failed(None);
176 }
177 while !self.values.is_empty() {
178 if *budget == 0 {
179 return Poll::Pending;
180 }
181 drop(self.values.pop());
182 *budget -= 1;
183 }
184 self.input.release(budget).0
185 }
186
187 pub fn step(mut self, budget: NonZero<usize>) -> Outcome<'d, Self, Vec<F::Value>> {
188 if matches!(self.state, State::Failed(_)) {
189 let mut left = budget.get();
190 if self.release(&mut left).is_pending() {
191 return Outcome::Pending(self);
192 }
193 if let State::Failed(Some(error)) = self.state {
194 return Outcome::Failed(error.into());
195 }
196 return Outcome::Pending(self);
197 }
198 match self.try_step(budget) {
199 Ok(ControlFlow::Continue(())) => Outcome::Pending(self),
200 Ok(ControlFlow::Break(values)) => Outcome::Ready(values),
201 Err(error) => {
202 self.state = State::Failed(Some(error));
203 Outcome::Pending(self)
204 }
205 }
206 }
207
208 fn try_step(&mut self, budget: NonZero<usize>) -> crate::Result<ControlFlow<Vec<F::Value>>> {
209 let mut left = budget.get();
210 while let Some(budget) = NonZero::new(left) {
211 let input = &self.input;
212 match &mut self.state {
213 State::Failed(_) => break,
214 State::Leading => {
215 if self.cursor.take_ws(input) == Taken::Yes {
216 left -= 1;
217 } else {
218 if self.cursor.take(input, b'[') == Taken::No {
219 return Err(Error::Invalid);
220 }
221 left -= 1;
222 self.state = State::Element { end: End::Allowed };
223 }
224 }
225 State::Element { end } => {
226 if self.cursor.take_ws(input) == Taken::Yes {
227 left -= 1;
228 } else if *end == End::Allowed && self.cursor.take(input, b']') == Taken::Yes {
229 left -= 1;
230 self.state = State::Trailing;
231 } else {
232 let (byte, advance) = self.cursor.read(input).ok_or(Error::Invalid)?;
233 if byte == b'"' {
234 self.cursor.advance(advance);
235 left -= 1;
236 self.state = State::String {
237 start: self.cursor.absolute,
238 string: Scan::new(input.is_admitted()),
239 };
240 } else if F::MODE == Mode::Plain {
241 return Err(Error::Invalid);
242 } else if matches!(byte, b'{' | b'[') {
243 let nesting = if input.is_admitted() {
244 Nesting::admitted()
245 } else {
246 Nesting::start(byte)?
247 };
248 let start = self.cursor.absolute;
249 self.cursor.advance(advance);
250 left -= 1;
251 self.state = State::Compound { start, nesting };
252 } else {
253 let atom = Atom::new(byte, false)?;
254 self.state = State::Atom {
255 start: self.cursor.absolute,
256 atom,
257 };
258 }
259 }
260 }
261 State::String { start, string } => {
262 let (byte, advance) = self.cursor.read(input).ok_or(Error::Invalid)?;
263 let decoded = string.step(byte)?;
264 if decoded.is_none() {
265 let (range, removed) = match F::MODE {
266 Mode::Raw => (*start - 1..self.cursor.absolute + 1, 0),
267 Mode::Plain if string.removed() != 0 => {
268 return Err(Error::Invalid);
269 }
270 Mode::Plain | Mode::Frame => {
271 (*start..self.cursor.absolute, string.removed())
272 }
273 };
274 self.cursor.advance(advance);
275 left -= 1;
276 self.capture(range, removed)?;
277 } else {
278 self.cursor.advance(advance);
279 left -= 1;
280 }
281 }
282 State::Atom { start, atom } => {
283 let (byte, advance) = self.cursor.read(input).ok_or(Error::Invalid)?;
284 if is_delimiter(byte) {
285 atom.finish()?;
286 let range = *start..self.cursor.absolute;
287 self.capture(range, 0)?;
288 } else {
289 *atom = atom.step(byte)?;
290 self.cursor.advance(advance);
291 left -= 1;
292 }
293 }
294 State::Compound { start, nesting } => {
295 let (byte, advance) = self.cursor.read(input).ok_or(Error::Invalid)?;
296 let done = nesting.step(byte)?;
297 self.cursor.advance(advance);
298 left -= 1;
299 if done {
300 let range = *start..self.cursor.absolute;
301 self.capture(range, 0)?;
302 }
303 }
304 State::Copy(replay) => {
305 if replay.is_done() {
306 let shared = replay.try_finish()?;
307 self.store(shared);
308 } else {
309 let copied = replay.try_copy(input, budget)?;
310 left -= copied.get();
311 }
312 }
313 State::Delimiter => {
314 if self.cursor.take_ws(input) == Taken::Yes {
315 left -= 1;
316 } else if self.cursor.take(input, b',') == Taken::Yes {
317 left -= 1;
318 self.state = State::Element {
319 end: End::Forbidden,
320 };
321 } else if self.cursor.take(input, b']') == Taken::Yes {
322 left -= 1;
323 self.state = State::Trailing;
324 } else {
325 return Err(Error::Invalid);
326 }
327 }
328 State::Trailing => {
329 if self.cursor.take_ws(input) == Taken::Yes {
330 left -= 1;
331 } else if self.cursor.absolute == input.len() {
332 self.state = State::Release;
333 } else {
334 return Err(Error::Invalid);
335 }
336 }
337 State::Release => {
338 if self.input.release(&mut left).0.is_ready() {
339 return Ok(ControlFlow::Break(std::mem::take(&mut self.values)));
340 }
341 }
342 }
343 }
344 Ok(ControlFlow::Continue(()))
345 }
346}