soft_rust_runtime 0.1.1

Runtime support library for soft_rust macros
Documentation
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) => {
                // Fallback: produce a list of the two
                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());
        // heterogeneous add falls back to a list of the two values
        assert_eq!(a + b, SoftValue::List(vec![SoftValue::Int(1), SoftValue::Str("two".to_string())]));
    }
}