use o3::buffer::resident::bound;
use crate::link::egress::{
self, Charge, Excess, NonEmpty, Rejected,
data::{self, Bound, compose},
load,
};
pub(in crate::link::egress) mod charge;
pub(in crate::link::egress) mod empty;
pub(in crate::link::egress) mod nonempty;
pub(in crate::link::egress) mod rejected;
#[derive(Debug)]
pub struct Load<B> {
value: B,
charge: Charge,
}
impl<B> Load<B> {
pub fn new<'d>(value: B) -> Self
where
B: data::raw::Payload<'d>,
{
let charge = Charge::of(&value);
Self { value, charge }
}
pub const fn charge(&self) -> Charge {
self.charge
}
pub const fn as_inner(&self) -> &B {
&self.value
}
pub fn into_inner(self) -> B {
self.value
}
pub fn try_nonempty(self) -> Result<NonEmpty<B>, egress::Rejected<Self, load::Error>> {
let Self { value, charge } = self;
let geometry = match charge.try_geometry() {
Ok(geometry) => geometry,
Err(reason) => {
return Err(Rejected::new(Self::from_parts(value, charge), reason));
}
};
Ok(NonEmpty::new(value, geometry.wire(), geometry.resident()))
}
pub fn try_bound<G: bound::Bound>(self) -> Result<Load<Bound<B, G>>, Excess<B>> {
if let bound::Limit::AtMost(maximum) = G::LIMIT
&& self.charge.resident().is_excess(maximum)
{
return Err(Excess {
load: self,
maximum,
});
}
let (value, charge) = self.into_parts();
Ok(Load::from_parts(Bound::from_inner(value), charge))
}
pub fn unbounded(self) -> Load<Bound<B, bound::Unbounded>> {
let (value, charge) = self.into_parts();
Load::from_parts(Bound::from_inner(value), charge)
}
pub fn into_left<R>(self) -> Load<compose::Either<B, R>> {
let (value, charge) = self.into_parts();
Load::from_parts(compose::Either::Left(value), charge)
}
pub fn into_right<L>(self) -> Load<compose::Either<L, B>> {
let (value, charge) = self.into_parts();
Load::from_parts(compose::Either::Right(value), charge)
}
pub fn tagged<K>(self, tag: K) -> Load<compose::Tagged<B, K>> {
let (value, charge) = self.into_parts();
Load::from_parts(compose::Tagged::new(value, tag), charge)
}
pub(in crate::link) fn into_parts(self) -> (B, Charge) {
(self.value, self.charge)
}
pub(in crate::link) const fn from_parts(value: B, charge: Charge) -> Self {
Self { value, charge }
}
}
impl<B, G> Load<Bound<B, G>> {
pub fn bound_left<R>(self) -> Load<Bound<compose::Either<B, R>, G>> {
let (value, charge) = self.into_parts();
Load::from_parts(
Bound::from_inner(compose::Either::Left(value.into_inner())),
charge,
)
}
}
impl<L, R> Load<compose::Either<L, R>> {
pub fn split(self) -> compose::Either<Load<L>, Load<R>> {
let (value, charge) = self.into_parts();
match value {
compose::Either::Left(value) => compose::Either::Left(Load::from_parts(value, charge)),
compose::Either::Right(value) => {
compose::Either::Right(Load::from_parts(value, charge))
}
}
}
}