use crate::{Currency, CurrencyLocale};
use std::ops::{Add, Sub, SubAssign};
impl<L, T> Sub<T> for Currency<L>
where
T: Into<Currency<L>>,
L: CurrencyLocale + Default,
{
type Output = Self;
fn sub(self, rhs: T) -> Self::Output {
let rhs = rhs.into();
match (self.negative, rhs.negative) {
(true | false, true) => self.add(Self::new(false, rhs.full, rhs.part, rhs.locale)),
(true, false) => {
let new_part = self.part + rhs.part;
let new_full = self.full + rhs.full + usize::from(new_part >= 100);
Self::new(false, new_full, new_part % 100, self.locale)
}
(false, false) => {
let decrease_full = self.part.checked_sub(rhs.part).is_none();
let decrement = rhs.full + usize::from(decrease_full);
let mut negative = false;
let (new_full, new_part) = if decrement > self.full {
negative = true;
(rhs.full - self.full, rhs.part - self.part)
} else {
(self.full - decrement, self.part - rhs.part)
};
Self::new(negative, new_full, new_part, self.locale)
}
}
}
}
impl<L, T> SubAssign<T> for Currency<L>
where
T: Into<Currency<L>>,
L: CurrencyLocale + Default + Clone,
{
fn sub_assign(&mut self, rhs: T) {
let rhs = rhs.into();
match (self.negative, rhs.negative) {
(true | false, true) => {
let new = rhs
.clone()
.add(Self::new(false, rhs.full, rhs.part, L::default()));
self.negative = new.negative;
self.full = new.full;
self.part = new.part;
}
(true, false) => {
let new_part = self.part + rhs.part;
let new_full = self.full + rhs.full + usize::from(new_part >= 100);
self.part = new_part % 100;
self.full = new_full;
}
(false, false) => {
let decrease_full = self.part.checked_sub(rhs.part).is_none();
let decrement = rhs.full + usize::from(decrease_full);
let mut negative = false;
let (new_full, new_part) = if decrement > self.full {
negative = true;
(
rhs.full - self.full - usize::from(decrease_full),
rhs.part - self.part,
)
} else {
(self.full - decrement, self.part - rhs.part)
};
let new = Self::new(negative, new_full, new_part, self.locale.clone());
self.negative = new.negative;
self.full = new.full;
self.part = new.part;
}
}
}
}