use std::mem;
use crate::mem::credit::fair;
#[must_use = "a detached grant must be stored or returned"]
pub struct Grant<
S: crate::mem::raw::Source<N>,
const N: usize = 1,
A: crate::mem::raw::Amount<N, S::Word> = [<S as crate::mem::raw::Source<N>>::Word; N],
> {
charge: mem::ManuallyDrop<crate::mem::raw::Charge<S, N, A>>,
}
impl<S: crate::mem::raw::Source<N>, const N: usize, A: crate::mem::raw::Amount<N, S::Word>>
From<crate::mem::raw::Charge<S, N, A>> for Grant<S, N, A>
{
fn from(charge: crate::mem::raw::Charge<S, N, A>) -> Self {
Self {
charge: mem::ManuallyDrop::new(charge),
}
}
}
impl<S: crate::mem::raw::Source<N>, const N: usize, A: crate::mem::raw::Amount<N, S::Word>>
Grant<S, N, A>
{
pub fn amount(&self) -> A {
self.charge.amount
}
pub fn into_array(self) -> Grant<S, N> {
Grant::from(crate::mem::raw::Charge::new(
self.charge.source,
self.charge.amount.get(),
))
}
pub fn try_extend(&mut self, amount: A) -> Extension<'_, S, N, A>
where
A: crate::mem::raw::Sum<N, S::Word>,
{
let charge = crate::mem::raw::Charge::try_new(self.charge.source, amount)?;
Ok(crate::mem::raw::Bound {
source: self,
proof: charge,
})
}
pub(super) unsafe fn merge_bound(&mut self, other: Self)
where
A: crate::mem::raw::Sum<N, S::Word>,
{
self.charge.amount = unsafe { A::add_raw(self.charge.amount, other.charge.amount) };
}
pub fn release(self) {
drop(mem::ManuallyDrop::into_inner(self.charge));
}
pub unsafe fn bind<P>(self, proof: P) -> crate::mem::raw::Bound<Self, P> {
crate::mem::raw::Bound {
source: self,
proof,
}
}
pub unsafe fn bind_mut<P>(&mut self, proof: P) -> crate::mem::raw::Bound<&mut Self, P> {
crate::mem::raw::Bound {
source: self,
proof,
}
}
pub fn map<P>(self, change: P) -> Grant<S, N, P::Output>
where
P: crate::mem::raw::Rebind<N, S::Word, A>,
{
unsafe { self.map_exact(change) }
}
pub fn update<P>(&mut self, change: P)
where
P: crate::mem::raw::Rebind<N, S::Word, A, Output = A>,
{
self.charge.amount = change.rebind(self.charge.amount);
}
pub(super) unsafe fn into_parts<P>(
self,
proof: P,
input: P::Input,
) -> crate::mem::raw::Partition<S, N, A, P>
where
P: crate::mem::raw::Exact<N, S::Word, A>,
{
let (left, right) = proof.parts(self.charge.amount, input);
let source = self.charge.source;
(
Grant::from(crate::mem::raw::Charge::new(source, left)),
Grant::from(crate::mem::raw::Charge::new(source, right)),
)
}
pub(super) unsafe fn map_exact<P>(self, proof: P) -> Grant<S, N, P::Output>
where
P: crate::mem::raw::ExactRebind<N, S::Word, A>,
{
Grant::from(crate::mem::raw::Charge::new(
self.charge.source,
proof.rebind(self.charge.amount),
))
}
pub(super) unsafe fn split_exact<P>(
&mut self,
proof: P,
input: P::Input,
) -> Grant<S, N, P::Right>
where
P: crate::mem::raw::Exact<N, S::Word, A, Left = A>,
{
let (rest, part) = proof.parts(self.charge.amount, input);
self.charge.amount = rest;
Grant::from(crate::mem::raw::Charge::new(self.charge.source, part))
}
}
const _: () = {
assert!(
mem::size_of::<Grant<crate::mem::raw::Lane<'static, 'static>>>()
== 3 * mem::size_of::<usize>()
);
assert!(
mem::size_of::<Grant<crate::mem::raw::Lane<'static, 'static, 2>, 2>>()
== 4 * mem::size_of::<usize>()
);
assert!(
mem::size_of::<Grant<crate::mem::raw::Lane<'static, 'static, 2, (), u32>, 2>>()
== 3 * mem::size_of::<usize>()
);
assert!(
mem::size_of::<Option<Grant<crate::mem::raw::Lane<'static, 'static, 2, (), u32>, 2>>>()
== mem::size_of::<Grant<crate::mem::raw::Lane<'static, 'static, 2, (), u32>, 2>>()
);
assert!(!mem::needs_drop::<
Grant<crate::mem::raw::Lane<'static, 'static, 2, (), u32>, 2>,
>());
};
impl<S: crate::mem::raw::Source<N>, const N: usize> Grant<S, N> {
pub fn drain(&mut self) -> Self {
let empty = Self::empty(self.charge.source);
mem::replace(self, empty)
}
pub fn empty(source: S) -> Self {
Self::from(crate::mem::raw::Charge::new(
source,
[<S::Word as crate::mem::raw::Word>::ZERO; N],
))
}
}
type Extension<'a, S, const N: usize, A> = Result<
crate::mem::raw::Bound<&'a mut Grant<S, N, A>, crate::mem::raw::Charge<S, N, A>>,
crate::mem::Rejected<A, fair::Cause<<S as crate::mem::raw::Source<N>>::Word, N>>,
>;