1use serde_json;
2use serde_json::Value;
3
4mod error;
5pub 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 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 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
85pub 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 (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 (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 (
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 (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 (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 (
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 (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 (
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 (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 (
232 json!({"var": "foo"}),
233 json!({"foo": "bar"}),
234 Ok(json!("bar")),
235 ),
236 (json!({"var": 1}), json!(["foo", "bar"]), Ok(json!("bar"))),
238 (json!({"var": "foo"}), json!({}), Ok(json!(null))),
240 (
241 json!({"==": [{"var": "first"}, true]}),
242 json!({"first": true}),
243 Ok(json!(true)),
244 ),
245 (
247 json!({"var": "foo.bar"}),
248 json!({"foo": {"bar": "baz"}}),
249 Ok(json!("baz")),
250 ),
251 (
253 json!({"var": "foo.1"}),
254 json!({"foo": ["bar", "baz", "pop"]}),
255 Ok(json!("baz")),
256 ),
257 (
259 json!({"var": "foo.bar"}),
260 json!({"foo": {"baz": "baz"}}),
261 Ok(json!(null)),
262 ),
263 (
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 (
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 (
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 (json!({"all": [1, 1]}), json!({}), Err(())),
581 (json!({"all": [{}, 1]}), json!({}), Err(())),
582 (json!({"all": [false, 1]}), json!({}), Err(())),
583 (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 (json!({"all": [[1, 2], 1]}), json!({}), Ok(json!(true))),
589 (json!({"all": [[1, 2], 0]}), json!({}), Ok(json!(false))),
590 (
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 (
613 json!({"all": [ {"var": "a"}, {"===": [{"var": ""}, "a"]} ]}),
614 json!({"a": "a"}),
615 Ok(json!(true)),
616 ),
617 (
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 (
630 json!({"all": [[1, -1, {"==": []}], {">": [{"var": ""}, 0]}]}),
635 json!({}),
636 Ok(json!(false)),
637 ),
638 (
639 json!({"all": [[1, {"==": []}, -1], {">": [{"var": ""}, 0]}]}),
643 json!({}),
644 Err(()),
645 ),
646 (
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 (json!({"some": [1, 1]}), json!({}), Err(())),
669 (json!({"some": [{}, 1]}), json!({}), Err(())),
670 (json!({"some": [false, 1]}), json!({}), Err(())),
671 (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 (json!({"some": [[1, 2], 1]}), json!({}), Ok(json!(true))),
677 (json!({"some": [[1, 2], 0]}), json!({}), Ok(json!(false))),
678 (
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 (
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 (
717 json!({"some": [[1, {"==": []}], {">": [{"var": ""}, 0]}]}),
722 json!({}),
723 Ok(json!(true)),
724 ),
725 (
726 json!({"some": [[-51, {"==": []}, -1], {">": [{"var": ""}, 0]}]}),
730 json!({}),
731 Err(()),
732 ),
733 (
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 (json!({"none": [1, 1]}), json!({}), Err(())),
751 (json!({"none": [{}, 1]}), json!({}), Err(())),
752 (json!({"none": [false, 1]}), json!({}), Err(())),
753 (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 (json!({"none": [[1, 2], 1]}), json!({}), Ok(json!(false))),
759 (json!({"none": [[1, 2], 0]}), json!({}), Ok(json!(true))),
760 (
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 (
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 (
799 json!({"none": [[1, {"==": []}], {">": [{"var": ""}, 0]}]}),
804 json!({}),
805 Ok(json!(false)),
806 ),
807 (
808 json!({"none": [[-51, {"==": []}, -1], {">": [{"var": ""}, 0]}]}),
812 json!({}),
813 Err(()),
814 ),
815 (
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 (json!({"substr": []}), json!({}), Err(())),
881 (json!({"substr": ["foo"]}), json!({}), Err(())),
882 (json!({"substr": ["foo", 1, 2, 3]}), json!({}), Err(())),
883 (json!({"substr": [12, 1]}), json!({}), Err(())),
885 (json!({"substr": ["foo", "12"]}), json!({}), Err(())),
886 (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 (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 (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 (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 (
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 (
917 json!({"substr": ["foo", 0, 10]}),
918 json!({}),
919 Ok(json!("foo")),
920 ),
921 (json!({"substr": ["foo", 0, -10]}), json!({}), Ok(json!(""))),
922 (
924 json!({"substr": ["foo", -3, -2]}),
925 json!({}),
926 Ok(json!("f")),
927 ),
928 (
930 json!({"substr": ["foo", -3, 2]}),
931 json!({}),
932 Ok(json!("fo")),
933 ),
934 (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 (json!({"log": []}), json!({}), Err(())),
958 (json!({"log": [1, 2]}), json!({}), Err(())),
959 (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"]}), 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 (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 (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 .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 .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 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}