use std::fmt::Display;
use std::hash::Hash;
use std::ops::{Add, AddAssign, Sub, SubAssign};
#[derive(Clone, Debug, PartialOrd, Copy)]
pub enum Value {
Bool(bool),
I64(i64),
F64(f64),
}
impl From<i64> for Value {
fn from(value: i64) -> Self {
Value::I64(value)
}
}
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value::F64(value)
}
}
impl From<bool> for Value {
fn from(value: bool) -> Self {
Value::Bool(value)
}
}
impl Hash for Value {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
core::mem::discriminant(self).hash(state);
match self {
Value::Bool(b) => b.hash(state),
Value::I64(i) => i.hash(state),
Value::F64(f) => f.to_bits().hash(state),
}
}
}
impl PartialEq for Value {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Bool(l0), Self::Bool(r0)) => l0 == r0,
(Self::I64(l0), Self::I64(r0)) => l0 == r0,
(Self::F64(l0), Self::F64(r0)) => l0 == r0,
_ => false,
}
}
}
impl Eq for Value {}
impl Value {
pub fn distance(&self, other: &Value) -> u64 {
match (self, other) {
(Value::Bool(lhs), Value::Bool(rhs)) => {
if lhs == rhs {
0
} else {
1
}
},
(Value::I64(lhs), Value::I64(rhs)) => (lhs - rhs).unsigned_abs(),
(Value::F64(lhs), Value::F64(rhs)) => (lhs - rhs).abs() as u64,
_ => panic!("Cannot calculate distance between different Value types"),
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bool(v) => {
write!(f, "Value:Bool({v})")
},
Self::I64(v) => {
write!(f, "Value:I64({v})")
},
Self::F64(v) => {
write!(f, "Value:F64({v})")
},
}
}
}
impl Add for Value {
type Output = Value;
fn add(self, other: Value) -> Value {
match (self, other) {
(Value::I64(a), Value::I64(b)) => Value::I64(a + b),
(Value::F64(a), Value::F64(b)) => Value::F64(a + b),
_ => panic!("Unsupported addition between Datum variants, {self:?} - {other:?}"),
}
}
}
impl Sub for Value {
type Output = Value;
fn sub(self, other: Value) -> Value {
match (self, other) {
(Value::I64(a), Value::I64(b)) => Value::I64(a - b),
(Value::F64(a), Value::F64(b)) => Value::F64(a - b),
_ => panic!("Unsupported negation between Datum variants, {self:?} - {other:?}"),
}
}
}
impl AddAssign for Value {
fn add_assign(&mut self, rhs: Self) {
match self {
Self::I64(v1) => match rhs {
Self::I64(v2) => {
*v1 += v2;
},
_ => unimplemented!("Unimplemented! Tried to add {self:?} to {rhs:?}"),
},
Self::F64(v1) => match rhs {
Self::F64(v2) => {
*v1 += v2;
},
_ => unimplemented!("Unimplemented! Tried to add {self:?} to {rhs:?}"),
},
_ => unimplemented!("Unimplemented! Tried to add {self:?} to {rhs:?}"),
}
}
}
impl SubAssign for Value {
fn sub_assign(&mut self, rhs: Self) {
match self {
Self::I64(v1) => match rhs {
Self::I64(v2) => {
*v1 -= v2;
},
_ => unimplemented!("Unimplemented! Tried to subtract {rhs:?} from {self:?}"),
},
Self::F64(v1) => match rhs {
Self::F64(v2) => {
*v1 -= v2;
},
_ => unimplemented!("Unimplemented! Tried to subtract {rhs:?} from {self:?}"),
},
_ => unimplemented!("Unimplemented! Tried to subtract {rhs:?} from {self:?}"),
}
}
}