flowstdlib 0.142.0

The standard library of functions and flows for 'flow' programs
Documentation
use serde_json::Value;

use flowcore::{RUN_AGAIN, RunAgain};
use flowcore::errors::*;
use flowmacro::flow_function;

#[flow_function]
fn compare(inputs: &[Value]) -> Result<(Option<Value>, RunAgain)> {
    let left = &inputs[0];
    let right = &inputs[1];
    match (left.as_f64(), right.as_f64()) {
        (Some(lhs), Some(rhs)) => {
            let mut output_map = serde_json::Map::new();
            if (rhs - lhs).abs() < f64::EPSILON {
                output_map.insert("equal".into(), right.clone());
                output_map.insert("right-lte".into(), right.clone());
                output_map.insert("left-gte".into(), left.clone());
                output_map.insert("right-gte".into(), right.clone());
                output_map.insert("left-lte".into(), left.clone());
            } else if rhs < lhs {
                output_map.insert("right-lt".into(), right.clone());
                output_map.insert("left-gt".into(), left.clone());
                output_map.insert("right-lte".into(), right.clone());
                output_map.insert("left-gte".into(), left.clone());
            } else if rhs > lhs {
                output_map.insert("right-gt".into(), right.clone());
                output_map.insert("left-lt".into(), left.clone());
                output_map.insert("right-gte".into(), right.clone());
                output_map.insert("left-lte".into(), left.clone());
            }

            let output = Value::Object(output_map);

            Ok((Some(output), RUN_AGAIN))
        }
        (_, _) => bail!("Could not get input values as f64"),
    }
}

#[cfg(test)]
mod test {
    use serde_json::json;

    use flowcore::RUN_AGAIN;

    use super::compare;

    #[test]
    fn integer_equals() {
        let left = json!(1);
        let right = json!(1);
        let inputs = vec![left, right];

        let (value, run_again) = compare(&inputs).expect("compare() failed");

        assert_eq!(run_again, RUN_AGAIN);
        assert!(value.is_some());
        let value = value.expect("No value was returned");
        let map = value.as_object().expect("Expected a json object");
        assert!(map.contains_key("equal"));
    }

    #[test]
    fn float_equals() {
        let left = json!(1.0);
        let right = json!(1.0);
        let inputs = vec![left, right];

        let (value, run_again) = compare(&inputs).expect("compare() failed");

        assert_eq!(run_again, RUN_AGAIN);
        assert!(value.is_some());
        let value = value.expect("Could not get the value from the output");
        let map = value.as_object().expect("Could not get the json object from the output");
        assert!(map.contains_key("equal"));
    }

    #[test]
    fn integer_less_than() {
        let inputs = vec![json!(1), json!(2)];
        let (value, run_again) = compare(&inputs).expect("compare() failed");

        assert_eq!(run_again, RUN_AGAIN);
        assert!(value.is_some());
        let value = value.expect("Could not get the value from the output");
        let map = value.as_object().expect("Could not get the object from the output");
        assert_eq!(map.get("left-lt"), Some(&json!(1)));
        assert_eq!(map.get("right-gt"), Some(&json!(2)));
    }

    #[test]
    fn float_less_than() {
        let inputs = vec![json!(1.0), json!(2.0)];
        let (value, run_again) = compare(&inputs).expect("compare() failed");

        assert_eq!(run_again, RUN_AGAIN);
        assert!(value.is_some());
        let value = value.expect("Could not get the value from the output");
        let map = value.as_object().expect("Could not get the object from the output");
        assert_eq!(map.get("left-lt"), Some(&json!(1.0)));
        assert_eq!(map.get("right-gt"), Some(&json!(2.0)));
    }

    #[test]
    fn integer_more_than() {
        let inputs = vec![json!(2), json!(1)];
        let (value, run_again) = compare(&inputs).expect("compare() failed");

        assert_eq!(run_again, RUN_AGAIN);
        assert!(value.is_some());
        let value = value.expect("Could not get the value from the output");
        let map = value.as_object().expect("Could not get the object from the output");
        assert_eq!(map.get("left-gt"), Some(&json!(2)));
        assert_eq!(map.get("right-lt"), Some(&json!(1)));
    }

    #[test]
    fn float_more_than() {
        let inputs = vec![json!(2.0), json!(1.0)];
        let (value, run_again) = compare(&inputs).expect("compare() failed");

        assert_eq!(run_again, RUN_AGAIN);
        assert!(value.is_some());
        let value = value.expect("Could not get the value from the output");
        let map = value.as_object().expect("Could not get the object from the output");
        assert_eq!(map.get("left-gt"), Some(&json!(2.0)));
        assert_eq!(map.get("right-lt"), Some(&json!(1.0)));
    }

    #[test]
    fn invalid() {
        let inputs = vec![json!("AAA"), json!(1.0)];
        assert!(compare(&inputs).is_err());
    }
}