use std::num;
pub use bytes::Bytes;
use dope_core::io::transfer;
pub use input::Input;
use o3::{
buffer,
buffer::{hold, resident, write::consume::scope},
};
use crate::client::session::response;
mod bytes;
pub mod eof;
mod input;
pub mod mode;
pub mod staging;
pub mod storage;
pub type Owner<'slot, 'id, 'd, C, S> =
storage::Owner<'slot, 'id, <C as Stateful>::Storage<S>, <C as Stateful>::State<'d>>;
pub struct Need<'id> {
consumed: Option<scope::End<'id, { transfer::MAX_BYTES as u32 }>>,
target: Option<Exact>,
}
pub enum Parse<'input, T> {
More(Need<'input>),
Blocked,
CapacityExhausted,
Item {
head: T,
consumed: scope::End<'input, { transfer::MAX_BYTES as u32 }>,
},
}
#[must_use]
pub enum Finish<T> {
Empty,
CapacityExhausted,
Item(T),
}
pub type Finished<O, T> = (O, Result<Finish<T>, T>);
pub type End<'input, 'd, C, S> =
Result<Finish<<C as Codec>::Head<'input, 'd, S>>, <C as Codec>::Error>;
pub(crate) type Parsed<'id, 'input, 'd, C, R> =
Result<Parse<'id, <C as Codec>::Head<'input, 'd, R>>, <C as Codec>::Error>;
#[must_use]
pub enum Admission<F> {
RetryInput,
Ready(F),
}
pub struct Step<T>(pub(crate) Progress<T>);
pub(crate) enum Progress<T> {
More {
advanced: bool,
target: Option<Exact>,
},
AwaitEof {
retained: Exact,
},
Blocked,
CapacityExhausted,
RetryInput,
Rejected(T),
Item(T),
}
impl<T> Step<T> {
pub const fn blocked() -> Self {
Self(Progress::Blocked)
}
pub const fn rejected(delivery: T) -> Self {
Self(Progress::Rejected(delivery))
}
pub const fn has_consumed(&self) -> bool {
match self.0 {
Progress::More { advanced, .. } => advanced,
Progress::Item(_) => true,
Progress::AwaitEof { .. }
| Progress::Blocked
| Progress::CapacityExhausted
| Progress::RetryInput
| Progress::Rejected(_) => false,
}
}
}
const _: () = assert!(
size_of::<Option<scope::End<'static, { transfer::MAX_BYTES as u32 }>>>()
== size_of::<transfer::NonZero>()
);
pub trait Codec {
type Head<'input, 'd, R: buffer::Cursor>
where
R: 'input,
'd: 'input;
type Error;
type Staging: staging::Policy;
fn staging(&self) -> <Self::Staging as staging::Policy>::Spec;
}
pub trait Stateless: Codec {
fn parse<'id, 'input, 'd, R: buffer::Cursor + hold::raw::Retain<'d>>(
&self,
input: Input<'id, 'input, 'd, R>,
) -> Parsed<'id, 'input, 'd, Self, R>
where
'd: 'input;
}
pub trait Stateful: Codec {
type State<'d>;
type Storage<S>;
type Preview<'a>;
type Outcome<'d>;
fn state<'d>(&self, budget: resident::Budget<'d>) -> Self::State<'d>;
fn storage<'d, S>(&self, source: S, state: &Self::State<'d>) -> Self::Storage<S>;
fn source<S: buffer::raw::Source>(storage: &Self::Storage<S>) -> &S;
fn edit<S>(storage: &mut Self::Storage<S>) -> storage::Edit<'_, S>;
fn restart<'a, 'd, S>(
&self,
storage: &'a mut Self::Storage<S>,
state: &Self::State<'d>,
) -> storage::Edit<'a, S>;
fn decode<'d, S, T, F>(
&self,
storage: &mut Self::Storage<S>,
state: &mut Self::State<'d>,
budget: &resident::Budget<'d>,
limit: staging::Limit,
admit: impl FnOnce(Result<Self::Preview<'_>, &Self::Error>) -> Admission<F>,
) -> Step<T>
where
S: buffer::Cursor + hold::raw::Retain<'d> + buffer::raw::Consume,
T: response::Outcome,
F: FnOnce(Result<Self::Outcome<'d>, Self::Error>, &mut Self::State<'d>) -> T::Accepted;
fn finish<'slot, 'id, 'd, S, T, F>(
&self,
input: storage::Owner<'slot, 'id, Self::Storage<S>, Self::State<'d>>,
budget: &resident::Budget<'d>,
limit: staging::Limit,
admit: impl FnOnce(Result<Self::Preview<'_>, &Self::Error>) -> Admission<F>,
) -> Finished<storage::Owner<'slot, 'id, Self::Storage<S>, Self::State<'d>>, T>
where
S: buffer::Cursor + hold::raw::Retain<'d> + buffer::raw::Consume,
T: response::Outcome,
F: FnOnce(Result<Self::Outcome<'d>, Self::Error>, &mut Self::State<'d>) -> T::Accepted;
}
#[derive(Clone, Copy)]
#[repr(transparent)]
pub(crate) struct Exact(num::NonZero<u32>);
impl Exact {
const fn from_valid(target: usize) -> Self {
Self(num::NonZero::<u32>::MIN.saturating_add(target as u32 - 1))
}
pub(in crate::client::session) const fn count(self) -> num::NonZero<u32> {
self.0
}
}