datalogic_rs/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
mod error;
mod operators;

use error::Error;
use operators::preserve::PreserveOperator;
use operators::{
    operator::Operator, 
    var::VarOperator, 
    comparison::*, 
    logic::*, 
    arithmetic::*,
    string::*,
    array::*,
    missing::*,
    array_ops::*,
};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;

pub type JsonLogicResult = Result<Value, Error>;

#[derive(Clone)]
pub struct JsonLogic {
    operators: HashMap<String, Arc<dyn Operator>>,
}

impl Default for JsonLogic {
    fn default() -> Self {
        Self::new()
    }
}

impl JsonLogic {
    pub fn new() -> Self {
        let mut logic = Self {
            operators: HashMap::new(),
        };
        logic.register_defaults();
        logic
    }

    fn register_defaults(&mut self) {
        self.operators.insert("var".into(), Arc::new(VarOperator));

        self.operators.insert("==".into(), Arc::new(EqualsOperator));
        self.operators.insert("===".into(), Arc::new(StrictEqualsOperator));
        self.operators.insert("!=".into(), Arc::new(NotEqualsOperator));
        self.operators.insert("!==".into(), Arc::new(StrictNotEqualsOperator));
        self.operators.insert(">".into(), Arc::new(GreaterThanOperator));
        self.operators.insert(">=".into(), Arc::new(GreaterThanEqualOperator));
        self.operators.insert("<".into(), Arc::new(LessThanOperator));
        self.operators.insert("<=".into(), Arc::new(LessThanEqualOperator));
        self.operators.insert("!".into(), Arc::new(NotOperator));

        self.operators.insert("or".into(), Arc::new(OrOperator));
        self.operators.insert("and".into(), Arc::new(AndOperator));
        self.operators.insert("?:".into(), Arc::new(TernaryOperator));
        self.operators.insert("!!".into(), Arc::new(DoubleBangOperator));

        self.operators.insert("in".into(), Arc::new(InOperator));
        self.operators.insert("cat".into(), Arc::new(CatOperator));
        self.operators.insert("substr".into(), Arc::new(SubstrOperator));

        self.operators.insert("+".into(), Arc::new(AddOperator));
        self.operators.insert("*".into(), Arc::new(MultiplyOperator));
        self.operators.insert("-".into(), Arc::new(SubtractOperator));
        self.operators.insert("/".into(), Arc::new(DivideOperator));
        self.operators.insert("%".into(), Arc::new(ModuloOperator));
        self.operators.insert("max".into(), Arc::new(MaxOperator));
        self.operators.insert("min".into(), Arc::new(MinOperator));

        self.operators.insert("merge".into(), Arc::new(MergeOperator));

        self.operators.insert("if".into(), Arc::new(IfOperator));

        self.operators.insert("missing".into(), Arc::new(MissingOperator));
        self.operators.insert("missing_some".into(), Arc::new(MissingSomeOperator));

        self.operators.insert("filter".into(), Arc::new(FilterOperator));
        self.operators.insert("map".into(), Arc::new(MapOperator));
        self.operators.insert("reduce".into(), Arc::new(ReduceOperator));
        self.operators.insert("all".into(), Arc::new(AllOperator));
        self.operators.insert("none".into(), Arc::new(NoneOperator)); 
        self.operators.insert("some".into(), Arc::new(SomeOperator));
 
        self.operators.insert("preserve".into(), Arc::new(PreserveOperator));
    
    }

    pub fn apply(&self, logic: &Value, data: &Value) -> JsonLogicResult {
        match logic {
            Value::Object(map) if map.len() == 1 => {
                let (op, args) = map.iter().next().unwrap();
                let operator = self.operators
                    .get(op)
                    .ok_or(Error::UnknownOperator(op.clone()))?;

                // Handle automatic traversal
                if operator.auto_traverse() {
                    match args {
                        Value::Array(values) => {
                            let evaluated = values
                                .iter()
                                .map(|v| self.apply(v, data))
                                .collect::<Result<Vec<_>, _>>()?;
                            operator.apply(self, &Value::Array(evaluated), data)
                        }
                        _ => operator.apply(self, args, data)
                    }
                } else {
                    operator.apply(self, args, data)
                }
            }
            Value::Array(values) => {
                let mut results = Vec::with_capacity(values.len());
                for v in values {
                    results.push(self.apply(v, data)?);
                }
                Ok(Value::Array(results))
            }
            Value::String(_) | Value::Number(_) | Value::Bool(_) | Value::Null => {
                Ok(logic.clone())
            }
            _ => Err(Error::InvalidRule("Invalid Rule".to_string())),
        }
    }
}