use std::{fmt::Display, ops::{Add, AddAssign, Mul, MulAssign, Sub, SubAssign}, str::FromStr};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Chips(u64);
impl Chips {
pub fn new(value: u64) -> Self {
Self(value)
}
}
impl Display for Chips {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if f.alternate() {
write!(f, "{:}", self.0)
} else {
write!(f, "${:}", self.0)
}
}
}
impl From<u64> for Chips {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<Chips> for u64 {
fn from(value: Chips) -> Self {
value.0
}
}
impl FromStr for Chips {
type Err = std::num::ParseIntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s.starts_with('$') {
Ok(Self(s[1..].parse::<u64>()?))
} else {
Ok(Self(s.parse::<u64>()?))
}
}
}
impl Add<Chips> for Chips {
type Output = Chips;
fn add(self, other: Chips) -> Self::Output {
Self(self.0 + other.0)
}
}
impl AddAssign<Chips> for Chips {
fn add_assign(&mut self, other: Chips) {
*self = *self + other;
}
}
impl Sub<Chips> for Chips {
type Output = Chips;
fn sub(self, other: Chips) -> Self::Output {
Self(self.0 - other.0)
}
}
impl SubAssign<Chips> for Chips {
fn sub_assign(&mut self, other: Chips) {
*self = *self - other;
}
}
impl Mul<u64> for Chips {
type Output = Chips;
fn mul(self, other: u64) -> Self::Output {
Self(self.0 * other)
}
}
impl MulAssign<u64> for Chips {
fn mul_assign(&mut self, other: u64) {
*self = *self * other;
}
}
pub fn withdraw_capped(from: &mut Chips, amount: Chips) -> (Chips, bool) {
let actual = amount.min(*from);
*from -= actual;
let depleted = *from == 0.into();
(actual, depleted)
}
pub fn deposit(to: &mut Chips, amount: Chips) {
*to += amount;
}
pub fn transfer_capped(to: &mut Chips, from: &mut Chips, amount: Chips) -> (Chips, bool) {
let (actual, depleted) = withdraw_capped(from, amount);
deposit(to, actual);
(actual, depleted)
}