use std::fmt;
use std::ops::{Add, Neg, Sub};
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum Number {
Int(i32),
Float(f32),
}
impl Number {
pub fn as_f32(&self) -> f32 {
match *self {
Number::Int(val) => val as f32,
Number::Float(val) => val,
}
}
}
impl Into<Number> for i32 {
fn into(self) -> Number {
Number::Int(self)
}
}
impl Into<Number> for f32 {
fn into(self) -> Number {
Number::Float(self)
}
}
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Number::Int(val) => write!(f, "{}", val),
Number::Float(val) => write!(f, "{}", val),
}
}
}
impl Add for Number {
type Output = Self;
fn add(self, other: Self) -> Self {
match (self, other) {
(Number::Int(i), Number::Int(j)) => Number::Int(i + j),
(Number::Float(i), Number::Int(j)) => Number::Float(i + j as f32),
(Number::Int(i), Number::Float(j)) => Number::Float(i as f32 + j),
(Number::Float(i), Number::Float(j)) => Number::Float(i + j),
}
}
}
impl Sub for Number {
type Output = Self;
fn sub(self, other: Self) -> Self {
match (self, other) {
(Number::Int(i), Number::Int(j)) => Number::Int(i - j),
(Number::Float(i), Number::Int(j)) => Number::Float(i - j as f32),
(Number::Int(i), Number::Float(j)) => Number::Float(i as f32 - j),
(Number::Float(i), Number::Float(j)) => Number::Float(i - j),
}
}
}
impl Neg for Number {
type Output = Self;
fn neg(self) -> Self {
match self {
Number::Int(val) => Number::Int(-val),
Number::Float(val) => Number::Float(-val),
}
}
}
#[cfg(test)]
mod tests {
use crate::utils::Number;
#[test]
fn add() {
let i1 = Number::Int(1);
let i2 = Number::Int(2);
let f1 = Number::Float(0.5);
let f2 = Number::Float(1.5);
assert_eq!(i1 + i2, Number::Int(3));
assert_eq!(f1 + i2, Number::Float(2.5));
assert_eq!(i2 + f2, Number::Float(3.5));
assert_eq!(f1 + f2, Number::Float(2.));
}
#[test]
fn sub() {
let i1 = Number::Int(1);
let i2 = Number::Int(2);
let f1 = Number::Float(0.5);
let f2 = Number::Float(1.5);
assert_eq!(i2 - i1, Number::Int(1));
assert_eq!(i2 - f1, Number::Float(1.5));
assert_eq!(i2 - f2, Number::Float(0.5));
assert_eq!(f2 - f1, Number::Float(1.));
}
#[test]
fn neg() {
let i1 = Number::Int(1);
let f1 = Number::Float(0.5);
assert_eq!(-i1, Number::Int(-1));
assert_eq!(-f1, Number::Float(-0.5));
}
}