use super::*;
define_derive_deftly! {
BookkeptQty:
${defcond BOMB not(tmeta(allow_nonzero_drop))}
impl BookkeepableQty for $ttype {
const ZERO: $ttype = $ttype {
raw: Qty(0),
${if BOMB {
bomb: DropBombCondition::new_armed(),
}}
};
fn as_raw(&self) -> Qty {
self.raw
}
}
impl<Rhs: BookkeepableQty> PartialEq<Rhs> for $ttype {
fn eq(&self, other: &Rhs) -> bool {
self.as_raw().eq(&other.as_raw())
}
}
impl<Rhs: BookkeepableQty> PartialOrd<Rhs> for $ttype {
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
self.as_raw().partial_cmp(&other.as_raw())
}
}
impl DefaultExtTake for $ttype {}
impl BookkeptQty for $ttype {
fn from_raw(q: Qty) -> Self {
$ttype {
raw: q,
${if BOMB {
bomb: DropBombCondition::new_armed(),
}}
}
}
fn into_raw(mut self) -> Qty {
mem::replace(&mut self.raw, Qty(0))
}
}
assert_not_impl_any!($ttype: Clone, Into<Qty>, From<Qty>);
${if BOMB {
#[cfg(test)]
impl Drop for $ttype {
fn drop(&mut self) {
drop_bomb_disarm_assert!(self.bomb, self.raw == Qty(0));
}
}
}}
}
pub(super) trait BookkeepableQty: Default {
const ZERO: Self;
fn as_raw(&self) -> Qty;
}
trait BookkeptQty: BookkeepableQty + DefaultExtTake {
fn from_raw(q: Qty) -> Self;
fn into_raw(self) -> Qty;
}
impl BookkeepableQty for Qty {
const ZERO: Qty = Qty(0);
fn as_raw(&self) -> Qty {
*self
}
}
#[derive(Default, Debug, Deftly, derive_more::Display)]
#[derive_deftly(BookkeptQty)]
#[deftly(allow_nonzero_drop)] pub(super) struct TotalQty {
raw: Qty,
}
#[derive(Default, Debug, Deftly, derive_more::Display)]
#[derive_deftly(BookkeptQty)]
#[display("{raw}")]
pub(super) struct ParticipQty {
raw: Qty,
bomb: DropBombCondition,
}
#[derive(Default, Debug, Deftly, derive_more::Display)]
#[derive_deftly(BookkeptQty)]
#[display("{raw}")]
#[must_use]
pub(super) struct ClaimedQty {
raw: Qty,
bomb: DropBombCondition,
}
impl TotalQty {
pub(super) fn claim(&mut self, p_used: &mut ParticipQty, want: Qty) -> Option<ClaimedQty> {
let new_self = self.raw.checked_add(*want)?;
if new_self == usize::MAX {
return None;
}
let new_p_used = p_used.raw.checked_add(*want)?;
self.raw = Qty(new_self);
p_used.raw = Qty(new_p_used);
Some(ClaimedQty::from_raw(want))
}
pub(super) fn release(&mut self, p_used: &mut ParticipQty, have: ClaimedQty) {
let have = have.into_raw();
*p_used.raw = p_used.raw.saturating_sub(*have);
if self.raw != Qty::MAX {
*self.raw = self.raw.saturating_sub(*have);
}
}
pub(super) fn set_poisoned(&mut self) {
self.raw = Qty::MAX;
}
}
impl ClaimedQty {
pub(super) fn split_off(&mut self, want: Qty) -> Option<ClaimedQty> {
let new_self = self.raw.checked_sub(*want)?;
*self.raw = new_self;
Some(ClaimedQty::from_raw(want))
}
pub(super) fn merge_into(&mut self, have: ClaimedQty) {
let have = have.into_raw();
*self.raw = self.raw.saturating_add(*have);
}
#[allow(clippy::unnecessary_wraps)] pub(super) fn claim_return_to_participant(self) -> crate::Result<()> {
let _: Qty = self.into_raw();
Ok(())
}
pub(super) fn release_got_from_participant(got: Qty) -> Self {
ClaimedQty::from_raw(got)
}
pub(super) fn dispose_participant_destroyed(mut self) {
let _: Qty = mem::take(&mut self).into_raw();
}
}
impl ParticipQty {
pub(super) fn for_participant_teardown(&self) -> ClaimedQty {
ClaimedQty::from_raw(self.as_raw())
}
}