use anyhow::anyhow; use chrono::{DateTime, Utc}; use std::cmp::Ordering; use std::collections::HashMap; use std::fmt::{Display, Formatter}; use std::hash::{Hash, Hasher}; use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Not, Shl, Shr, Sub}; #[derive(Debug, Clone)] pub struct StructDefinition { fields: Vec, } #[derive(Debug, Clone)] pub struct StructValue { definition: StructDefinition, fields: Vec, } impl StructValue { pub fn new(definition: StructDefinition) -> Self { Self { definition, fields: Vec::new(), } } } impl Display for StructValue { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { for (i, field) in self.definition.fields.iter().enumerate() { write!(f, "{}: {}", field, self.fields[i])?; } Ok(()) } } #[derive(Debug, Clone)] pub enum Value { U32(u32), I32(i32), U64(u64), I64(i64), F32(f32), F64(f64), String(String), Char(char), Bool(bool), Date(DateTime), Enum, List(Vec), Map(HashMap), Struct(StructValue), Error(String), Void, } impl Into for i32 { fn into(self) -> Value { Value::I32(self) } } impl Into for i64 { fn into(self) -> Value { Value::I64(self) } } impl Into for u32 { fn into(self) -> Value { Value::U32(self) } } impl Into for u64 { fn into(self) -> Value { Value::U64(self) } } impl Into for f32 { fn into(self) -> Value { Value::F32(self) } } impl Into for f64 { fn into(self) -> Value { Value::F64(self) } } impl Into for &str { fn into(self) -> Value { Value::String(self.to_string()) } } impl From for Value { fn from(s: String) -> Self { Value::String(s.clone()) } } impl From<&String> for Value { fn from(s: &String) -> Self { Value::String(s.clone()) } } impl Into for char { fn into(self) -> Value { Value::Char(self) } } impl Into for bool { fn into(self) -> Value { Value::Bool(self) } } impl Into for DateTime { fn into(self) -> Value { Value::Date(self) } } impl Display for Value { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match &self { &Value::U32(v) => write!(f, "{}", v), &Value::U64(v) => write!(f, "{}", v), &Value::String(v) => write!(f, "{}", v), &Value::Bool(v) => write!(f, "{}", v), &Value::I32(v) => write!(f, "{}", v), &Value::I64(v) => write!(f, "{}", v), &Value::F32(v) => write!(f, "{}", v), &Value::F64(v) => write!(f, "{}", v), &Value::Char(v) => write!(f, "{}", v), &Value::Date(v) => write!(f, "{}", v), &Value::Enum => write!(f, "enum"), &Value::Struct(v) => write!(f, "{}", v), &Value::List(v) => write!(f, "{:?}", v), &Value::Map(v) => write!(f, "map"), &Value::Error(v) => write!(f, "{}", v), &Value::Void => write!(f, "()"), } } } impl Neg for &Value { type Output = anyhow::Result; fn neg(self) -> Self::Output { match self { Value::I32(i) => Ok(Value::I32(-i)), Value::I64(i) => Ok(Value::I64(-i)), Value::F32(i) => Ok(Value::F32(-i)), Value::F64(i) => Ok(Value::F64(-i)), _ => Err(anyhow!("Cannot negate")), } } } impl Add<&Value> for &Value { type Output = anyhow::Result; fn add(self, rhs: &Value) -> Self::Output { if let Value::List(s) = self { let mut copy = s.clone(); copy.push(rhs.clone()); Ok(Value::List(copy)) } else if let Value::List(rhs) = rhs { let mut copy = rhs.clone(); copy.push(self.clone()); Ok(Value::List(copy)) } else { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a + b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a + b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a + b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a + b)), (Value::F32(a), Value::F32(b)) => Ok(Value::F32(a + b)), (Value::F64(a), Value::F64(b)) => Ok(Value::F64(a + b)), (Value::String(s), Value::I32(i)) => Ok(format!("{}{}", s, i).into()), (Value::String(s), Value::I64(i)) => Ok(format!("{}{}", s, i).into()), (Value::String(s), Value::U32(u)) => Ok(Value::String(format!("{}{}", s, u))), (Value::String(s), Value::U64(u)) => Ok(Value::String(format!("{}{}", s, u))), (Value::String(s), Value::F32(f)) => Ok(Value::String(format!("{}{}", s, f))), (Value::String(s), Value::F64(f)) => Ok(Value::String(format!("{}{}", s, f))), (Value::String(s), Value::Bool(b)) => Ok(Value::String(format!("{}{}", s, b))), (Value::String(s), Value::Char(c)) => Ok(Value::String(format!("{}{}", s, c))), (Value::String(s1), Value::String(s2)) => { Ok(Value::String(format!("{}{}", s1, s2))) } (Value::String(s1), Value::Map(m)) => Ok(Value::String(format!("{}{:?}", s1, m))), //enum? _ => Err(anyhow!("Cannot add")), } } } } impl Sub<&Value> for &Value { type Output = anyhow::Result; fn sub(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a - b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a - b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a - b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a - b)), (Value::F32(a), Value::F32(b)) => Ok(Value::F32(a - b)), (Value::F64(a), Value::F64(b)) => Ok(Value::F64(a - b)), //enum? _ => Err(anyhow!("Cannot subtract")), } } } impl Mul<&Value> for &Value { type Output = anyhow::Result; fn mul(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a * b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a * b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a * b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a * b)), (Value::F32(a), Value::F32(b)) => Ok(Value::F32(a * b)), (Value::F64(a), Value::F64(b)) => Ok(Value::F64(a * b)), _ => Err(anyhow!("Cannot multiply")), } } } impl Div<&Value> for &Value { type Output = anyhow::Result; fn div(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a / b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a / b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a / b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a / b)), (Value::F32(a), Value::F32(b)) => Ok(Value::F32(a / b)), (Value::F64(a), Value::F64(b)) => Ok(Value::F64(a / b)), _ => Err(anyhow!("Cannot divide")), } } } impl BitAnd<&Value> for &Value { type Output = anyhow::Result; fn bitand(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a & b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a & b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a & b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a & b)), _ => Err(anyhow!("Cannot do bitwise-and on")), } } } impl BitOr<&Value> for &Value { type Output = anyhow::Result; fn bitor(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a | b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a | b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a | b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a | b)), _ => Err(anyhow!("Cannot do bitwise-or on")), } } } impl BitXor<&Value> for &Value { type Output = anyhow::Result; fn bitxor(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a ^ b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a ^ b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a ^ b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a ^ b)), _ => Err(anyhow!("Cannot do bitwise-xor on")), } } } impl Not for &Value { type Output = anyhow::Result; fn not(self) -> Self::Output { match (self) { Value::Bool(b) => Ok(Value::Bool(!b)), Value::I32(i32) => Ok(Value::I32(!i32)), Value::I64(i64) => Ok(Value::I64(!i64)), Value::U32(u32) => Ok(Value::U32(!u32)), Value::U64(u64) => Ok(Value::U64(!u64)), _ => Err(anyhow!("Cannot calculate not")), } } } impl Shl<&Value> for &Value { type Output = anyhow::Result; fn shl(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a << b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a << b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a << b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a << b)), _ => Err(anyhow!("Cannot shift left on")), } } } impl Shr<&Value> for &Value { type Output = anyhow::Result; fn shr(self, rhs: &Value) -> Self::Output { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Ok(Value::I32(a >> b)), (Value::I64(a), Value::I64(b)) => Ok(Value::I64(a >> b)), (Value::U32(a), Value::U32(b)) => Ok(Value::U32(a >> b)), (Value::U64(a), Value::U64(b)) => Ok(Value::U64(a >> b)), _ => Err(anyhow!("Cannot shift right on")), } } } impl PartialEq for Value { fn eq(&self, rhs: &Self) -> bool { match (self, rhs) { (Value::I32(a), Value::I32(b)) => a == b, (Value::I64(a), Value::I64(b)) => a == b, (Value::U32(a), Value::U32(b)) => a == b, (Value::U64(a), Value::U64(b)) => a == b, (Value::F32(a), Value::F32(b)) => a == b, (Value::F64(a), Value::F64(b)) => a == b, (Value::Bool(a), Value::Bool(b)) => a == b, (Value::String(a), Value::String(b)) => a == b, (Value::Char(a), Value::Char(b)) => a == b, (Value::Date(a), Value::Date(b)) => a == b, // (Value::List(a), Value::List(b)) => a == b, // (Value::Map(a), Value::Map(b)) => { // let mut equal = true; // for (k, v) in a.iter() { // if !b.contains_key(k) || b.get(k).unwrap() != v { // //safe unwrap // equal = false; // break; // } // } // equal // } // struct? _ => false, //? } } } impl Eq for Value {} impl PartialOrd for Value { fn partial_cmp(&self, rhs: &Self) -> Option { match (self, rhs) { (Value::I32(a), Value::I32(b)) => Some(a.partial_cmp(b)?), (Value::I64(a), Value::I64(b)) => Some(a.partial_cmp(b)?), (Value::U32(a), Value::U32(b)) => Some(a.partial_cmp(b)?), (Value::U64(a), Value::U64(b)) => Some(a.partial_cmp(b)?), (Value::F32(a), Value::F32(b)) => Some(a.partial_cmp(b)?), (Value::F64(a), Value::F64(b)) => Some(a.partial_cmp(b)?), (Value::String(a), Value::String(b)) => Some(a.partial_cmp(b)?), (Value::Char(a), Value::Char(b)) => Some(a.partial_cmp(b)?), (Value::Date(a), Value::Date(b)) => Some(a.partial_cmp(b)?), _ => None, } } } impl Hash for Value { fn hash(&self, state: &mut H) { std::mem::discriminant(self).hash(state); // Then hash the fields match self { Value::I32(i32) => i32.hash(state), Value::I64(i64) => i64.hash(state), Value::U32(u32) => u32.hash(state), Value::U64(u64) => u64.hash(state), Value::F32(f32) => f32.to_bits().hash(state), Value::F64(f64) => f64.to_bits().hash(state), Value::String(s) => s.hash(state), Value::Char(c) => c.hash(state), Value::Bool(b) => b.hash(state), Value::Date(d) => d.hash(state), Value::List(l) => l.hash(state), _ => {} } } } // impl Ord for Value { // fn cmp(&self, rhs: &Self) -> Ordering { // self.partial_cmp(rhs).unwrap() // } // }