oso-cloud 0.5.4

Oso Cloud client
Documentation
/// Convenience macro to construct a `Fact` from
///  a predicate and a list of arguments.
///
/// Arguments can either take "literal" syntax, i.e. `User{"123"}`
/// or can be Rust literals, i.e. `123`.
///
/// ## Example
///
/// ```
/// use oso_cloud::{fact, Fact, Value};
///
/// let fact: Fact = fact!("has_role", User { "1" }, "member", Repo { "1" });
///
/// assert_eq!(fact.args[0], Value::new("User", "1"));
/// ```
#[macro_export]
macro_rules! fact {
    ($predicate:expr, $($args:tt)*) => {{
        let mut args = vec![];
        $crate::push_values!(args; $($args)+);
        $crate::Fact {
            predicate: $predicate.to_owned(),
            args,
        }
    }};
}

#[macro_export]
macro_rules! value {
    ($lit:literal) => {
        $crate::Value::from($lit)
    };
    ($type_:ident { $id:expr }) => {
        $crate::Value::new(stringify!($type_), $id)
    };
    ($val:expr) => {
        $crate::Value::from($val)
    };
}

#[macro_export]
macro_rules! push_values {
    ($args:expr; $str:literal) => {{
        $args.push($crate::value!($str));
    }};
    ($args:expr; $type_:ident { $id:expr }) => {{
        $args.push($crate::value!($type_ { $id }));
    }};

    ($args:expr; $str:literal, $($rest:tt)*) => {{
        $args.push($crate::value!($str));
        $crate::push_values!($args; $($rest)*);
    }};
    ($args:expr; $type_:ident { $id:expr }, $($rest:tt)*) => {{
        $args.push($crate::value!($type_ { $id }));
        $crate::push_values!($args; $($rest)*);
    }};
    ($args:expr; $val:expr) => {{
        $args.push($crate::value!($val));
    }};
    ($args:expr; $val:expr, $($rest:tt)*) => {{
        $args.push($crate::value!($val));
        $crate::push_values!($args; $($rest)*);
    }};
}

#[cfg(test)]
mod test {
    use crate::{
        polar_ast::{PRIMITIVE_BOOLEAN_SYMBOL, PRIMITIVE_INTEGER_SYMBOL, PRIMITIVE_STRING_SYMBOL},
        Fact, Value,
    };

    #[test]
    fn test_macro_expansion() {
        let bool_val = value!(true);
        assert_eq!(bool_val, Value::new(PRIMITIVE_BOOLEAN_SYMBOL, "true"));

        let string_val = value!("foo");
        assert_eq!(string_val, Value::new(PRIMITIVE_STRING_SYMBOL, "foo"));

        let int_val = value!(42);
        assert_eq!(int_val, Value::new(PRIMITIVE_INTEGER_SYMBOL, "42"));

        let literal_val = value!(Foo { "bar" });
        assert_eq!(literal_val, Value::new("Foo", "bar"));

        let fact = fact!("foo", "bar", 42, true, Foo { "bar" });
        assert_eq!(
            fact,
            Fact {
                predicate: "foo".to_string(),
                args: vec![
                    Value::new(PRIMITIVE_STRING_SYMBOL, "bar"),
                    Value::new(PRIMITIVE_INTEGER_SYMBOL, "42"),
                    Value::new(PRIMITIVE_BOOLEAN_SYMBOL, "true"),
                    Value::new("Foo", "bar"),
                ],
            }
        );
    }
}