use std::collections::HashMap;
use std::fmt;
#[derive(Clone, Debug, PartialEq)]
pub enum SoftValue {
Int(i64),
Float(f64),
Bool(bool),
Str(String),
List(Vec<SoftValue>),
Map(HashMap<String, SoftValue>),
None,
}
impl fmt::Display for SoftValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SoftValue::Int(i) => write!(f, "{}", i),
SoftValue::Float(x) => write!(f, "{}", x),
SoftValue::Bool(b) => write!(f, "{}", b),
SoftValue::Str(s) => write!(f, "{}", s),
SoftValue::List(v) => {
write!(f, "[")?;
let mut first = true;
for e in v {
if !first { write!(f, ", ")?; }
write!(f, "{}", e)?;
first = false;
}
write!(f, "]")
}
SoftValue::Map(m) => {
write!(f, "{{")?;
let mut first = true;
for (k, v) in m {
if !first { write!(f, ", ")?; }
write!(f, "\"{}\": {}", k, v)?;
first = false;
}
write!(f, "}}")
}
SoftValue::None => write!(f, "None"),
}
}
}
impl From<i64> for SoftValue {
fn from(i: i64) -> Self { SoftValue::Int(i) }
}
impl From<f64> for SoftValue {
fn from(fv: f64) -> Self { SoftValue::Float(fv) }
}
impl From<&str> for SoftValue {
fn from(s: &str) -> Self { SoftValue::Str(s.to_string()) }
}
impl From<String> for SoftValue {
fn from(s: String) -> Self { SoftValue::Str(s) }
}
impl std::ops::Add for SoftValue {
type Output = SoftValue;
fn add(self, rhs: SoftValue) -> SoftValue {
match (self, rhs) {
(SoftValue::Int(a), SoftValue::Int(b)) => SoftValue::Int(a + b),
(SoftValue::Int(a), SoftValue::Float(b)) => SoftValue::Float(a as f64 + b),
(SoftValue::Float(a), SoftValue::Int(b)) => SoftValue::Float(a + b as f64),
(SoftValue::Float(a), SoftValue::Float(b)) => SoftValue::Float(a + b),
(SoftValue::Str(a), SoftValue::Str(b)) => SoftValue::Str(a + &b),
(a, b) => {
SoftValue::List(vec![a, b])
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn softvalue_add_int_float() {
let a = SoftValue::Int(2);
let b = SoftValue::Float(3.5);
assert_eq!(a + b, SoftValue::Float(5.5));
}
#[test]
fn softvalue_str_concat() {
let a = SoftValue::Str("hello".to_string());
let b = SoftValue::Str(" world".to_string());
assert_eq!(a + b, SoftValue::Str("hello world".to_string()));
}
#[test]
fn softvalue_fallback_list() {
let a = SoftValue::Int(1);
let b = SoftValue::Str("two".to_string());
assert_eq!(a + b, SoftValue::List(vec![SoftValue::Int(1), SoftValue::Str("two".to_string())]));
}
}