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
204pub struct Decoder<'d, T: Decode<C>, C: Copy = ()> {
213 phase: slot::Storage<Phase<'d, T::State<'d>>>,
214 context: C,
215 bytes: usize,
216 chunks: segments::Count,
217 marker: marker::PhantomData<fn() -> T>,
218}
219
220enum Phase<'d, S> {
221 Scan(Scanner<'d>),
222 Start(Document<'d>),
223 Build(S),
224 Release {
225 release: Release<'d>,
226 error: Option<crate::parsing::Error<'d>>,
227 },
228 ReleaseBuild(S),
229}
230
231impl<'d, T: Decode> Decoder<'d, T> {
232 pub fn try_stream() -> Result<Self, Create> {
234 Self::try_feed(())
235 }
236
237 pub fn new(segments: Vec<storage::Shared>) -> crate::Result<Self> {
238 let scan = Scanner::new(segments, T::fields(), T::ORDER)?;
239 Ok(Self::with_scan(scan, ()))
240 }
241
242 pub fn one(segment: storage::Shared) -> crate::Result<Self> {
243 let scan = Scanner::new(iter::once(segment), T::fields(), T::ORDER)?;
244 Ok(Self::with_scan(scan, ()))
245 }
246
247 pub fn from_scoped(segments: Vec<resident::Shared<'d>>) -> crate::Result<Self> {
249 let scan = Scanner::new(segments, T::fields(), T::ORDER)?;
250 Ok(Self::with_scan(scan, ()))
251 }
252}
253
254impl<'d, T: Decode<C>, C: Copy> Decoder<'d, T, C> {
255 fn with_scan(scan: Scanner<'d>, context: C) -> Self {
256 Self {
257 phase: slot::Storage::filled(Phase::Scan(scan), ()),
258 context,
259 bytes: 0,
260 chunks: segments::Count::EMPTY,
261 marker: marker::PhantomData,
262 }
263 }
264
265 pub fn try_feed(context: C) -> Result<Self, Create> {
267 let scan = Scanner::try_stream(T::fields(), T::ORDER)?;
268 Ok(Self::with_scan(scan, context))
269 }
270
271 #[doc(hidden)]
274 pub fn try_admitted(input: &mut Admitted<'d>, context: C) -> crate::Result<Box<Self>> {
275 let selection =
276 scanner::Selection::try_new(T::fields(), T::ORDER).map_err(crate::Error::Allocation)?;
277 let slot: Box<mem::MaybeUninit<Self>> =
278 alloc::BoxExt::try_new(mem::MaybeUninit::uninit()).map_err(crate::Error::Exhausted)?;
279 let input = Admitted {
280 input: mem::replace(&mut input.input, input::Input::empty()),
281 };
282 let scan = Scanner::admitted(input, selection);
283 Ok(Box::write(slot, Self::with_scan(scan, context)))
284 }
285
286 #[doc(hidden)]
288 pub fn try_scoped(segments: owned::Segments<'d>, context: C) -> Result<Self, Create> {
289 let scan = Scanner::try_new(segments, T::fields(), T::ORDER)?;
290 Ok(Self::with_scan(scan, context))
291 }
292
293 pub fn push(mut self, segment: resident::Shared<'d>) -> Transfer<Self, Push<'d>> {
295 let result = match self.phase.get_mut() {
296 Some(Phase::Scan(scanner)) => scanner.push(segment),
297 _ => Err(Push::Complete(segment)),
298 };
299 match result {
300 Ok(()) => Transfer::Accepted(self),
301 Err(error) => Transfer::Rejected { state: self, error },
302 }
303 }
304
305 pub fn close(mut self) -> Self {
307 if let Some(phase) = self.phase.occupied() {
308 let (phase, vacant) = phase.take();
309 vacant.insert(match phase {
310 Phase::Scan(scanner) => Phase::Scan(scanner.close()),
311 phase => phase,
312 });
313 }
314 self
315 }
316
317 pub fn take_bytes(&mut self) -> usize {
321 mem::replace(&mut self.bytes, 0)
322 }
323
324 pub fn take_chunks(&mut self) -> segments::Count {
327 mem::replace(&mut self.chunks, segments::Count::EMPTY)
328 }
329
330 pub fn release(&mut self, budget: &mut usize) -> Poll<()> {
332 let Some(phase) = self.phase.occupied() else {
333 return Poll::Ready(());
334 };
335 let (phase, vacant) = phase.take();
336 let (mut release, error) = match phase {
337 Phase::Scan(scanner) => (scanner.release(), None),
338 Phase::Start(document) => (document.release(), None),
339 Phase::Build(mut state) | Phase::ReleaseBuild(mut state) => {
340 let done = Materialize::release(&mut state, budget);
341 if done.is_pending() {
342 vacant.insert(Phase::ReleaseBuild(state));
343 }
344 return done;
345 }
346 Phase::Release { release, error } => (release, error),
347 };
348 let done = release.retire(budget);
349 if done.is_pending() {
350 vacant.insert(Phase::Release { release, error });
351 }
352 done
353 }
354
355 pub fn poll(&mut self, budget: NonZero<usize>) -> Progress<'d, T> {
358 let Some(phase) = self.phase.occupied() else {
359 return Progress::Pending;
360 };
361 let (phase, vacant) = phase.take();
362 let (state, budget, vacant) = match phase {
363 Phase::ReleaseBuild(mut state) => {
364 let mut left = budget.get();
365 if Materialize::release(&mut state, &mut left).is_pending() {
366 vacant.insert(Phase::ReleaseBuild(state));
367 }
368 return Progress::Pending;
369 }
370 Phase::Release { mut release, error } => {
371 let mut left = budget.get();
372 let (done, released) = release.drain(&mut left);
373 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
376 if done.is_ready() {
377 return match error {
378 Some(error) => Progress::Failed(error),
379 None => Progress::Pending,
380 };
381 }
382 vacant.insert(Phase::Release { release, error });
383 return Progress::Pending;
384 }
385 Phase::Build(state) => (state, budget, vacant),
386 Phase::Start(document) => (T::start(document, self.context), budget, vacant),
387 Phase::Scan(scanner) => {
388 let (document, left, released) = {
389 let mut prepared;
390 let left = 'prepare: {
391 let (mut scan, closed) = match scanner {
392 Scanner::Open(scan) => (scan, false),
393 Scanner::Closed(scan) => (scan, true),
394 Scanner::Preparing(value) => {
395 prepared = value;
396 break 'prepare budget.get();
397 }
398 };
399 let (progress, left) = match scan.step(budget, closed) {
400 Ok(progress) => progress,
401 Err(error) => {
402 let released = scan.stream.drain();
403 let release = scan.release();
404 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
405 vacant.insert(Phase::Release {
406 release,
407 error: Some(error.into()),
408 });
409 return Progress::Pending;
410 }
411 };
412 let progress = match progress {
413 ScanProgress::Ready => {
414 prepared = Prepared::new(scan);
415 break 'prepare left;
416 }
417 ScanProgress::NeedInput => Progress::NeedInput,
418 ScanProgress::Pending => Progress::Pending,
419 };
420 let released = scan.stream.drain();
421 vacant.insert(Phase::Scan(if closed {
422 Scanner::Closed(scan)
423 } else {
424 Scanner::Open(scan)
425 }));
426 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
427 return progress;
428 };
429 let progress = match prepared.step(left) {
430 Ok(progress) => progress,
431 Err(error) => {
432 let released = prepared.stream.drain();
433 let release = prepared.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 released = prepared.stream.drain();
443 match progress {
444 Poll::Ready(left) => (prepared.document, left, released),
445 Poll::Pending => {
446 vacant.insert(Phase::Scan(Scanner::Preparing(prepared)));
447 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
448 return Progress::Pending;
449 }
450 }
451 };
452 (self.bytes, self.chunks) = released.add(self.bytes, self.chunks);
453 let Some(left) = NonZero::new(left) else {
454 vacant.insert(Phase::Start(document));
455 return Progress::Pending;
456 };
457 (T::start(document, self.context), left, vacant)
458 }
459 };
460 match Materialize::step(state, budget) {
461 Outcome::Ready(value) => Progress::Ready(value),
462 Outcome::Pending(state) => {
463 vacant.insert(Phase::Build(state));
464 Progress::Pending
465 }
466 Outcome::Failed(error) => Progress::Failed(error),
467 }
468 }
469}