jsonlogic_rs/
lib.rs

1use serde_json;
2use serde_json::Value;
3
4mod error;
5// TODO consider whether this should be public; move doctests if so
6pub mod js_op;
7mod op;
8mod value;
9
10use error::Error;
11use value::{Evaluated, Parsed};
12
13const NULL: Value = Value::Null;
14
15trait Parser<'a>: Sized + Into<Value> {
16    fn from_value(value: &'a Value) -> Result<Option<Self>, Error>;
17    fn evaluate(&self, data: &'a Value) -> Result<Evaluated, Error>;
18}
19
20#[cfg(feature = "wasm")]
21pub mod javascript_iface {
22    use serde_json::Value;
23    use wasm_bindgen::prelude::*;
24
25    fn to_serde_value(js_value: JsValue) -> Result<Value, JsValue> {
26        // If we're passed a string, try to parse it as JSON. If we fail,
27        // we will just return a Value::String, since that's a valid thing
28        // to pass in to JSONLogic.
29        // js_value
30        if js_value.is_string() {
31            let js_string = js_value.as_string().expect(
32                "Could not convert value to string, even though it was checked to be a string."
33            );
34            serde_json::from_str(&js_string).or(Ok(Value::String(js_string)))
35        } else {
36            // If we're passed anything else, convert it directly to a serde Value.
37            js_value
38                .into_serde::<Value>()
39                .map_err(|err| format!("{}", err))
40                .map_err(JsValue::from)
41        }
42    }
43
44    #[wasm_bindgen]
45    pub fn apply(value: JsValue, data: JsValue) -> Result<JsValue, JsValue> {
46        let value_json = to_serde_value(value)?;
47        let data_json = to_serde_value(data)?;
48
49        let res = crate::apply(&value_json, &data_json)
50            .map_err(|err| format!("{}", err))
51            .map_err(JsValue::from)?;
52
53        JsValue::from_serde(&res)
54            .map_err(|err| format!("{}", err))
55            .map_err(JsValue::from)
56    }
57}
58
59#[cfg(feature = "python")]
60pub mod python_iface {
61    use cpython::exc::ValueError;
62    use cpython::{py_fn, py_module_initializer, PyErr, PyResult, Python};
63
64    py_module_initializer!(jsonlogic, initjsonlogic, PyInit_jsonlogic, |py, m| {
65        m.add(py, "__doc__", "Python bindings for json-logic-rs")?;
66        m.add(py, "apply", py_fn!(py, py_apply(value: &str, data: &str)))?;
67        Ok(())
68    });
69
70    fn apply(value: &str, data: &str) -> Result<String, String> {
71        let value_json =
72            serde_json::from_str(value).map_err(|err| format!("{}", err))?;
73        let data_json = serde_json::from_str(data).map_err(|err| format!("{}", err))?;
74
75        crate::apply(&value_json, &data_json)
76            .map_err(|err| format!("{}", err))
77            .map(|res| res.to_string())
78    }
79
80    fn py_apply(py: Python, value: &str, data: &str) -> PyResult<String> {
81        apply(value, data).map_err(|err| PyErr::new::<ValueError, _>(py, err))
82    }
83}
84
85/// Run JSONLogic for the given operation and data.
86///
87pub fn apply(value: &Value, data: &Value) -> Result<Value, Error> {
88    let parsed = Parsed::from_value(&value)?;
89    parsed.evaluate(data).map(Value::from)
90}
91
92#[cfg(test)]
93mod jsonlogic_tests {
94    use super::*;
95    use serde_json::json;
96
97    fn no_op_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
98        vec![
99            // Passing a static value returns the value unchanged.
100            (json!("foo"), json!({}), Ok(json!("foo"))),
101            (json!(""), json!({}), Ok(json!(""))),
102            (json!([1, 2]), json!({}), Ok(json!([1, 2]))),
103            (json!([]), json!({}), Ok(json!([]))),
104            (json!(null), json!({}), Ok(json!(null))),
105            (json!(0), json!({}), Ok(json!(0))),
106            (json!(234), json!({}), Ok(json!(234))),
107            (json!({}), json!({}), Ok(json!({}))),
108            // Note: as of this writing, this behavior differs from the
109            // original jsonlogic implementation, which errors for objects of
110            // length one, due to attempting to parse their key as an operation
111            (json!({"a": 1}), json!({}), Ok(json!({"a": 1}))),
112            (
113                json!({"a": 1, "b": 2}),
114                json!({}),
115                Ok(json!({"a": 1, "b": 2})),
116            ),
117        ]
118    }
119
120    fn abstract_eq_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
121        vec![
122            (json!({"==": [1, 1]}), json!({}), Ok(json!(true))),
123            (json!({"==": [1, 2]}), json!({}), Ok(json!(false))),
124            (json!({"==": [1, "1"]}), json!({}), Ok(json!(true))),
125            (
126                json!({"==": [{}, "[object Object]"]}),
127                json!({}),
128                Ok(json!(true)),
129            ),
130            (json!({"==": [1, [1]]}), json!({}), Ok(json!(true))),
131            (json!({"==": [1, true]}), json!({}), Ok(json!(true))),
132            // Recursive evaluation
133            (
134                json!({"==": [true, {"==": [1, 1]}]}),
135                json!({}),
136                Ok(json!(true)),
137            ),
138            (
139                json!({"==": [{"==": [{"==": [1, 1]}, true]}, {"==": [1, 1]}]}),
140                json!({}),
141                Ok(json!(true)),
142            ),
143            // Wrong number of arguments
144            (json!({"==": [1]}), json!({}), Err(())),
145            (json!({"==": [1, 1, 1]}), json!({}), Err(())),
146        ]
147    }
148
149    fn abstract_ne_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
150        vec![
151            (json!({"!=": [1, 1]}), json!({}), Ok(json!(false))),
152            (json!({"!=": [1, 2]}), json!({}), Ok(json!(true))),
153            (json!({"!=": [1, "1"]}), json!({}), Ok(json!(false))),
154            (
155                json!({"!=": [{}, "[object Object]"]}),
156                json!({}),
157                Ok(json!(false)),
158            ),
159            (
160                json!({"!=": [{"!=": [1, 2]}, 1]}),
161                json!({}),
162                Ok(json!(false)),
163            ),
164            // Wrong number of arguments
165            (json!({"!=": [1]}), json!({}), Err(())),
166            (json!({"!=": [1, 1, 1]}), json!({}), Err(())),
167        ]
168    }
169
170    fn strict_eq_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
171        vec![
172            (json!({"===": [1, 1]}), json!({}), Ok(json!(true))),
173            (json!({"===": [1, 2]}), json!({}), Ok(json!(false))),
174            (json!({"===": [1, "1"]}), json!({}), Ok(json!(false))),
175            (
176                json!({"===": [{}, "[object Object]"]}),
177                json!({}),
178                Ok(json!(false)),
179            ),
180            (json!({"===": [1, [1]]}), json!({}), Ok(json!(false))),
181            (json!({"===": [1, true]}), json!({}), Ok(json!(false))),
182            // Recursive evaluation
183            (
184                json!({"===": [true, {"===": [1, 1]}]}),
185                json!({}),
186                Ok(json!(true)),
187            ),
188            (
189                json!({"===": [{"===": [{"===": [1, 1]}, true]}, {"===": [1, 1]}]}),
190                json!({}),
191                Ok(json!(true)),
192            ),
193            // Wrong number of arguments
194            (json!({"===": [1]}), json!({}), Err(())),
195            (json!({"===": [1, 1, 1]}), json!({}), Err(())),
196        ]
197    }
198
199    fn strict_ne_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
200        vec![
201            (json!({"!==": [1, 1]}), json!({}), Ok(json!(false))),
202            (json!({"!==": [1, 2]}), json!({}), Ok(json!(true))),
203            (json!({"!==": [1, "1"]}), json!({}), Ok(json!(true))),
204            (
205                json!({"!==": [{}, "[object Object]"]}),
206                json!({}),
207                Ok(json!(true)),
208            ),
209            (json!({"!==": [1, [1]]}), json!({}), Ok(json!(true))),
210            (json!({"!==": [1, true]}), json!({}), Ok(json!(true))),
211            // Recursive evaluation
212            (
213                json!({"!==": [true, {"!==": [1, 1]}]}),
214                json!({}),
215                Ok(json!(true)),
216            ),
217            (
218                json!({"!==": [{"!==": [{"!==": [1, 1]}, false]}, {"!==": [1, 1]}]}),
219                json!({}),
220                Ok(json!(false)),
221            ),
222            // Wrong number of arguments
223            (json!({"!==": [1]}), json!({}), Err(())),
224            (json!({"!==": [1, 1, 1]}), json!({}), Err(())),
225        ]
226    }
227
228    fn var_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
229        vec![
230            // Variable substitution
231            (
232                json!({"var": "foo"}),
233                json!({"foo": "bar"}),
234                Ok(json!("bar")),
235            ),
236            // Index into array data
237            (json!({"var": 1}), json!(["foo", "bar"]), Ok(json!("bar"))),
238            // Absent variable
239            (json!({"var": "foo"}), json!({}), Ok(json!(null))),
240            (
241                json!({"==": [{"var": "first"}, true]}),
242                json!({"first": true}),
243                Ok(json!(true)),
244            ),
245            // Dotted variable substitution
246            (
247                json!({"var": "foo.bar"}),
248                json!({"foo": {"bar": "baz"}}),
249                Ok(json!("baz")),
250            ),
251            // Dotted variable with nested array access
252            (
253                json!({"var": "foo.1"}),
254                json!({"foo": ["bar", "baz", "pop"]}),
255                Ok(json!("baz")),
256            ),
257            // Absent dotted variable
258            (
259                json!({"var": "foo.bar"}),
260                json!({"foo": {"baz": "baz"}}),
261                Ok(json!(null)),
262            ),
263            // Non-object type in dotted variable path
264            (
265                json!({"var": "foo.bar.baz"}),
266                json!({"foo": {"bar": 1}}),
267                Ok(json!(null)),
268            ),
269            (
270                json!({"var": "foo.bar"}),
271                json!({"foo": "not an object"}),
272                Ok(json!(null)),
273            ),
274        ]
275    }
276
277    fn missing_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
278        vec![
279            // "missing" data operator
280            (
281                json!({"missing": ["a", "b"]}),
282                json!({"a": 1, "b": 2}),
283                Ok(json!([])),
284            ),
285            (
286                json!({"missing": ["a", "b"]}),
287                json!({"a": 1}),
288                Ok(json!(["b"])),
289            ),
290            (json!({"missing": [1, 5]}), json!([1, 2, 3]), Ok(json!([5]))),
291        ]
292    }
293
294    fn missing_some_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
295        vec![
296            // "missing_some" data operator
297            (
298                json!({"missing_some": [1, ["a", "b"]]}),
299                json!({"a": 1, "b": 2}),
300                Ok(json!([])),
301            ),
302            (
303                json!({"missing_some": [1, ["a", "b", "c"]]}),
304                json!({"a": 1, "b": 2}),
305                Ok(json!([])),
306            ),
307            (
308                json!({"missing_some": [2, ["a", "b", "c"]]}),
309                json!({"a": 1}),
310                Ok(json!(["b", "c"])),
311            ),
312        ]
313    }
314
315    fn if_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
316        vec![
317            (
318                json!({"if": [true, "true", "false"]}),
319                json!({}),
320                Ok(json!("true")),
321            ),
322            (
323                json!({"if": [false, "true", "false"]}),
324                json!({}),
325                Ok(json!("false")),
326            ),
327            (
328                json!({"if": [false, "true", true, "true2"]}),
329                json!({}),
330                Ok(json!("true2")),
331            ),
332            (
333                json!({"if": [false, "true", false, "true2", "false2"]}),
334                json!({}),
335                Ok(json!("false2")),
336            ),
337            (
338                json!({"if": [{"===": [1, 1]}, "true", "false"]}),
339                json!({}),
340                Ok(json!("true")),
341            ),
342            (
343                json!({"if": [{"===": [1, 2]}, "true", "false"]}),
344                json!({}),
345                Ok(json!("false")),
346            ),
347            (
348                json!({"if": [{"===": [1, 2]}, "true", {"===": [1, 1]}, "true2"]}),
349                json!({}),
350                Ok(json!("true2")),
351            ),
352            (
353                json!({"if": [{"===": [1, 2]}, "true", {"===": [1, 2]}, "true2", "false2"]}),
354                json!({}),
355                Ok(json!("false2")),
356            ),
357        ]
358    }
359
360    fn or_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
361        vec![
362            (json!({"or": [true]}), json!({}), Ok(json!(true))),
363            (json!({"or": [false]}), json!({}), Ok(json!(false))),
364            (json!({"or": [false, true]}), json!({}), Ok(json!(true))),
365            (
366                json!({"or": [false, true, false]}),
367                json!({}),
368                Ok(json!(true)),
369            ),
370            (json!({"or": [false, false, 12]}), json!({}), Ok(json!(12))),
371            (
372                json!({"or": [false, false, 12, 13, 14]}),
373                json!({}),
374                Ok(json!(12)),
375            ),
376            (
377                json!({"or": [false, false, 0, 12]}),
378                json!({}),
379                Ok(json!(12)),
380            ),
381            (
382                json!({"or": [false, {"===": [1, 1]}]}),
383                json!({}),
384                Ok(json!(true)),
385            ),
386            (
387                json!({"or": [false, {"===": [{"var": "foo"}, 1]}]}),
388                json!({"foo": 1}),
389                Ok(json!(true)),
390            ),
391            (
392                json!({"or": [false, {"===": [{"var": "foo"}, 1]}]}),
393                json!({"foo": 2}),
394                Ok(json!(false)),
395            ),
396        ]
397    }
398
399    fn and_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
400        vec![
401            (json!({"and": [true]}), json!({}), Ok(json!(true))),
402            (json!({"and": [false]}), json!({}), Ok(json!(false))),
403            (json!({"and": [false, true]}), json!({}), Ok(json!(false))),
404            (json!({"and": [true, false]}), json!({}), Ok(json!(false))),
405            (json!({"and": [true, true]}), json!({}), Ok(json!(true))),
406            (
407                json!({"and": [false, true, false]}),
408                json!({}),
409                Ok(json!(false)),
410            ),
411            (json!({"and": [12, true, 0]}), json!({}), Ok(json!(0))),
412            (
413                json!({"and": [12, true, 0, 12, false]}),
414                json!({}),
415                Ok(json!(0)),
416            ),
417            (json!({"and": [true, true, 12]}), json!({}), Ok(json!(12))),
418            (
419                json!({"and": [{"===": [1, 1]}, false]}),
420                json!({}),
421                Ok(json!(false)),
422            ),
423            (
424                json!({"and": [{"===": [{"var": "foo"}, 1]}, true]}),
425                json!({"foo": 1}),
426                Ok(json!(true)),
427            ),
428            (
429                json!({"and": [{"===": [{"var": "foo"}, 1]}, true]}),
430                json!({"foo": 2}),
431                Ok(json!(false)),
432            ),
433        ]
434    }
435
436    fn map_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
437        vec![
438            (
439                json!({"map": [[1, 2, 3], {"*": [{"var": ""}, 2]}]}),
440                json!(null),
441                Ok(json!([2, 4, 6])),
442            ),
443            (
444                json!({"map": [[], {"*": [{"var": ""}, 2]}]}),
445                json!(null),
446                Ok(json!([])),
447            ),
448            (
449                json!({"map": [{"var": "vals"}, {"*": [{"var": ""}, 2]}]}),
450                json!({"vals": [1, 2, 3]}),
451                Ok(json!([2, 4, 6])),
452            ),
453            (
454                json!({"map": [{"var": ""}, {"*": [{"var": ""}, 2]}]}),
455                json!([1, 2, 3]),
456                Ok(json!([2, 4, 6])),
457            ),
458            (
459                json!({"map": [[true, 2, 0, [], {}], {"!!": [{"var": ""}]}]}),
460                json!(null),
461                Ok(json!([true, true, false, false, true])),
462            ),
463        ]
464    }
465
466    fn filter_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
467        vec![
468            (
469                json!({"filter": [[1, 2, 3], {"%": [{"var": ""}, 2]}]}),
470                json!(null),
471                Ok(json!([1, 3])),
472            ),
473            (
474                json!({"filter": [[], {"%": [{"var": ""}, 2]}]}),
475                json!(null),
476                Ok(json!([])),
477            ),
478            (
479                json!({"filter": [[2, 4, 6], {"%": [{"var": ""}, 2]}]}),
480                json!(null),
481                Ok(json!([])),
482            ),
483            (
484                json!({"filter": [{"var": "vals"}, {"%": [{"var": ""}, 2]}]}),
485                json!({"vals": [1, 2, 3]}),
486                Ok(json!([1, 3])),
487            ),
488            (
489                json!({"filter": [["aa", "bb", "aa"], {"===": [{"var": ""}, "aa"]}]}),
490                json!(null),
491                Ok(json!(["aa", "aa"])),
492            ),
493            (
494                json!(
495                    {
496                        "filter": [
497                            [1, 2, 3],
498                            {"<": [
499                                {"-": [{"var": ""}, 3]},
500                                0
501                            ]}
502                        ]
503                    }
504                ),
505                json!(null),
506                Ok(json!([1, 2])),
507            ),
508        ]
509    }
510
511    fn reduce_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
512        vec![
513            (
514                json!(
515                    {"reduce":[
516                        [1, 2, 3, 4, 5],
517                        {"+": [{"var":"current"}, {"var":"accumulator"}]},
518                        0
519                    ]}
520                ),
521                json!(null),
522                Ok(json!(15)),
523            ),
524            (
525                json!(
526                    {"reduce":[
527                        {"var": "vals"},
528                        {"+": [{"var":"current"}, {"var":"accumulator"}]},
529                        0
530                    ]}
531                ),
532                json!({"vals": [1, 2, 3, 4, 5]}),
533                Ok(json!(15)),
534            ),
535            (
536                json!(
537                    {"reduce":[
538                        {"var": "vals"},
539                        {"+": [{"var":"current"}, {"var":"accumulator"}]},
540                        {"var": "init"}
541                    ]}
542                ),
543                json!({"vals": [1, 2, 3, 4, 5], "init": 0}),
544                Ok(json!(15)),
545            ),
546            (
547                json!(
548                    {"reduce":[
549                        {"var": "vals"},
550                        {"and":
551                            [{"var": "accumulator"},
552                             {"!!": [{"var": "current"}]}]
553                        },
554                        true,
555                    ]}
556                ),
557                json!({"vals": [1, true, 10, "foo", 1, 1]}),
558                Ok(json!(true)),
559            ),
560            (
561                json!(
562                    {"reduce":[
563                        {"var": "vals"},
564                        {"and":
565                            [{"var": "accumulator"},
566                             {"!!": [{"var": "current"}]}]
567                        },
568                        true,
569                    ]}
570                ),
571                json!({"vals": [1, true, 10, "foo", 0, 1]}),
572                Ok(json!(false)),
573            ),
574        ]
575    }
576
577    fn all_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
578        vec![
579            // Invalid first arguments
580            (json!({"all": [1, 1]}), json!({}), Err(())),
581            (json!({"all": [{}, 1]}), json!({}), Err(())),
582            (json!({"all": [false, 1]}), json!({}), Err(())),
583            // Empty array/string/null
584            (json!({"all": [[], 1]}), json!({}), Ok(json!(false))),
585            (json!({"all": ["", 1]}), json!({}), Ok(json!(false))),
586            (json!({"all": [null, 1]}), json!({}), Ok(json!(false))),
587            // Constant predicate
588            (json!({"all": [[1, 2], 1]}), json!({}), Ok(json!(true))),
589            (json!({"all": [[1, 2], 0]}), json!({}), Ok(json!(false))),
590            // Simple predicate
591            (
592                json!({"all": [[1, 2], {">": [{"var": ""}, 0]}]}),
593                json!({}),
594                Ok(json!(true)),
595            ),
596            (
597                json!({"all": [[1, 2, -1], {">": [{"var": ""}, 0]}]}),
598                json!({}),
599                Ok(json!(false)),
600            ),
601            (
602                json!({"all": ["aaaa", {"===": [{"var": ""}, "a"]}]}),
603                json!({}),
604                Ok(json!(true)),
605            ),
606            (
607                json!({"all": ["aabaa", {"===": [{"var": ""}, "a"]}]}),
608                json!({}),
609                Ok(json!(false)),
610            ),
611            // First argument requires evaluation
612            (
613                json!({"all": [ {"var": "a"}, {"===": [{"var": ""}, "a"]} ]}),
614                json!({"a": "a"}),
615                Ok(json!(true)),
616            ),
617            // Expression in array
618            (
619                json!({"all": [[1, {"+": [1, 1]}], {">": [{"var": ""}, 0]}]}),
620                json!({}),
621                Ok(json!(true)),
622            ),
623            (
624                json!({"all": [[1, {"+": [-2, 1]}], {">": [{"var": ""}, 0]}]}),
625                json!({}),
626                Ok(json!(false)),
627            ),
628            // Validate short-circuit
629            (
630                // The equality expression is invalid and would return an
631                // Err if parsed, b/c it has an invalid number of arguments.
632                // Since the value before it invalidates the predicate, though,
633                // we should never attempt to evaluate it.
634                json!({"all": [[1, -1, {"==": []}], {">": [{"var": ""}, 0]}]}),
635                json!({}),
636                Ok(json!(false)),
637            ),
638            (
639                // Same as above, but put the error before the invalidating
640                // value just to make sure our hypothesis is correct re:
641                // getting an error
642                json!({"all": [[1, {"==": []}, -1], {">": [{"var": ""}, 0]}]}),
643                json!({}),
644                Err(()),
645            ),
646            // Parse data in array
647            (
648                json!({"all": [[1, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
649                json!({"foo": 1}),
650                Ok(json!(true)),
651            ),
652            (
653                json!({"all": [[1, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
654                json!({"foo": -5}),
655                Ok(json!(false)),
656            ),
657            (
658                json!({"all": [[1, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
659                json!({"foo": -5}),
660                Ok(json!(false)),
661            ),
662        ]
663    }
664
665    fn some_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
666        vec![
667            // Invalid first arguments
668            (json!({"some": [1, 1]}), json!({}), Err(())),
669            (json!({"some": [{}, 1]}), json!({}), Err(())),
670            (json!({"some": [false, 1]}), json!({}), Err(())),
671            // Empty array/string
672            (json!({"some": [[], 1]}), json!({}), Ok(json!(false))),
673            (json!({"some": ["", 1]}), json!({}), Ok(json!(false))),
674            (json!({"some": [null, 1]}), json!({}), Ok(json!(false))),
675            // Constant predicate
676            (json!({"some": [[1, 2], 1]}), json!({}), Ok(json!(true))),
677            (json!({"some": [[1, 2], 0]}), json!({}), Ok(json!(false))),
678            // Simple predicate
679            (
680                json!({"some": [[-5, 2], {">": [{"var": ""}, 0]}]}),
681                json!({}),
682                Ok(json!(true)),
683            ),
684            (
685                json!({"some": [[-3, 1, 2, -1], {">": [{"var": ""}, 0]}]}),
686                json!({}),
687                Ok(json!(true)),
688            ),
689            (
690                json!({"some": ["aaaa", {"===": [{"var": ""}, "a"]}]}),
691                json!({}),
692                Ok(json!(true)),
693            ),
694            (
695                json!({"some": ["aabaa", {"===": [{"var": ""}, "a"]}]}),
696                json!({}),
697                Ok(json!(true)),
698            ),
699            (
700                json!({"some": ["cdefg", {"===": [{"var": ""}, "a"]}]}),
701                json!({}),
702                Ok(json!(false)),
703            ),
704            // Expression in array
705            (
706                json!({"some": [[-6, {"+": [1, 1]}], {">": [{"var": ""}, 0]}]}),
707                json!({}),
708                Ok(json!(true)),
709            ),
710            (
711                json!({"some": [[-5, {"+": [-2, 1]}], {">": [{"var": ""}, 0]}]}),
712                json!({}),
713                Ok(json!(false)),
714            ),
715            // Validate short-circuit
716            (
717                // The equality expression is invalid and would return an
718                // Err if parsed, b/c it has an invalid number of arguments.
719                // Since the value before it validates the predicate, though,
720                // we should never attempt to evaluate it.
721                json!({"some": [[1, {"==": []}], {">": [{"var": ""}, 0]}]}),
722                json!({}),
723                Ok(json!(true)),
724            ),
725            (
726                // Same as above, but put the error before the invalidating
727                // value just to make sure our hypothesis is correct re:
728                // getting an error
729                json!({"some": [[-51, {"==": []}, -1], {">": [{"var": ""}, 0]}]}),
730                json!({}),
731                Err(()),
732            ),
733            // Parse data in array
734            (
735                json!({"some": [[-4, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
736                json!({"foo": 1}),
737                Ok(json!(true)),
738            ),
739            (
740                json!({"some": [[-4, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
741                json!({"foo": -5}),
742                Ok(json!(false)),
743            ),
744        ]
745    }
746
747    fn none_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
748        vec![
749            // Invalid first arguments
750            (json!({"none": [1, 1]}), json!({}), Err(())),
751            (json!({"none": [{}, 1]}), json!({}), Err(())),
752            (json!({"none": [false, 1]}), json!({}), Err(())),
753            // Empty array/string
754            (json!({"none": [[], 1]}), json!({}), Ok(json!(true))),
755            (json!({"none": ["", 1]}), json!({}), Ok(json!(true))),
756            (json!({"none": [null, 1]}), json!({}), Ok(json!(true))),
757            // Constant predicate
758            (json!({"none": [[1, 2], 1]}), json!({}), Ok(json!(false))),
759            (json!({"none": [[1, 2], 0]}), json!({}), Ok(json!(true))),
760            // Simple predicate
761            (
762                json!({"none": [[-5, 2], {">": [{"var": ""}, 0]}]}),
763                json!({}),
764                Ok(json!(false)),
765            ),
766            (
767                json!({"none": [[-3, 1, 2, -1], {">": [{"var": ""}, 0]}]}),
768                json!({}),
769                Ok(json!(false)),
770            ),
771            (
772                json!({"none": ["aaaa", {"===": [{"var": ""}, "a"]}]}),
773                json!({}),
774                Ok(json!(false)),
775            ),
776            (
777                json!({"none": ["aabaa", {"===": [{"var": ""}, "a"]}]}),
778                json!({}),
779                Ok(json!(false)),
780            ),
781            (
782                json!({"none": ["cdefg", {"===": [{"var": ""}, "a"]}]}),
783                json!({}),
784                Ok(json!(true)),
785            ),
786            // Expression in array
787            (
788                json!({"none": [[-6, {"+": [1, 1]}], {">": [{"var": ""}, 0]}]}),
789                json!({}),
790                Ok(json!(false)),
791            ),
792            (
793                json!({"none": [[-5, {"+": [-2, 1]}], {">": [{"var": ""}, 0]}]}),
794                json!({}),
795                Ok(json!(true)),
796            ),
797            // Validate short-circuit
798            (
799                // The equality expression is invalid and would return an
800                // Err if parsed, b/c it has an invalid number of arguments.
801                // Since the value before it validates the predicate, though,
802                // we should never attempt to evaluate it.
803                json!({"none": [[1, {"==": []}], {">": [{"var": ""}, 0]}]}),
804                json!({}),
805                Ok(json!(false)),
806            ),
807            (
808                // Same as above, but put the error before the invalidating
809                // value just to make sure our hypothesis is correct re:
810                // getting an error
811                json!({"none": [[-51, {"==": []}, -1], {">": [{"var": ""}, 0]}]}),
812                json!({}),
813                Err(()),
814            ),
815            // Parse data in array
816            (
817                json!({"none": [[-4, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
818                json!({"foo": 1}),
819                Ok(json!(false)),
820            ),
821            (
822                json!({"none": [[-4, {"var": "foo"}], {">": [{"var": ""}, 0]}]}),
823                json!({"foo": -5}),
824                Ok(json!(true)),
825            ),
826        ]
827    }
828
829    fn merge_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
830        vec![
831            (json!({"merge": []}), json!({}), Ok(json!([]))),
832            (json!({"merge": [1]}), json!({}), Ok(json!([1]))),
833            (json!({"merge": [1, 2]}), json!({}), Ok(json!([1, 2]))),
834            (
835                json!({"merge": [[1, 2], 2]}),
836                json!({}),
837                Ok(json!([1, 2, 2])),
838            ),
839            (json!({"merge": [[1], [2]]}), json!({}), Ok(json!([1, 2]))),
840            (json!({"merge": [1, [2]]}), json!({}), Ok(json!([1, 2]))),
841            (
842                json!({"merge": [1, [2, [3, 4]]]}),
843                json!({}),
844                Ok(json!([1, 2, [3, 4]])),
845            ),
846            (
847                json!({"merge": [{"var": "foo"}, [2]]}),
848                json!({"foo": 1}),
849                Ok(json!([1, 2])),
850            ),
851            (json!({"merge": [[], [2]]}), json!(null), Ok(json!([2]))),
852            (
853                json!({"merge": [[[]], [2]]}),
854                json!(null),
855                Ok(json!([[], 2])),
856            ),
857            (json!({"merge": [{}, [2]]}), json!(null), Ok(json!([{}, 2]))),
858            (
859                json!({"merge": [{}, [2], 3, false]}),
860                json!(null),
861                Ok(json!([{}, 2, 3, false])),
862            ),
863        ]
864    }
865
866    fn cat_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
867        vec![
868            (json!({"cat": []}), json!({}), Ok(json!(""))),
869            (json!({"cat": [1]}), json!({}), Ok(json!("1"))),
870            (json!({"cat": ["a"]}), json!({}), Ok(json!("a"))),
871            (json!({"cat": ["a", "b"]}), json!({}), Ok(json!("ab"))),
872            (json!({"cat": ["a", "b", "c"]}), json!({}), Ok(json!("abc"))),
873            (json!({"cat": ["a", "b", 1]}), json!({}), Ok(json!("ab1"))),
874        ]
875    }
876
877    fn substr_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
878        vec![
879            // Wrong number of arguments
880            (json!({"substr": []}), json!({}), Err(())),
881            (json!({"substr": ["foo"]}), json!({}), Err(())),
882            (json!({"substr": ["foo", 1, 2, 3]}), json!({}), Err(())),
883            // Wrong argument types
884            (json!({"substr": [12, 1]}), json!({}), Err(())),
885            (json!({"substr": ["foo", "12"]}), json!({}), Err(())),
886            // Non-negative indices
887            (json!({"substr": ["foo", 0]}), json!({}), Ok(json!("foo"))),
888            (json!({"substr": ["foo", 1]}), json!({}), Ok(json!("oo"))),
889            (json!({"substr": ["foo", 2]}), json!({}), Ok(json!("o"))),
890            // Negative indices
891            (json!({"substr": ["foo", -1]}), json!({}), Ok(json!("o"))),
892            (json!({"substr": ["foo", -2]}), json!({}), Ok(json!("oo"))),
893            (json!({"substr": ["foo", -3]}), json!({}), Ok(json!("foo"))),
894            // Out-of-bounds indices
895            (json!({"substr": ["foo", 3]}), json!({}), Ok(json!(""))),
896            (json!({"substr": ["foo", 20]}), json!({}), Ok(json!(""))),
897            (json!({"substr": ["foo", -4]}), json!({}), Ok(json!("foo"))),
898            // Non-negative Limits
899            (json!({"substr": ["foo", 0, 1]}), json!({}), Ok(json!("f"))),
900            (
901                json!({"substr": ["foo", 0, 3]}),
902                json!({}),
903                Ok(json!("foo")),
904            ),
905            (json!({"substr": ["foo", 0, 0]}), json!({}), Ok(json!(""))),
906            (json!({"substr": ["foo", 1, 1]}), json!({}), Ok(json!("o"))),
907            // Negative Limits
908            (
909                json!({"substr": ["foo", 0, -1]}),
910                json!({}),
911                Ok(json!("fo")),
912            ),
913            (json!({"substr": ["foo", 0, -2]}), json!({}), Ok(json!("f"))),
914            (json!({"substr": ["foo", 0, -3]}), json!({}), Ok(json!(""))),
915            // Out-of-bounds limits
916            (
917                json!({"substr": ["foo", 0, 10]}),
918                json!({}),
919                Ok(json!("foo")),
920            ),
921            (json!({"substr": ["foo", 0, -10]}), json!({}), Ok(json!(""))),
922            // Negative indices with negative limits
923            (
924                json!({"substr": ["foo", -3, -2]}),
925                json!({}),
926                Ok(json!("f")),
927            ),
928            // Negative indices with positive limits
929            (
930                json!({"substr": ["foo", -3, 2]}),
931                json!({}),
932                Ok(json!("fo")),
933            ),
934            // Out-of-bounds indices with out-of-bounds limits
935            (json!({"substr": ["foo", 10, 10]}), json!({}), Ok(json!(""))),
936            (
937                json!({"substr": ["foo", 10, -10]}),
938                json!({}),
939                Ok(json!("")),
940            ),
941            (
942                json!({"substr": ["foo", -10, 10]}),
943                json!({}),
944                Ok(json!("foo")),
945            ),
946            (
947                json!({"substr": ["foo", -10, -10]}),
948                json!({}),
949                Ok(json!("")),
950            ),
951        ]
952    }
953
954    fn log_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
955        vec![
956            // Invalid number of arguments
957            (json!({"log": []}), json!({}), Err(())),
958            (json!({"log": [1, 2]}), json!({}), Err(())),
959            // Correct number of arguments
960            (json!({"log": [1]}), json!({}), Ok(json!(1))),
961            (json!({"log": 1}), json!({}), Ok(json!(1))),
962        ]
963    }
964
965    fn lt_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
966        vec![
967            (json!({"<": [1, 2]}), json!({}), Ok(json!(true))),
968            (json!({"<": [3, 2]}), json!({}), Ok(json!(false))),
969            (
970                json!({"<": [1, {"var": "foo"}]}),
971                json!({"foo": 5}),
972                Ok(json!(true)),
973            ),
974            (json!({"<": [1, 2, 3]}), json!({}), Ok(json!(true))),
975            (json!({"<": [3, 2, 3]}), json!({}), Ok(json!(false))),
976            (json!({"<": [1, 2, 1]}), json!({}), Ok(json!(false))),
977        ]
978    }
979
980    fn gt_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
981        vec![
982            (json!({">": [1, 2]}), json!({}), Ok(json!(false))),
983            (json!({">": [3, 2]}), json!({}), Ok(json!(true))),
984            (
985                json!({">": [1, {"var": "foo"}]}),
986                json!({"foo": 5}),
987                Ok(json!(false)),
988            ),
989            (json!({">": [1, 2, 3]}), json!({}), Ok(json!(false))),
990            (json!({">": [3, 2, 3]}), json!({}), Ok(json!(false))),
991            (json!({">": [1, 2, 1]}), json!({}), Ok(json!(false))),
992            (json!({">": [3, 2, 1]}), json!({}), Ok(json!(true))),
993        ]
994    }
995
996    fn plus_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
997        vec![
998            (json!({"+": []}), json!({}), Ok(json!(0))),
999            (json!({"+": [1]}), json!({}), Ok(json!(1))),
1000            (json!({"+": ["1"]}), json!({}), Ok(json!(1))),
1001            (json!({"+": [1, 1]}), json!({}), Ok(json!(2))),
1002            (json!({"+": [1, 1, 1]}), json!({}), Ok(json!(3))),
1003            (json!({"+": [1, 1, false]}), json!({}), Err(())),
1004            (json!({"+": [1, 1, "1"]}), json!({}), Ok(json!(3))),
1005            (
1006                json!({"+": [1, 1, "123abc"]}), // WHY???
1007                json!({}),
1008                Ok(json!(125)),
1009            ),
1010        ]
1011    }
1012
1013    fn minus_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1014        vec![
1015            (json!({"-": "5"}), json!({}), Ok(json!(-5))),
1016            (json!({"-": [2]}), json!({}), Ok(json!(-2))),
1017            (json!({"-": [2, 2]}), json!({}), Ok(json!(0))),
1018            (json!({"-": ["9", [3]]}), json!({}), Ok(json!(6))),
1019        ]
1020    }
1021
1022    fn multiplication_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1023        vec![
1024            (json!({"*": 1}), json!({}), Ok(json!(1))),
1025            (json!({"*": [1]}), json!({}), Ok(json!(1))),
1026            (json!({"*": [1, 2]}), json!({}), Ok(json!(2))),
1027            (json!({"*": [0, 2]}), json!({}), Ok(json!(0))),
1028            (json!({"*": [1, 2, 3]}), json!({}), Ok(json!(6))),
1029            (json!({"*": [1, 2, "3"]}), json!({}), Ok(json!(6))),
1030            (json!({"*": [1, "2abc", "3"]}), json!({}), Ok(json!(6))),
1031            (json!({"*": []}), json!({}), Err(())),
1032        ]
1033    }
1034
1035    fn division_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1036        vec![
1037            (json!({"/": [2, 1]}), json!({}), Ok(json!(2))),
1038            (json!({"/": [1, 2]}), json!({}), Ok(json!(0.5))),
1039            (json!({"/": [1, "2"]}), json!({}), Ok(json!(0.5))),
1040            (json!({"/": [12, "-2"]}), json!({}), Ok(json!(-6))),
1041            (json!({"/": []}), json!({}), Err(())),
1042            (json!({"/": [5]}), json!({}), Err(())),
1043            (json!({"/": [5, 2, 1]}), json!({}), Err(())),
1044        ]
1045    }
1046
1047    fn modulo_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1048        vec![
1049            (json!({"%": [2, 1]}), json!({}), Ok(json!(0))),
1050            (json!({"%": [1, 2]}), json!({}), Ok(json!(1))),
1051            (json!({"%": [1, "2"]}), json!({}), Ok(json!(1))),
1052            (json!({"%": [12, "-2"]}), json!({}), Ok(json!(0))),
1053            (json!({"%": []}), json!({}), Err(())),
1054            (json!({"%": [5]}), json!({}), Err(())),
1055            (json!({"%": [5, 2, 1]}), json!({}), Err(())),
1056        ]
1057    }
1058
1059    fn max_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1060        vec![
1061            (json!({"max": [1, 2, 3]}), json!({}), Ok(json!(3))),
1062            (json!({"max": [false, -1, 2]}), json!({}), Ok(json!(2))),
1063            (json!({"max": [0, -1, true]}), json!({}), Ok(json!(1))),
1064            (json!({"max": [0, -1, true, [3]]}), json!({}), Ok(json!(3))),
1065        ]
1066    }
1067
1068    fn min_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1069        vec![
1070            (json!({"min": [1, 2, 3]}), json!({}), Ok(json!(1))),
1071            (json!({"min": [false, 1, 2]}), json!({}), Ok(json!(0))),
1072            (json!({"min": [0, -1, true]}), json!({}), Ok(json!(-1))),
1073            (
1074                json!({"min": [0, [-1], true, [3]]}),
1075                json!({}),
1076                Ok(json!(-1)),
1077            ),
1078        ]
1079    }
1080
1081    fn bang_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1082        vec![
1083            (json!( {"!": []} ), json!({}), Err(())),
1084            (json!( {"!": [1, 2]} ), json!({}), Err(())),
1085            (json!({"!": [true]}), json!({}), Ok(json!(false))),
1086            (json!({"!": [1]}), json!({}), Ok(json!(false))),
1087            (json!({"!": [0]}), json!({}), Ok(json!(true))),
1088            (json!({"!": [[]]}), json!({}), Ok(json!(true))),
1089            (json!({"!": [{}]}), json!({}), Ok(json!(false))),
1090            (json!({"!": [""]}), json!({}), Ok(json!(true))),
1091            (json!({"!": ["foo"]}), json!({}), Ok(json!(false))),
1092            (json!({"!": true}), json!({}), Ok(json!(false))),
1093        ]
1094    }
1095
1096    fn in_cases() -> Vec<(Value, Value, Result<Value, ()>)> {
1097        vec![
1098            // Invalid inputs
1099            (json!( {"in": []} ), json!({}), Err(())),
1100            (json!( {"in": [1, [], 1]} ), json!({}), Err(())),
1101            (json!( {"in": [1, "foo"]} ), json!({}), Err(())),
1102            (json!( {"in": [1, 1]} ), json!({}), Err(())),
1103            // Valid inputs
1104            (json!( {"in": [1, null]} ), json!({}), Ok(json!(false))),
1105            (json!( {"in": [1, [1, 2]]} ), json!({}), Ok(json!(true))),
1106            (json!( {"in": [1, [0, 2]]} ), json!({}), Ok(json!(false))),
1107            (json!( {"in": ["f", "foo"]} ), json!({}), Ok(json!(true))),
1108            (json!( {"in": ["f", "bar"]} ), json!({}), Ok(json!(false))),
1109            (json!( {"in": ["f", null]} ), json!({}), Ok(json!(false))),
1110            (
1111                json!( {"in": [null, [1, null]]} ),
1112                json!({}),
1113                Ok(json!(true)),
1114            ),
1115            (json!( {"in": [null, [1, 2]]} ), json!({}), Ok(json!(false))),
1116            (
1117                json!( {"in": [true, [true, 2]]} ),
1118                json!({}),
1119                Ok(json!(true)),
1120            ),
1121            (json!( {"in": [true, [1, 2]]} ), json!({}), Ok(json!(false))),
1122            (
1123                json!( {"in": [[1, 2], [[1, 2], 2]]} ),
1124                json!({}),
1125                Ok(json!(true)),
1126            ),
1127            (
1128                json!( {"in": [[], [[1, 2], 2]]} ),
1129                json!({}),
1130                Ok(json!(false)),
1131            ),
1132            (
1133                json!( {"in": [{"a": 1}, [{"a": 1}, 2]]} ),
1134                json!({}),
1135                Ok(json!(true)),
1136            ),
1137            (
1138                json!( {"in": [{"a": 1}, [{"a": 2}, 2]]} ),
1139                json!({}),
1140                Ok(json!(false)),
1141            ),
1142            (
1143                json!( {"in": [{"a": 1}, [{"a": 1, "b": 2}, 2]]} ),
1144                json!({}),
1145                Ok(json!(false)),
1146            ),
1147        ]
1148    }
1149
1150    fn assert_jsonlogic((op, data, exp): (Value, Value, Result<Value, ()>)) -> () {
1151        println!("Running rule: {:?} with data: {:?}", op, data);
1152        let result = apply(&op, &data);
1153        println!("- Result: {:?}", result);
1154        println!("- Expected: {:?}", exp);
1155        if exp.is_ok() {
1156            assert_eq!(result.unwrap(), exp.unwrap());
1157        } else {
1158            result.unwrap_err();
1159        }
1160    }
1161
1162    fn replace_operator(
1163        old_op: &'static str,
1164        new_op: &'static str,
1165        (op, data, exp): (Value, Value, Result<Value, ()>),
1166    ) -> (Value, Value, Result<Value, ()>) {
1167        (
1168            match op {
1169                Value::Object(obj) => json!({new_op: obj.get(old_op).unwrap()}),
1170                _ => panic!(),
1171            },
1172            data,
1173            exp,
1174        )
1175    }
1176
1177    fn flip_boolean_exp(
1178        (op, data, exp): (Value, Value, Result<Value, ()>),
1179    ) -> (Value, Value, Result<Value, ()>) {
1180        (
1181            op,
1182            data,
1183            match exp {
1184                Err(_) => exp,
1185                Ok(Value::Bool(exp)) => Ok(Value::Bool(!exp)),
1186                _ => panic!(),
1187            },
1188        )
1189    }
1190
1191    fn only_boolean(
1192        wanted: bool,
1193        (_, _, exp): &(Value, Value, Result<Value, ()>),
1194    ) -> bool {
1195        match exp {
1196            Err(_) => false,
1197            Ok(Value::Bool(exp)) => *exp == wanted,
1198            _ => panic!("unexpected type of expectation"),
1199        }
1200    }
1201
1202    #[test]
1203    fn test_no_op() {
1204        no_op_cases().into_iter().for_each(assert_jsonlogic)
1205    }
1206
1207    #[test]
1208    fn test_abstract_eq_op() {
1209        abstract_eq_cases().into_iter().for_each(assert_jsonlogic)
1210    }
1211
1212    #[test]
1213    fn test_abstract_ne_op() {
1214        abstract_ne_cases().into_iter().for_each(assert_jsonlogic)
1215    }
1216
1217    #[test]
1218    fn test_strict_eq_op() {
1219        strict_eq_cases().into_iter().for_each(assert_jsonlogic)
1220    }
1221
1222    #[test]
1223    fn test_strict_ne_op() {
1224        strict_ne_cases().into_iter().for_each(assert_jsonlogic)
1225    }
1226
1227    #[test]
1228    fn test_var_data_op() {
1229        var_cases().into_iter().for_each(assert_jsonlogic)
1230    }
1231
1232    #[test]
1233    fn test_missing_data_op() {
1234        missing_cases().into_iter().for_each(assert_jsonlogic)
1235    }
1236
1237    #[test]
1238    fn test_missing_some_data_op() {
1239        missing_some_cases().into_iter().for_each(assert_jsonlogic)
1240    }
1241
1242    #[test]
1243    fn test_if_op() {
1244        if_cases().into_iter().for_each(assert_jsonlogic)
1245    }
1246
1247    #[test]
1248    fn test_or_op() {
1249        or_cases().into_iter().for_each(assert_jsonlogic)
1250    }
1251
1252    #[test]
1253    fn test_and_op() {
1254        and_cases().into_iter().for_each(assert_jsonlogic)
1255    }
1256
1257    #[test]
1258    fn test_map_op() {
1259        map_cases().into_iter().for_each(assert_jsonlogic)
1260    }
1261
1262    #[test]
1263    fn test_filter_op() {
1264        filter_cases().into_iter().for_each(assert_jsonlogic)
1265    }
1266
1267    #[test]
1268    fn test_reduce_op() {
1269        reduce_cases().into_iter().for_each(assert_jsonlogic)
1270    }
1271
1272    #[test]
1273    fn test_all_op() {
1274        all_cases().into_iter().for_each(assert_jsonlogic)
1275    }
1276
1277    #[test]
1278    fn test_some_op() {
1279        some_cases().into_iter().for_each(assert_jsonlogic)
1280    }
1281
1282    #[test]
1283    fn test_none_op() {
1284        none_cases().into_iter().for_each(assert_jsonlogic)
1285    }
1286
1287    #[test]
1288    fn test_merge_op() {
1289        merge_cases().into_iter().for_each(assert_jsonlogic)
1290    }
1291
1292    #[test]
1293    fn test_cat_op() {
1294        cat_cases().into_iter().for_each(assert_jsonlogic)
1295    }
1296
1297    #[test]
1298    fn test_substr_op() {
1299        substr_cases().into_iter().for_each(assert_jsonlogic)
1300    }
1301
1302    #[test]
1303    fn test_log_op() {
1304        log_cases().into_iter().for_each(assert_jsonlogic)
1305    }
1306
1307    #[test]
1308    fn test_lt_op() {
1309        lt_cases().into_iter().for_each(assert_jsonlogic)
1310    }
1311
1312    #[test]
1313    fn test_lte_op() {
1314        lt_cases()
1315            .into_iter()
1316            .map(|case| replace_operator("<", "<=", case))
1317            .for_each(assert_jsonlogic);
1318        abstract_eq_cases()
1319            .into_iter()
1320            // Only get cases that are equal, since we don't know whether
1321            // non-equality cases were lt or gt or what.
1322            .filter(|case| only_boolean(true, case))
1323            .map(|case| replace_operator("==", "<=", case))
1324            .for_each(assert_jsonlogic);
1325    }
1326
1327    #[test]
1328    fn test_gt_op() {
1329        gt_cases().into_iter().for_each(assert_jsonlogic);
1330    }
1331
1332    #[test]
1333    fn test_gte_op() {
1334        gt_cases()
1335            .into_iter()
1336            .map(|case| replace_operator(">", ">=", case))
1337            .for_each(assert_jsonlogic);
1338        abstract_eq_cases()
1339            .into_iter()
1340            // Only get cases that are equal, since we don't know whether
1341            // non-equality cases were lt or gt or what.
1342            .filter(|case| only_boolean(true, case))
1343            .map(|case| replace_operator("==", ">=", case))
1344            .for_each(assert_jsonlogic);
1345    }
1346
1347    #[test]
1348    fn test_plus_op() {
1349        plus_cases().into_iter().for_each(assert_jsonlogic)
1350    }
1351
1352    #[test]
1353    fn test_minus_op() {
1354        minus_cases().into_iter().for_each(assert_jsonlogic)
1355    }
1356
1357    #[test]
1358    fn test_mul_op() {
1359        multiplication_cases()
1360            .into_iter()
1361            .for_each(assert_jsonlogic)
1362    }
1363
1364    #[test]
1365    fn test_div_op() {
1366        division_cases().into_iter().for_each(assert_jsonlogic)
1367    }
1368
1369    #[test]
1370    fn test_mod_op() {
1371        modulo_cases().into_iter().for_each(assert_jsonlogic)
1372    }
1373
1374    #[test]
1375    fn test_max_op() {
1376        max_cases().into_iter().for_each(assert_jsonlogic)
1377    }
1378
1379    #[test]
1380    fn test_min_op() {
1381        min_cases().into_iter().for_each(assert_jsonlogic)
1382    }
1383
1384    #[test]
1385    fn test_bang_op() {
1386        bang_cases().into_iter().for_each(assert_jsonlogic)
1387    }
1388
1389    #[test]
1390    fn test_bang_bang_op() {
1391        // just assert the opposite for all the bang cases
1392        bang_cases()
1393            .into_iter()
1394            .map(|case| replace_operator("!", "!!", case))
1395            .map(flip_boolean_exp)
1396            .for_each(assert_jsonlogic)
1397    }
1398
1399    #[test]
1400    fn test_in_op() {
1401        in_cases().into_iter().for_each(assert_jsonlogic)
1402    }
1403}