resolver/
lib.rs

1//! Eval is a powerful expression evaluator.
2//!
3//! Supported operators: `!` `!=` `""` `''` `()` `[]` `.` `,` `>` `<` `>=` `<=`
4//! `==` `+` `-` `*` `/` `%` `&&` `||` `n..m`.
5//!
6//! Built-in functions: `min()` `max()` `len()` `is_empty()` `array()`.
7//!
8//! ## Examples
9//!
10//! You can do mathematical calculations with supported operators:
11//!
12//! ```
13//! use resolver::{eval, to_value};
14//!
15//! assert_eq!(eval("1 + 2 + 3"), Ok(to_value(6)));
16//! assert_eq!(eval("2 * 2 + 3"), Ok(to_value(7)));
17//! assert_eq!(eval("2 / 2 + 3"), Ok(to_value(4.0)));
18//! assert_eq!(eval("2 / 2 + 3 / 3"), Ok(to_value(2.0)));
19//! ```
20//!
21//! You can eval with context:
22//!
23//! ```
24//! use resolver::{Expr, to_value};
25//!
26//! assert_eq!(Expr::new("foo == bar")
27//!                .value("foo", true)
28//!                .value("bar", true)
29//!                .exec(),
30//!            Ok(to_value(true)));
31//! ```
32//!
33//! You can access data like javascript by using `.` and `[]`. `[]` supports expression.
34//!
35//! ```
36//! use resolver::{Expr, to_value};
37//! use std::collections::HashMap;
38//!
39//! let mut object = HashMap::new();
40//! object.insert("foos", vec!["Hello", "world", "!"]);
41//!
42//! assert_eq!(Expr::new("object.foos[2-1] == 'world'") // Access field `foos` and index `2-1`
43//!                .value("object", object)
44//!                .exec(),
45//!            Ok(to_value(true)));
46//! ```
47//!
48//! You can eval with function:
49//!
50//! ```
51//! use resolver::{Expr, to_value};
52//!
53//! assert_eq!(Expr::new("say_hello()")
54//!                .function("say_hello", |_| Ok(to_value("Hello world!")))
55//!                .exec(),
56//!            Ok(to_value("Hello world!")));
57//! ```
58//!
59//! You can create an array with `array()`:
60//!
61//! ```
62//! use resolver::{eval, to_value};
63//!
64//! assert_eq!(eval("array(1, 2, 3, 4, 5)"), Ok(to_value(vec![1, 2, 3, 4, 5])));
65//! ```
66//!
67//! You can create an integer array with `n..m`:
68//!
69//! ```
70//! use resolver::{eval, to_value};
71//!
72//! assert_eq!(eval("0..5"), Ok(to_value(vec![0, 1, 2, 3, 4])));
73//! ```
74//!
75//! ## Built-in functions
76//!
77//! ### min()
78//! Accept multiple arguments and return the minimum value.
79//!
80//! ### max()
81//! Accept multiple arguments and return the maximum value.
82//!
83//! ### len()
84//! Accept single arguments and return the length of value. Only accept String, Array, Object and Null.
85//!
86//! ### is_empty()
87//! Accept single arguments and return a boolean. Check whether the value is empty or not.
88//!
89//! ### array()
90//! Accept multiple arguments and return an array.
91//!
92//!
93#![recursion_limit="100"]
94#![deny(missing_docs)]
95
96#![forbid(unsafe_code)]
97#[macro_use]
98extern crate quick_error;
99extern crate serde;
100extern crate serde_json;
101
102mod math;
103mod function;
104mod operator;
105mod node;
106mod tree;
107mod error;
108mod builtin;
109mod expr;
110
111pub use expr::ExecOptions;
112use function::ConstFunction;
113pub use serde_json::Value;
114pub use error::Error;
115pub use function::Function;
116pub use expr::Expr;
117
118use std::{collections::HashMap, rc::Rc, cell::RefCell};
119use serde_json::to_value as json_to_value;
120use serde::Serialize;
121
122/// Convert variable to `serde_json::Value`
123pub fn to_value<S: Serialize>(v: S) -> Value {
124    json_to_value(v).unwrap()
125}
126
127/// Custom context.
128pub type Context = HashMap<String, Value>;
129/// Custom contexts. The value of the last context is searched first.
130pub type Contexts = Vec<Context>;
131/// Custom functions.
132pub type Functions = HashMap<String, Function>;
133/// Custom static function. Like fn
134pub type ConstFunctions = HashMap<String, ConstFunction>;
135
136/// Evaluates the value of an expression.
137pub fn eval(expr: &str) -> Result<Value, Error> {
138    Expr::new(expr).compile()?.exec()
139}
140
141type Compiled = Box<dyn Fn(&[Context], &Functions, Rc<RefCell<ConstFunctions>>) -> Result<Value, Error>>;
142
143#[cfg(test)]
144mod tests {
145    use std::collections::HashMap;
146    
147    use crate::to_value;
148    use crate::error::Error;
149    use crate::Expr;
150    use crate::tree::Tree;
151    use crate::Value;
152    use crate::eval;
153
154    #[test]
155    fn test_add() {
156        assert_eq!(eval("2 + 3"), Ok(to_value(5)));
157    }
158
159    #[test]
160    fn test_brackets_add() {
161        assert_eq!(eval("(2 + 3) + (3 + 5)"), Ok(to_value(13)));
162    }
163
164    #[test]
165    fn test_brackets_float_add() {
166        assert_eq!(eval("(2 + 3.2) + (3 + 5)"), Ok(to_value(13.2)));
167    }
168
169    #[test]
170    fn test_brackets_float_mul() {
171        assert_eq!(eval("(2 + 3.2) * 5"), Ok(to_value(26.0)));
172    }
173
174    #[test]
175    fn test_brackets_sub() {
176        assert_eq!(eval("(4 - 3) * 5"), Ok(to_value(5)));
177    }
178
179    #[test]
180    fn test_useless_brackets() {
181        assert_eq!(eval("2 + 3 + (5)"), Ok(to_value(10)));
182    }
183
184    #[test]
185    fn test_error_brackets_not_with_function() {
186        assert_eq!(eval("5 + ()"), Err(Error::BracketNotWithFunction));
187    }
188
189    #[test]
190    fn test_deep_brackets() {
191        assert_eq!(eval("(2 + (3 + 4) + (6 + (6 + 7)) + 5)"), Ok(to_value(33)));
192    }
193
194    #[test]
195    fn test_brackets_div() {
196        assert_eq!(eval("(4 / (2 + 2)) * 5"), Ok(to_value(5.0)));
197    }
198
199    #[test]
200    fn test_min() {
201        assert_eq!(eval("min(30, 5, 245, 20)"), Ok(to_value(5)));
202    }
203
204    #[test]
205    fn test_min_brackets() {
206        assert_eq!(
207            eval("(min(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
208            Ok(to_value(100))
209        );
210    }
211
212    #[test]
213    fn test_min_and_mul() {
214        assert_eq!(eval("min(30, 5, 245, 20) * 10"), Ok(to_value(50)));
215    }
216
217    #[test]
218    fn test_max() {
219        assert_eq!(eval("max(30, 5, 245, 20)"), Ok(to_value(245)));
220    }
221
222    #[test]
223    fn test_max_brackets() {
224        assert_eq!(
225            eval("(max(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
226            Ok(to_value(2500))
227        );
228    }
229
230    #[test]
231    fn test_max_and_mul() {
232        assert_eq!(eval("max(30, 5, 245, 20) * 10"), Ok(to_value(2450)));
233    }
234
235    #[test]
236    fn test_len_array() {
237        assert_eq!(eval("len(array(2, 3, 4, 5, 6))"), Ok(to_value(5)));
238    }
239
240    #[test]
241    fn test_null_and_number() {
242        assert_eq!(eval("hos != 0"), Ok(to_value(true)));
243        assert_eq!(eval("hos > 0"), Ok(to_value(false)));
244    }
245
246    #[test]
247    fn test_len_string() {
248        assert_eq!(eval("len('Hello world!')"), Ok(to_value(12)));
249    }
250
251    #[test]
252    fn test_len_object() {
253        let mut object = HashMap::new();
254        object.insert("field1", "value1");
255        object.insert("field2", "value2");
256        object.insert("field3", "value3");
257        assert_eq!(
258            Expr::new("len(object)").value("object", object).exec(),
259            Ok(to_value(3_i64))
260        );
261    }
262
263    #[test]
264    fn test_brackets_1() {
265        assert_eq!(eval("(5) + (min(3, 4, 5)) + 20"), Ok(to_value(28)));
266    }
267
268    #[test]
269    fn test_brackets_2() {
270        assert_eq!(eval("(((5) / 5))"), Ok(to_value(1.0)));
271    }
272
273    #[test]
274    fn test_string_add() {
275        assert_eq!(eval(r#""Hello"+", world!""#), Ok(to_value("Hello, world!")));
276    }
277
278    #[test]
279    fn test_equal() {
280        assert_eq!(eval("1 == 1"), Ok(to_value(true)));
281    }
282
283    #[test]
284    fn test_not_equal() {
285        assert_eq!(eval("1 != 2"), Ok(to_value(true)));
286    }
287
288    #[test]
289    fn test_multiple_equal() {
290        assert_eq!(eval("(1 == 2) == (2 == 3)"), Ok(to_value(true)));
291    }
292
293    #[test]
294    fn test_multiple_not_equal() {
295        assert_eq!(eval("(1 != 2) == (2 != 3)"), Ok(to_value(true)));
296    }
297
298    #[test]
299    fn test_greater_than() {
300        assert_eq!(eval("1 > 2"), Ok(to_value(false)));
301        assert_eq!(eval("2 > 1"), Ok(to_value(true)));
302    }
303
304    #[test]
305    fn test_less_than() {
306        assert_eq!(eval("2 < 1"), Ok(to_value(false)));
307        assert_eq!(eval("1 < 2"), Ok(to_value(true)));
308    }
309
310    #[test]
311    fn test_greater_and_less() {
312        assert_eq!(eval("(2 > 1) == (1 < 2)"), Ok(to_value(true)));
313    }
314
315    #[test]
316    fn test_ge() {
317        assert_eq!(eval("2 >= 1"), Ok(to_value(true)));
318        assert_eq!(eval("2 >= 2"), Ok(to_value(true)));
319        assert_eq!(eval("2 >= 3"), Ok(to_value(false)));
320    }
321
322    #[test]
323    fn test_le() {
324        assert_eq!(eval("2 <= 1"), Ok(to_value(false)));
325        assert_eq!(eval("2 <= 2"), Ok(to_value(true)));
326        assert_eq!(eval("2 <= 3"), Ok(to_value(true)));
327    }
328
329    #[test]
330    fn test_quotes() {
331        assert_eq!(eval(r#""1><2" + "3<>4""#), Ok(to_value("1><23<>4")));
332        assert_eq!(eval(r#""1==2" + "3--4""#), Ok(to_value("1==23--4")));
333        assert_eq!(eval(r#""1!=2" + "3>>4""#), Ok(to_value("1!=23>>4")));
334        assert_eq!(eval(r#""><1!=2" + "3>>4""#), Ok(to_value("><1!=23>>4")));
335    }
336
337    #[test]
338    fn test_single_quote() {
339        assert_eq!(eval(r#"'1><2' + '3<>4'"#), Ok(to_value("1><23<>4")));
340        assert_eq!(eval(r#"'1==2' + '3--4'"#), Ok(to_value("1==23--4")));
341        assert_eq!(eval(r#"'1!=2' + '3>>4'"#), Ok(to_value("1!=23>>4")));
342        assert_eq!(eval(r#"'!=1<>2' + '3>>4'"#), Ok(to_value("!=1<>23>>4")));
343    }
344
345    #[test]
346    fn test_single_and_double_quote() {
347        assert_eq!(
348            eval(r#"' """" ' + ' """" '"#),
349            Ok(to_value(r#" """"  """" "#))
350        );
351    }
352
353    #[test]
354    fn test_double_and_single_quote() {
355        assert_eq!(
356            eval(r#"" '''' " + " '''' ""#),
357            Ok(to_value(r#" ''''  '''' "#))
358        );
359    }
360
361    #[test]
362    fn test_array() {
363        assert_eq!(eval("array(1, 2, 3, 4)"), Ok(to_value(vec![1, 2, 3, 4])));
364    }
365
366    #[test]
367    fn test_range() {
368        assert_eq!(eval("0..5"), Ok(to_value(vec![0, 1, 2, 3, 4])));
369    }
370
371    #[test]
372    fn test_range_and_min() {
373        assert_eq!(eval("min(0..5)"), Ok(to_value(0)));
374    }
375
376    #[test]
377    fn test_rem_1() {
378        assert_eq!(eval("2 % 2"), Ok(to_value(0)));
379    }
380
381    #[test]
382    fn test_rem_2() {
383        assert_eq!(eval("5 % 56 % 5"), Ok(to_value(0)));
384    }
385
386    #[test]
387    fn test_rem_3() {
388        assert_eq!(eval("5.5 % 23"), Ok(to_value(5.5)));
389    }
390
391    #[test]
392    fn test_rem_4() {
393        assert_eq!(eval("23 % 5.5"), Ok(to_value(1.0)));
394    }
395
396    #[test]
397    fn test_and_1() {
398        assert_eq!(eval("3 > 2 && 2 > 1"), Ok(to_value(true)));
399    }
400
401    #[test]
402    fn test_and_2() {
403        assert_eq!(eval("3 == 2 && 2 == 1"), Ok(to_value(false)));
404    }
405
406    #[test]
407    fn test_and_3() {
408        assert_eq!(eval("3 > 2 && 2 == 1"), Ok(to_value(false)));
409    }
410
411    #[test]
412    fn test_or_1() {
413        assert_eq!(eval("3 > 2 || 2 > 1"), Ok(to_value(true)));
414    }
415
416    #[test]
417    fn test_or_2() {
418        assert_eq!(eval("3 < 2 || 2 < 1"), Ok(to_value(false)));
419    }
420
421    #[test]
422    fn test_or_3() {
423        assert_eq!(eval("3 > 2 || 2 < 1"), Ok(to_value(true)));
424    }
425
426    #[test]
427    fn test_or_4() {
428        assert_eq!(eval("3 < 2 || 2 > 1"), Ok(to_value(true)));
429    }
430
431    #[test]
432    fn test_not() {
433        assert_eq!(eval("!false"), Ok(to_value(true)));
434        assert_eq!(eval("!true"), Ok(to_value(false)));
435        assert_eq!(eval("!(1 != 2)"), Ok(to_value(false)));
436        assert_eq!(eval("!(1 == 2)"), Ok(to_value(true)));
437        assert_eq!(eval("!(1 == 2) == true"), Ok(to_value(true)));
438    }
439
440    #[test]
441    fn test_not_and_brackets() {
442        assert_eq!(eval("(!(1 == 2)) == true"), Ok(to_value(true)));
443    }
444
445    #[test]
446    fn test_object_access() {
447        let mut object = HashMap::new();
448        object.insert("foo", "Foo, hello world!");
449        object.insert("bar", "Bar, hello world!");
450        assert_eq!(
451            Expr::new("object.foo == 'Foo, hello world!'")
452                .value("object", object)
453                .exec(),
454            Ok(to_value(true))
455        );
456    }
457
458    #[test]
459    fn test_object_dynamic_access() {
460        let mut object = HashMap::new();
461        object.insert("foo", "Foo, hello world!");
462        object.insert("bar", "Bar, hello world!");
463        assert_eq!(
464            Expr::new("object['foo'] == 'Foo, hello world!'")
465                .value("object", object)
466                .exec(),
467            Ok(to_value(true))
468        );
469    }
470
471    #[test]
472    fn test_object_dynamic_access_2() {
473        let mut object = HashMap::new();
474        object.insert("foo", "Foo, hello world!");
475        object.insert("bar", "Bar, hello world!");
476        assert_eq!(
477            Expr::new("object[foo] == 'Foo, hello world!'")
478                .value("object", object)
479                .value("foo", "foo")
480                .exec(),
481            Ok(to_value(true))
482        );
483    }
484
485    #[test]
486    fn test_path() {
487        assert_eq!(Expr::new("array[2-2].foo[2-2]").exec(), Ok(Value::Null));
488    }
489
490    #[test]
491    fn test_array_access() {
492        let array = vec!["hello", "world", "!"];
493        assert_eq!(
494            Expr::new(
495                "array[1-1] == 'hello' && array[1] == 'world' && array[2] == '!'",
496            ).value("array", array)
497                .exec(),
498            Ok(to_value(true))
499        );
500    }
501
502    #[test]
503    fn test_builtin_is_empty() {
504        assert_eq!(
505            Expr::new("is_empty(array)")
506                .value("array", Vec::<String>::new())
507                .exec(),
508            Ok(to_value(true))
509        );
510    }
511
512    #[test]
513    fn test_builtin_min() {
514        assert_eq!(
515            Expr::new("min(array)")
516                .value("array", vec![23_i32, 34_i32, 45_i32, 2_i32])
517                .exec(),
518            Ok(to_value(2_i32))
519        );
520    }
521
522    #[test]
523    fn test_custom_function() {
524        assert_eq!(
525            Expr::new("output()")
526                .function(
527                    "output",
528                    |_| Ok(to_value("This is custom function's output")),
529                )
530                .exec(),
531            Ok(to_value("This is custom function's output"))
532        );
533    }
534
535    #[test]
536    fn test_error_start_with_non_value_operator() {
537        let mut tree = Tree {
538            raw: "+ + 5".to_owned(),
539            ..Default::default()
540        };
541
542        tree.parse_pos().unwrap();
543        tree.parse_operators().unwrap();
544
545        assert_eq!(tree.parse_node(), Err(Error::StartWithNonValueOperator));
546    }
547
548    #[test]
549    fn test_error_duplicate_operator() {
550        let mut tree = Tree {
551            raw: "5 + + 5".to_owned(),
552            ..Default::default()
553        };
554
555        tree.parse_pos().unwrap();
556        tree.parse_operators().unwrap();
557
558        assert_eq!(tree.parse_node(), Err(Error::DuplicateOperatorNode));
559    }
560
561    #[test]
562    fn test_error_duplicate_value() {
563        let mut tree = Tree {
564            raw: "2 + 6 5".to_owned(),
565            ..Default::default()
566        };
567
568        tree.parse_pos().unwrap();
569        tree.parse_operators().unwrap();
570
571        assert_eq!(tree.parse_node(), Err(Error::DuplicateValueNode));
572    }
573
574    #[test]
575    fn test_error_unpaired_brackets() {
576        let mut tree = Tree {
577            raw: "(2 + 3)) * 5".to_owned(),
578            ..Default::default()
579        };
580
581        tree.parse_pos().unwrap();
582
583        assert_eq!(tree.parse_operators(), Err(Error::UnpairedBrackets));
584    }
585
586    #[test]
587    fn test_error_comma() {
588        let mut tree = Tree {
589            raw: ", 2 + 5".to_owned(),
590            ..Default::default()
591        };
592
593        tree.parse_pos().unwrap();
594        tree.parse_operators().unwrap();
595
596        assert_eq!(tree.parse_node(), Err(Error::CommaNotWithFunction));
597    }
598
599    #[test]
600    fn test_eval_issue_2() {
601        assert_eq!(eval("2 * (4 + 0) + 4"), Ok(to_value(12)));
602        assert_eq!(eval("2 * (2 + 2) + (1 + 3)"), Ok(to_value(12)));
603        assert_eq!(eval("2 * (4) + (4)"), Ok(to_value(12)));
604    }
605
606    #[test]
607    fn test_eval_math_function(){
608        fn pow(v: Vec<Value>)->Result<Value, Error>{
609            let Some(base) = v.get(0) else {
610                return Err(Error::ArgumentsLess(2));
611            };
612            let Some(pow) = v.get(1) else {
613                return Err(Error::ArgumentsLess(2));
614            };
615            let Value::Number(base) = base else {
616                return Err(Error::ExpectedNumber);
617            };
618            let Value::Number(pow) = pow else {
619                return Err(Error::ExpectedNumber);
620            };
621            let Some(base) = base.as_i64() else {
622                return Err(Error::Custom("Must can into i64".into()));
623            };
624            let Some(pow) = pow.as_u64() else {
625                return Err(Error::Custom("Must can into u64".into()));
626            };
627            Ok(base.pow(pow as u32).into())
628        }
629        fn add2(v: Vec<Value>)->Result<Value, Error>{
630            let Some(base) = v.get(0) else {
631                return Err(Error::ArgumentsLess(1));
632            }; 
633            let Value::Number(base) = base else {
634                return Err(Error::ExpectedNumber);
635            };
636            let Some(base) = base.as_i64() else {
637                return Err(Error::Custom("Must can into i64".into()));
638            };
639            Ok((base + 2).into())
640        }
641        let e = Expr::new("add2(pow(2, 2) + pow(2, 2))").const_function("pow", pow).const_function("add2",add2);
642        assert_eq!(e.compile().unwrap().exec(), Ok(to_value(4 + 4 + 2)));
643    }
644}
645
646#[cfg(all(feature = "unstable", test))]
647mod benches {
648    extern crate test;
649    use resolver;
650    use tree::Tree;
651    use Expr;
652
653    #[bench]
654    fn bench_deep_brackets(b: &mut test::Bencher) {
655        b.iter(|| eval("(2 + (3 + 4) + (6 + (6 + 7)) + 5)"));
656    }
657
658    #[bench]
659    fn bench_parse_pos(b: &mut test::Bencher) {
660        let mut tree = Tree {
661            raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
662            ..Default::default()
663        };
664
665        b.iter(|| tree.parse_pos().unwrap());
666    }
667
668    #[bench]
669    fn bench_parse_operators(b: &mut test::Bencher) {
670        let mut tree = Tree {
671            raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
672            ..Default::default()
673        };
674
675        tree.parse_pos().unwrap();
676        b.iter(|| tree.parse_operators().unwrap());
677    }
678
679    #[bench]
680    fn bench_parse_nodes(b: &mut test::Bencher) {
681        let mut tree = Tree {
682            raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
683            ..Default::default()
684        };
685
686        tree.parse_pos().unwrap();
687        tree.parse_operators().unwrap();
688        b.iter(|| tree.parse_node().unwrap());
689    }
690
691    #[bench]
692    fn bench_compile(b: &mut test::Bencher) {
693        b.iter(|| {
694            let mut tree = Tree {
695                raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
696                ..Default::default()
697            };
698            tree.parse_pos().unwrap();
699            tree.parse_operators().unwrap();
700            tree.parse_node().unwrap();
701            tree.compile().unwrap();
702        });
703    }
704
705    #[bench]
706    fn bench_exec(b: &mut test::Bencher) {
707        let expr = Expr::new("(2 + (3 + 4) + (6 + (6 + 7)) + 5)")
708            .compile()
709            .unwrap();
710        b.iter(|| expr.exec().unwrap())
711    }
712
713    #[bench]
714    fn bench_eval(b: &mut test::Bencher) {
715        b.iter(|| eval("(2 + (3 + 4) + (6 + (6 + 7)) + 5)"));
716    }
717}