expy 0.0.2

Embeddable & extensible expression evaluator
Documentation
//! Serde integration tests

use claims::*;
use expy::{BinaryOp::*, Calc, Context, Expr};
use serde::{Deserialize, Deserializer};
use serde_json::{self, from_value as from_json, json, to_value as to_json};


fn from_str(s: &str) -> Result<Expr, serde_json::Error> {
    from_json(json!(s))
}

fn to_string(expr: &Expr) -> Result<String, serde_json::Error> {
    to_json(expr).map(|value| value.as_str().unwrap().to_owned())
}


#[test]
fn basic_deserialize() {
    let expr = from_str("2 + 2").unwrap();
    assert_eq!(expr, Expr::binary(Add, Expr::literal(2), Expr::literal(2)));
}

#[test]
fn basic_serialize() {
    let expr = Expr::binary(Add, Expr::literal(2), Expr::literal(2));

    // binary operators always have parentheses
    assert_ok_eq!(to_string(&expr), "(2 + 2)");
}

#[test]
fn calc_deserialize_primitive() {
    #[derive(Deserialize)]
    struct Test {
        foo: Calc<usize>,
    }

    let from_verbatim: Test = from_json(json!({"foo": 42})).unwrap();
    assert_eq!(from_verbatim.foo.value(), &42);
    assert_none!(from_verbatim.foo.expr());

    let from_expr: Test = from_json(json!({"foo": "2 + 2 * 2"})).unwrap();
    assert_eq!(from_expr.foo.value(), &6);
    assert_some_eq!(from_expr.foo.expr(), "2 + 2 * 2");
}

#[cfg(glam)]
#[test]
fn calc_deserialize_vector() {
    #[derive(Deserialize)]
    struct Test {
        foo: Calc<glam::Vec2>,
    }

    let from_verbatim: Test = from_json(json!({"foo": [12., 45.]})).unwrap();
    assert_eq!(from_verbatim.foo.value(), &glam::Vec2::new(12., 45.));
    assert_none!(from_verbatim.foo.expr());

    let from_expr: Test = from_json(json!({"foo": "normalize([1., 2.])"})).unwrap();
    assert_eq!(from_expr.foo.value(), &glam::Vec2::new(1., 2.).normalize_or_zero());
    assert_some_eq!(from_expr.foo.expr(), "normalize([1., 2.])");
}

#[test]
fn calc_deserialize_primitive_with_context() {
    fn deserialize_ctx<'de, D>(deserializer: D) -> Result<Calc<u32>, D::Error>
        where D: Deserializer<'de>
    {
        Calc::deserialize_ctx(deserializer, Context::new().with("x", 13))
    }

    #[derive(Deserialize)]
    struct Test {
        #[serde(deserialize_with = "deserialize_ctx")]
        foo: Calc<u32>,
    }

    let from_verbatim: Test = from_json(json!({"foo": 42})).unwrap();
    assert_eq!(from_verbatim.foo.value(), &42);
    assert_none!(from_verbatim.foo.expr());

    let from_expr: Test = from_json(json!({"foo": "x"})).unwrap();
    assert_eq!(from_expr.foo.value(), &13);
    assert_some_eq!(from_expr.foo.expr(), "x");
}