use std::ops::{Add, AddAssign, Mul, Sub, SubAssign};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Default, Clone, Debug, Copy)]
pub struct Euros {
total_cents: i32,
}
pub enum Currency {
Euros(f32),
Nok(f32),
}
impl Currency {
pub const NOK_RATE: f32 = 0.090;
}
impl TryFrom<String> for Currency {
type Error = ();
fn try_from(value: String) -> Result<Self, Self::Error> {
if let Some(value) = value.strip_prefix("kr") {
let float = value.parse::<f32>().map_err(|_| ())?;
Ok(Currency::Nok(float))
} else {
let float = value.parse::<f32>().map_err(|_| ())?;
Ok(Currency::Euros(float))
}
}
}
pub struct Kroner(pub f32);
impl From<Currency> for Euros {
fn from(value: Currency) -> Self {
match value {
Currency::Nok(val) => (val * Currency::NOK_RATE).into(),
Currency::Euros(euros) => euros.into(),
}
}
}
impl Euros {
pub fn new(euros: i32, cents: i32) -> Self {
Self {
total_cents: euros * 100 + cents,
}
}
pub fn print(&self) -> String {
format!("€{}.{}", self.euros(), self.cents())
}
pub fn as_negative(self) -> Self {
Self {
total_cents: -self.total_cents,
}
}
pub fn euros(&self) -> i32 {
self.total_cents / 100
}
pub fn total_cents(&self) -> i32 {
self.total_cents
}
pub fn cents(&self) -> i32 {
self.total_cents % 100
}
}
impl From<f32> for Euros {
fn from(value: f32) -> Self {
let total_cents = (value * 100.0) as i32;
Self { total_cents }
}
}
impl From<Euros> for f32 {
fn from(value: Euros) -> Self {
value.total_cents as f32 / 100.0
}
}
impl Add for Euros {
type Output = Self;
fn add(self, other: Self) -> Self {
Euros {
total_cents: self.total_cents + other.total_cents,
}
}
}
impl Sub for Euros {
type Output = Self;
fn sub(self, other: Self) -> Self {
Euros {
total_cents: self.total_cents - other.total_cents,
}
}
}
impl Mul<i32> for Euros {
type Output = Self;
fn mul(self, multiplier: i32) -> Self {
Euros {
total_cents: self.total_cents * multiplier,
}
}
}
impl SubAssign for Euros {
fn sub_assign(&mut self, other: Self) {
self.total_cents -= other.total_cents;
}
}
impl AddAssign for Euros {
fn add_assign(&mut self, other: Self) {
self.total_cents += other.total_cents;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testing() {
let kroner = Currency::Nok(100.);
let euros: Euros = kroner.into();
dbg!(euros.print());
}
}