use crate::{Currency, CurrencyLocale};
use std::ops::{Add, AddAssign};
impl<L, T> Add<T> for Currency<L>
where
T: Into<Currency<L>>,
L: CurrencyLocale,
{
type Output = Self;
fn add(self, rhs: T) -> Self::Output {
let rhs = rhs.into();
match (self.negative, rhs.negative) {
(true, true) | (false, false) => {
Self::new(self.negative, self.amount + rhs.amount, self.locale)
}
(true, false) | (false, true) => {
let negative = self.amount.checked_sub(rhs.amount).is_none();
let amount = if negative {
rhs.amount - self.amount
} else {
self.amount - rhs.amount
};
Self::new(self.negative ^ negative, amount, self.locale)
}
}
}
}
impl<L, T> AddAssign<T> for Currency<L>
where
T: Into<Currency<L>>,
L: CurrencyLocale,
{
fn add_assign(&mut self, rhs: T) {
let rhs = rhs.into();
match (self.negative, rhs.negative) {
(false, false) | (true, true) => self.amount += rhs.amount,
(false, true) | (true, false) => {
self.negative ^= self.amount.checked_sub(rhs.amount).is_none();
if self.negative {
self.amount = rhs.amount - self.amount
} else {
self.amount -= rhs.amount
};
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[derive(Clone, Copy, Default, Debug, PartialEq)]
enum CurrencyL {
#[default]
De,
}
impl CurrencyLocale for CurrencyL {
fn separator(&self) -> char {
','
}
fn thousand_separator(&self) -> char {
'.'
}
fn currency_symbol(&self) -> &'static str {
"€"
}
}
#[test]
fn add_currencies() {
let curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
let curr2 = Currency::new(false, 24_000_99, CurrencyL::De);
let expected = curr1 + curr2;
assert_eq!(expected, Currency::new(false, 48_001_21, CurrencyL::De));
}
#[test]
fn add_f32_to_currency() {
let curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
let expected = curr1 + 24_000.99_f32;
assert_eq!(expected, Currency::new(false, 48_001_21, CurrencyL::De));
}
#[test]
fn add_assign_usize() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
curr1 += 1usize;
assert_eq!(curr1, Currency::new(false, 24_000_23, CurrencyL::De));
}
#[test]
fn add_assign_f32() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
curr1 += 1.12f32;
assert_eq!(curr1, Currency::new(false, 24_001_34, CurrencyL::De));
}
#[test]
fn add_assign_negative_f32() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
curr1 += -1.12f32;
assert_eq!(curr1, Currency::new(false, 23_999_10, CurrencyL::De));
}
#[test]
fn add_assign_f64() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
curr1 += 1.12f64;
assert_eq!(curr1, Currency::new(false, 24_001_34, CurrencyL::De));
}
#[test]
fn add_assign_negative_f64() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
curr1 += -1.12f64;
assert_eq!(curr1, Currency::new(false, 23_999_10, CurrencyL::De));
}
#[test]
fn add_assign_currency() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
let curr2 = Currency::new(false, 24_000_99, CurrencyL::De);
curr1 += curr2;
assert_eq!(curr1, Currency::new(false, 48_001_21, CurrencyL::De));
}
#[test]
fn add_assign_negative_currency() {
let mut curr1 = Currency::new(false, 24_000_22, CurrencyL::De);
let curr2 = Currency::new(true, 1_22, CurrencyL::De);
curr1 += curr2;
assert_eq!(curr1, Currency::new(false, 23_999_00, CurrencyL::De));
}
}