null-kane 3.0.0

currency crate with the option to add your own currency localization logic
Documentation
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));
    }
}