1use std::{iter, marker, mem, num::NonZero, ops::ControlFlow, task::Poll};
4
5use o3::{
6 alloc,
7 buffer::{resident, segments, storage},
8 mem::slot,
9};
10use sark_http::{payload::owned, request};
11
12mod atom;
13mod cursor;
14mod document;
15pub mod frames;
16mod input;
17mod nested;
18mod scanner;
19mod state;
20
21pub(crate) use atom::Atom;
22use cursor::Cursor;
23pub use document::{
24 Document, admitted::Admitted, project::Project, release::Release, value::Value,
25};
26pub use nested::Nested;
27use scanner::{Prepared, Scanner};
28pub(crate) use state::ValueKind;
29use state::{Capture, ScanProgress, State, Stored, is_delimiter, is_overlap};
30
31pub const DEFAULT_STEP_BUDGET: NonZero<usize> = NonZero::<usize>::MIN.saturating_add(4 * 1024 - 1);
33
34#[derive(Clone, Copy, Eq, PartialEq)]
35enum End {
36 Allowed,
37 Forbidden,
38}
39
40#[derive(Clone, Copy, PartialEq, Eq)]
41pub enum Order {
42 Unordered,
43 Ordered,
44}
45
46#[derive(Clone, Copy, PartialEq, Eq)]
47pub enum Projection {
48 None,
49 Scalar,
50 Bytes,
51 Frame,
52 Segments,
55}
56
57#[derive(Clone, Copy)]
58pub struct Field<'a> {
59 name: &'a [u8],
60 projection: Projection,
61}
62
63impl<'a> Field<'a> {
64 #[must_use]
65 pub const fn new(name: &'a [u8], mode: Projection) -> Self {
66 Self {
67 name,
68 projection: mode,
69 }
70 }
71}
72
73pub trait Decode<C: Copy = ()>: Sized {
75 type State<'d>: Materialize<'d, Self>;
76
77 const ORDER: Order;
78
79 fn fields<'d>() -> &'d [Field<'d>];
80
81 fn start<'d>(document: Document<'d>, context: C) -> Self::State<'d>;
82
83 fn release(&mut self, budget: &mut usize) -> Poll<()>;
87}
88
89pub trait IntoRequest: Decode {
91 type Request<'d>: Decode<request::Id<'d>>;
92}
93
94pub trait Materialize<'d, T>: Sized {
95 fn step(self, budget: NonZero<usize>) -> Outcome<'d, Self, T>;
96
97 fn release(&mut self, budget: &mut usize) -> Poll<()>;
99}
100
101pub enum Outcome<'d, S, T> {
102 Pending(S),
103 Ready(T),
104 Failed(crate::parsing::Error<'d>),
105}
106
107pub struct Ready<'d, T> {
109 value: Result<T, crate::parsing::Error<'d>>,
110 release: Release<'d>,
111}
112
113impl<'d, T> Ready<'d, T> {
114 #[must_use]
115 pub fn new(value: T, document: Document<'d>) -> Self {
116 Self {
117 value: Ok(value),
118 release: document.release(),
119 }
120 }
121
122 #[must_use]
123 pub fn try_new(value: Result<T, crate::parsing::Error<'d>>, document: Document<'d>) -> Self {
124 Self {
125 value,
126 release: document.release(),
127 }
128 }
129}
130
131impl<'d, T> Materialize<'d, T> for Ready<'d, T> {
132 fn step(self, budget: NonZero<usize>) -> Outcome<'d, Self, T> {
133 match self.release.step(budget) {
134 ControlFlow::Continue(release) => Outcome::Pending(Self {
135 value: self.value,
136 release,
137 }),
138 ControlFlow::Break(()) => match self.value {
139 Ok(value) => Outcome::Ready(value),
140 Err(error) => Outcome::Failed(error),
141 },
142 }
143 }
144
145 fn release(&mut self, budget: &mut usize) -> Poll<()> {
146 self.release.retire(budget)
147 }
148}
149
150pub enum Progress<'d, T> {
153 NeedInput,
154 Pending,
155 Ready(T),
156 Failed(crate::parsing::Error<'d>),
157}
158
159#[repr(u8)]
161#[derive(Debug)]
162pub enum Create {
163 Exhausted,
164 Overflow,
165}
166
167impl From<alloc::Error> for Create {
168 fn from(error: alloc::Error) -> Self {
169 match error {
170 alloc::Error::Exhausted => Self::Exhausted,
171 alloc::Error::Overflow => Self::Overflow,
172 }
173 }
174}
175
176const _: () = assert!(mem::size_of::<Create>() == 1);
177
178pub enum Push<'d> {
180 Complete(resident::Shared<'d>),
181 Length {
182 len: usize,
183 add: usize,
184 owner: resident::Shared<'d>,
185 },
186 Segments {
187 current: segments::Count,
188 add: segments::Count,
189 owner: resident::Shared<'d>,
190 },
191 Allocation {
192 error: alloc::Error,
193 owner: resident::Shared<'d>,
194 },
195}
196
197#[must_use = "the accepted or rejected state must be consumed"]
199pub enum Transfer<S, E> {
200 Accepted(S),
201 Rejected { state: S, error: E },
202}
203
204impl<S, E> Transfer<S, E> {
205 pub(crate) fn map<T, F>(
206 self,
207 state: impl FnOnce(S) -> T,
208 error: impl FnOnce(E) -> F,
209 ) -> Transfer<T, F> {
210 match self {
211 Self::Accepted(value) => Transfer::Accepted(state(value)),
212 Self::Rejected {
213 state: value,
214 error: cause,
215 } => Transfer::Rejected {
216 state: state(value),
217 error: error(cause),
218 },
219 }
220 }
221}
222
223pub struct Decoder<'d, T: Decode<C>, C: Copy = ()> {
232 phase: slot::Storage<Phase<'d, T::State<'d>>>,
233 context: C,
234 bytes: usize,
235 chunks: segments::Count,
236 marker: marker::PhantomData<fn() -> T>,
237}
238
239enum Phase<'d, S> {
240 Scan(Scanner<'d>),
241 Start(Document<'d>),
242 Build(S),
243 Release {
244 release: Release<'d>,
245 error: Option<crate::parsing::Error<'d>>,
246 },
247 ReleaseBuild(S),
248}
249
250impl<'d, T: Decode> Decoder<'d, T> {
251 pub fn try_stream() -> Result<Self, Create> {
253 Self::try_feed(())
254 }
255
256 pub fn new(segments: Vec<storage::Shared>) -> crate::Result<Self> {
257 let scan = Scanner::new(segments, T::fields(), T::ORDER)?;
258 Ok(Self::with_scan(scan, ()))
259 }
260
261 pub fn one(segment: storage::Shared) -> crate::Result<Self> {
262 let scan = Scanner::new(iter::once(segment), T::fields(), T::ORDER)?;
263 Ok(Self::with_scan(scan, ()))
264 }
265
266 pub fn from_scoped(segments: Vec<resident::Shared<'d>>) -> crate::Result<Self> {
268 let scan = Scanner::new(segments, T::fields(), T::ORDER)?;
269 Ok(Self::with_scan(scan, ()))
270 }
271}
272
273impl<'d, T: Decode<C>, C: Copy> Decoder<'d, T, C> {
274 fn with_scan(scan: Scanner<'d>, context: C) -> Self {
275 Self {
276 phase: slot::Storage::filled(Phase::Scan(scan), ()),
277 context,
278 bytes: 0,
279 chunks: segments::Count::EMPTY,
280 marker: marker::PhantomData,
281 }
282 }
283
284 pub fn try_feed(context: C) -> Result<Self, Create> {
286 let scan = Scanner::try_stream(T::fields(), T::ORDER)?;
287 Ok(Self::with_scan(scan, context))
288 }
289
290 #[doc(hidden)]
293 pub fn try_admitted(input: &mut Admitted<'d>, context: C) -> crate::Result<Box<Self>> {
294 let selection =
295 scanner::Selection::try_new(T::fields(), T::ORDER).map_err(crate::Error::Allocation)?;
296 let slot: Box<mem::MaybeUninit<Self>> =
297 alloc::BoxExt::try_new(mem::MaybeUninit::uninit()).map_err(crate::Error::Exhausted)?;
298 let input = Admitted {
299 input: mem::replace(&mut input.input, input::Input::empty()),
300 };
301 let scan = Scanner::admitted(input, selection);
302 Ok(Box::write(slot, Self::with_scan(scan, context)))
303 }
304
305 #[doc(hidden)]
307 pub fn try_scoped(segments: owned::Segments<'d>, context: C) -> Result<Self, Create> {
308 let scan = Scanner::try_new(segments, T::fields(), T::ORDER)?;
309 Ok(Self::with_scan(scan, context))
310 }
311
312 pub fn push(mut self, segment: resident::Shared<'d>) -> Transfer<Self, Push<'d>> {
314 let Some(phase) = self.phase.occupied() else {
315 return Transfer::Rejected {
316 state: self,
317 error: Push::Complete(segment),
318 };
319 };
320 let (phase, vacant) = phase.take();
321 let (phase, error) = match phase {
322 Phase::Scan(scanner) => match scanner.push(segment) {
323 Transfer::Accepted(scanner) => (Phase::Scan(scanner), None),
324 Transfer::Rejected { state, error } => (Phase::Scan(state), Some(error)),
325 },
326 phase => (phase, Some(Push::Complete(segment))),
327 };
328 vacant.insert(phase);
329 match error {
330 Some(error) => Transfer::Rejected { state: self, error },
331 None => Transfer::Accepted(self),
332 }
333 }
334
335 pub fn close(mut self) -> Self {
337 if let Some(phase) = self.phase.occupied() {
338 let (phase, vacant) = phase.take();
339 vacant.insert(match phase {
340 Phase::Scan(scanner) => Phase::Scan(scanner.close()),
341 phase => phase,
342 });
343 }
344 self
345 }
346
347 pub fn take_bytes(&mut self) -> usize {
351 mem::replace(&mut self.bytes, 0)
352 }
353
354 pub fn take_chunks(&mut self) -> segments::Count {
357 mem::replace(&mut self.chunks, segments::Count::EMPTY)
358 }
359
360 pub fn release(&mut self, budget: &mut usize) -> Poll<()> {
362 let Some(phase) = self.phase.occupied() else {
363 return Poll::Ready(());
364 };
365 let (phase, vacant) = phase.take();
366 let (mut release, error) = match phase {
367 Phase::Scan(scanner) => (scanner.release(), None),
368 Phase::Start(document) => (document.release(), None),
369 Phase::Build(mut state) | Phase::ReleaseBuild(mut state) => {
370 let done = Materialize::release(&mut state, budget);
371 if done.is_pending() {
372 vacant.insert(Phase::ReleaseBuild(state));
373 }
374 return done;
375 }
376 Phase::Release { release, error } => (release, error),
377 };
378 let done = release.retire(budget);
379 if done.is_pending() {
380 vacant.insert(Phase::Release { release, error });
381 }
382 done
383 }
384
385 pub fn poll(&mut self, budget: NonZero<usize>) -> Progress<'d, T> {
388 let Some(phase) = self.phase.occupied() else {
389 return Progress::Pending;
390 };
391 let (phase, vacant) = phase.take();
392 let (state, budget, vacant) = match phase {
393 Phase::ReleaseBuild(mut state) => {
394 let mut left = budget.get();
395 if Materialize::release(&mut state, &mut left).is_pending() {
396 vacant.insert(Phase::ReleaseBuild(state));
397 }
398 return Progress::Pending;
399 }
400 Phase::Release { mut release, error } => {
401 let mut left = budget.get();
402 let (done, released) = release.drain(&mut left);
403 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
406 if done.is_ready() {
407 return match error {
408 Some(error) => Progress::Failed(error),
409 None => Progress::Pending,
410 };
411 }
412 vacant.insert(Phase::Release { release, error });
413 return Progress::Pending;
414 }
415 Phase::Build(state) => (state, budget, vacant),
416 Phase::Start(document) => (T::start(document, self.context), budget, vacant),
417 Phase::Scan(scanner) => {
418 let (document, left, released) = {
419 let mut prepared;
420 let left = 'prepare: {
421 let (mut scan, closed) = match scanner {
422 Scanner::Open(scan) => (scan, false),
423 Scanner::Closed(scan) => (scan, true),
424 Scanner::Preparing(value) => {
425 prepared = value;
426 break 'prepare budget.get();
427 }
428 };
429 let (progress, left) = match scan.step(budget, closed) {
430 Ok(progress) => progress,
431 Err(error) => {
432 let released = scan.stream.drain();
433 let release = scan.release();
434 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
435 vacant.insert(Phase::Release {
436 release,
437 error: Some(error.into()),
438 });
439 return Progress::Pending;
440 }
441 };
442 let progress = match progress {
443 ScanProgress::Ready => {
444 prepared = Prepared::new(scan);
445 break 'prepare left;
446 }
447 ScanProgress::NeedInput => Progress::NeedInput,
448 ScanProgress::Pending => Progress::Pending,
449 };
450 let released = scan.stream.drain();
451 vacant.insert(Phase::Scan(if closed {
452 Scanner::Closed(scan)
453 } else {
454 Scanner::Open(scan)
455 }));
456 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
457 return progress;
458 };
459 let progress = match prepared.step(left) {
460 Ok(progress) => progress,
461 Err(error) => {
462 let released = prepared.stream.drain();
463 let release = prepared.release();
464 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
465 vacant.insert(Phase::Release {
466 release,
467 error: Some(error.into()),
468 });
469 return Progress::Pending;
470 }
471 };
472 let released = prepared.stream.drain();
473 match progress {
474 Poll::Ready(left) => (prepared.document, left, released),
475 Poll::Pending => {
476 vacant.insert(Phase::Scan(Scanner::Preparing(prepared)));
477 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
478 return Progress::Pending;
479 }
480 }
481 };
482 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
483 let Some(left) = NonZero::new(left) else {
484 vacant.insert(Phase::Start(document));
485 return Progress::Pending;
486 };
487 (T::start(document, self.context), left, vacant)
488 }
489 };
490 match Materialize::step(state, budget) {
491 Outcome::Ready(value) => Progress::Ready(value),
492 Outcome::Pending(state) => {
493 vacant.insert(Phase::Build(state));
494 Progress::Pending
495 }
496 Outcome::Failed(error) => Progress::Failed(error),
497 }
498 }
499}