eval/
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 eval::{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 eval::{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 eval::{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 eval::{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 eval::{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 eval::{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#![cfg_attr(all(feature = "unstable", test), feature(test))]
96
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;
112pub use serde_json::Value;
113pub use error::Error;
114pub use function::Function;
115pub use expr::Expr;
116
117use std::collections::HashMap;
118use serde_json::to_value as json_to_value;
119use serde::Serialize;
120
121/// Convert variable to `serde_json::Value`
122pub fn to_value<S: Serialize>(v: S) -> Value {
123    json_to_value(v).unwrap()
124}
125
126/// Custom context.
127pub type Context = HashMap<String, Value>;
128/// Custom contexts. The value of the last context is searched first.
129pub type Contexts = Vec<Context>;
130/// Custom functions.
131pub type Functions = HashMap<String, Function>;
132
133/// Evaluates the value of an expression.
134pub fn eval(expr: &str) -> Result<Value, Error> {
135    Expr::new(expr).compile()?.exec()
136}
137
138
139type Compiled = Box<Fn(&[Context], &Functions) -> Result<Value, Error>>;
140
141
142
143#[cfg(test)]
144mod tests {
145    use to_value;
146    use error::Error;
147    use Expr;
148    use tree::Tree;
149    use Value;
150    use eval;
151    use std::collections::HashMap;
152
153    #[test]
154    fn test_add() {
155        assert_eq!(eval("2 + 3"), Ok(to_value(5)));
156    }
157
158    #[test]
159    fn test_brackets_add() {
160        assert_eq!(eval("(2 + 3) + (3 + 5)"), Ok(to_value(13)));
161    }
162
163    #[test]
164    fn test_brackets_float_add() {
165        assert_eq!(eval("(2 + 3.2) + (3 + 5)"), Ok(to_value(13.2)));
166    }
167
168    #[test]
169    fn test_brackets_float_mul() {
170        assert_eq!(eval("(2 + 3.2) * 5"), Ok(to_value(26.0)));
171    }
172
173    #[test]
174    fn test_brackets_sub() {
175        assert_eq!(eval("(4 - 3) * 5"), Ok(to_value(5)));
176    }
177
178    #[test]
179    fn test_useless_brackets() {
180        assert_eq!(eval("2 + 3 + (5)"), Ok(to_value(10)));
181    }
182
183    #[test]
184    fn test_error_brackets_not_with_function() {
185        assert_eq!(eval("5 + ()"), Err(Error::BracketNotWithFunction));
186    }
187
188    #[test]
189    fn test_deep_brackets() {
190        assert_eq!(eval("(2 + (3 + 4) + (6 + (6 + 7)) + 5)"), Ok(to_value(33)));
191    }
192
193    #[test]
194    fn test_brackets_div() {
195        assert_eq!(eval("(4 / (2 + 2)) * 5"), Ok(to_value(5.0)));
196    }
197
198    #[test]
199    fn test_min() {
200        assert_eq!(eval("min(30, 5, 245, 20)"), Ok(to_value(5)));
201    }
202
203    #[test]
204    fn test_min_brackets() {
205        assert_eq!(
206            eval("(min(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
207            Ok(to_value(100))
208        );
209    }
210
211    #[test]
212    fn test_min_and_mul() {
213        assert_eq!(eval("min(30, 5, 245, 20) * 10"), Ok(to_value(50)));
214    }
215
216    #[test]
217    fn test_max() {
218        assert_eq!(eval("max(30, 5, 245, 20)"), Ok(to_value(245)));
219    }
220
221    #[test]
222    fn test_max_brackets() {
223        assert_eq!(
224            eval("(max(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
225            Ok(to_value(2500))
226        );
227    }
228
229    #[test]
230    fn test_max_and_mul() {
231        assert_eq!(eval("max(30, 5, 245, 20) * 10"), Ok(to_value(2450)));
232    }
233
234    #[test]
235    fn test_len_array() {
236        assert_eq!(eval("len(array(2, 3, 4, 5, 6))"), Ok(to_value(5)));
237    }
238
239    #[test]
240    fn test_null_and_number() {
241        assert_eq!(eval("hos != 0"), Ok(to_value(true)));
242        assert_eq!(eval("hos > 0"), Ok(to_value(false)));
243    }
244
245    #[test]
246    fn test_len_string() {
247        assert_eq!(eval("len('Hello world!')"), Ok(to_value(12)));
248    }
249
250    #[test]
251    fn test_len_object() {
252        let mut object = HashMap::new();
253        object.insert("field1", "value1");
254        object.insert("field2", "value2");
255        object.insert("field3", "value3");
256        assert_eq!(
257            Expr::new("len(object)").value("object", object).exec(),
258            Ok(to_value(3))
259        );
260    }
261
262    #[test]
263    fn test_brackets_1() {
264        assert_eq!(eval("(5) + (min(3, 4, 5)) + 20"), Ok(to_value(28)));
265    }
266
267    #[test]
268    fn test_brackets_2() {
269        assert_eq!(eval("(((5) / 5))"), Ok(to_value(1.0)));
270    }
271
272    #[test]
273    fn test_string_add() {
274        assert_eq!(eval(r#""Hello"+", world!""#), Ok(to_value("Hello, world!")));
275    }
276
277    #[test]
278    fn test_equal() {
279        assert_eq!(eval("1 == 1"), Ok(to_value(true)));
280    }
281
282    #[test]
283    fn test_not_equal() {
284        assert_eq!(eval("1 != 2"), Ok(to_value(true)));
285    }
286
287    #[test]
288    fn test_multiple_equal() {
289        assert_eq!(eval("(1 == 2) == (2 == 3)"), Ok(to_value(true)));
290    }
291
292    #[test]
293    fn test_multiple_not_equal() {
294        assert_eq!(eval("(1 != 2) == (2 != 3)"), Ok(to_value(true)));
295    }
296
297    #[test]
298    fn test_greater_than() {
299        assert_eq!(eval("1 > 2"), Ok(to_value(false)));
300        assert_eq!(eval("2 > 1"), Ok(to_value(true)));
301    }
302
303    #[test]
304    fn test_less_than() {
305        assert_eq!(eval("2 < 1"), Ok(to_value(false)));
306        assert_eq!(eval("1 < 2"), Ok(to_value(true)));
307    }
308
309    #[test]
310    fn test_greater_and_less() {
311        assert_eq!(eval("(2 > 1) == (1 < 2)"), Ok(to_value(true)));
312    }
313
314    #[test]
315    fn test_ge() {
316        assert_eq!(eval("2 >= 1"), Ok(to_value(true)));
317        assert_eq!(eval("2 >= 2"), Ok(to_value(true)));
318        assert_eq!(eval("2 >= 3"), Ok(to_value(false)));
319    }
320
321    #[test]
322    fn test_le() {
323        assert_eq!(eval("2 <= 1"), Ok(to_value(false)));
324        assert_eq!(eval("2 <= 2"), Ok(to_value(true)));
325        assert_eq!(eval("2 <= 3"), Ok(to_value(true)));
326    }
327
328    #[test]
329    fn test_quotes() {
330        assert_eq!(eval(r#""1><2" + "3<>4""#), Ok(to_value("1><23<>4")));
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    }
335
336    #[test]
337    fn test_single_quote() {
338        assert_eq!(eval(r#"'1><2' + '3<>4'"#), Ok(to_value("1><23<>4")));
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    }
343
344    #[test]
345    fn test_single_and_double_quote() {
346        assert_eq!(
347            eval(r#"' """" ' + ' """" '"#),
348            Ok(to_value(r#" """"  """" "#))
349        );
350    }
351
352    #[test]
353    fn test_double_and_single_quote() {
354        assert_eq!(
355            eval(r#"" '''' " + " '''' ""#),
356            Ok(to_value(r#" ''''  '''' "#))
357        );
358    }
359
360    #[test]
361    fn test_array() {
362        assert_eq!(eval("array(1, 2, 3, 4)"), Ok(to_value(vec![1, 2, 3, 4])));
363    }
364
365    #[test]
366    fn test_range() {
367        assert_eq!(eval("0..5"), Ok(to_value(vec![0, 1, 2, 3, 4])));
368    }
369
370    #[test]
371    fn test_range_and_min() {
372        assert_eq!(eval("min(0..5)"), Ok(to_value(0)));
373    }
374
375    #[test]
376    fn test_rem_1() {
377        assert_eq!(eval("2 % 2"), Ok(to_value(0)));
378    }
379
380    #[test]
381    fn test_rem_2() {
382        assert_eq!(eval("5 % 56 % 5"), Ok(to_value(0)));
383    }
384
385    #[test]
386    fn test_rem_3() {
387        assert_eq!(eval("5.5 % 23"), Ok(to_value(5.5)));
388    }
389
390    #[test]
391    fn test_rem_4() {
392        assert_eq!(eval("23 % 5.5"), Ok(to_value(1.0)));
393    }
394
395    #[test]
396    fn test_and_1() {
397        assert_eq!(eval("3 > 2 && 2 > 1"), Ok(to_value(true)));
398    }
399
400    #[test]
401    fn test_and_2() {
402        assert_eq!(eval("3 == 2 && 2 == 1"), Ok(to_value(false)));
403    }
404
405    #[test]
406    fn test_and_3() {
407        assert_eq!(eval("3 > 2 && 2 == 1"), Ok(to_value(false)));
408    }
409
410    #[test]
411    fn test_or_1() {
412        assert_eq!(eval("3 > 2 || 2 > 1"), Ok(to_value(true)));
413    }
414
415    #[test]
416    fn test_or_2() {
417        assert_eq!(eval("3 < 2 || 2 < 1"), Ok(to_value(false)));
418    }
419
420    #[test]
421    fn test_or_3() {
422        assert_eq!(eval("3 > 2 || 2 < 1"), Ok(to_value(true)));
423    }
424
425    #[test]
426    fn test_or_4() {
427        assert_eq!(eval("3 < 2 || 2 > 1"), Ok(to_value(true)));
428    }
429
430    #[test]
431    fn test_not() {
432        assert_eq!(eval("!false"), Ok(to_value(true)));
433        assert_eq!(eval("!true"), Ok(to_value(false)));
434        assert_eq!(eval("!(1 != 2)"), Ok(to_value(false)));
435        assert_eq!(eval("!(1 == 2)"), Ok(to_value(true)));
436        assert_eq!(eval("!(1 == 2) == true"), Ok(to_value(true)));
437    }
438
439    #[test]
440    fn test_not_and_brackets() {
441        assert_eq!(eval("(!(1 == 2)) == true"), Ok(to_value(true)));
442    }
443
444    #[test]
445    fn test_object_access() {
446        let mut object = HashMap::new();
447        object.insert("foo", "Foo, hello world!");
448        object.insert("bar", "Bar, hello world!");
449        assert_eq!(
450            Expr::new("object.foo == 'Foo, hello world!'")
451                .value("object", object)
452                .exec(),
453            Ok(to_value(true))
454        );
455    }
456
457    #[test]
458    fn test_object_dynamic_access() {
459        let mut object = HashMap::new();
460        object.insert("foo", "Foo, hello world!");
461        object.insert("bar", "Bar, hello world!");
462        assert_eq!(
463            Expr::new("object['foo'] == 'Foo, hello world!'")
464                .value("object", object)
465                .exec(),
466            Ok(to_value(true))
467        );
468    }
469
470    #[test]
471    fn test_object_dynamic_access_2() {
472        let mut object = HashMap::new();
473        object.insert("foo", "Foo, hello world!");
474        object.insert("bar", "Bar, hello world!");
475        assert_eq!(
476            Expr::new("object[foo] == 'Foo, hello world!'")
477                .value("object", object)
478                .value("foo", "foo")
479                .exec(),
480            Ok(to_value(true))
481        );
482    }
483
484    #[test]
485    fn test_path() {
486        assert_eq!(Expr::new("array[2-2].foo[2-2]").exec(), Ok(Value::Null));
487    }
488
489    #[test]
490    fn test_array_access() {
491        let array = vec!["hello", "world", "!"];
492        assert_eq!(
493            Expr::new(
494                "array[1-1] == 'hello' && array[1] == 'world' && array[2] == '!'",
495            ).value("array", array)
496                .exec(),
497            Ok(to_value(true))
498        );
499    }
500
501    #[test]
502    fn test_builtin_is_empty() {
503        assert_eq!(
504            Expr::new("is_empty(array)")
505                .value("array", Vec::<String>::new())
506                .exec(),
507            Ok(to_value(true))
508        );
509    }
510
511    #[test]
512    fn test_builtin_min() {
513        assert_eq!(
514            Expr::new("min(array)")
515                .value("array", vec![23, 34, 45, 2])
516                .exec(),
517            Ok(to_value(2))
518        );
519    }
520
521    #[test]
522    fn test_custom_function() {
523        assert_eq!(
524            Expr::new("output()")
525                .function(
526                    "output",
527                    |_| Ok(to_value("This is custom function's output")),
528                )
529                .exec(),
530            Ok(to_value("This is custom function's output"))
531        );
532    }
533
534    #[test]
535    fn test_error_start_with_non_value_operator() {
536        let mut tree = Tree {
537            raw: "+ + 5".to_owned(),
538            ..Default::default()
539        };
540
541        tree.parse_pos().unwrap();
542        tree.parse_operators().unwrap();
543
544        assert_eq!(tree.parse_node(), Err(Error::StartWithNonValueOperator));
545    }
546
547    #[test]
548    fn test_error_duplicate_operator() {
549        let mut tree = Tree {
550            raw: "5 + + 5".to_owned(),
551            ..Default::default()
552        };
553
554        tree.parse_pos().unwrap();
555        tree.parse_operators().unwrap();
556
557        assert_eq!(tree.parse_node(), Err(Error::DuplicateOperatorNode));
558    }
559
560    #[test]
561    fn test_error_duplicate_value() {
562        let mut tree = Tree {
563            raw: "2 + 6 5".to_owned(),
564            ..Default::default()
565        };
566
567        tree.parse_pos().unwrap();
568        tree.parse_operators().unwrap();
569
570        assert_eq!(tree.parse_node(), Err(Error::DuplicateValueNode));
571    }
572
573    #[test]
574    fn test_error_unpaired_brackets() {
575        let mut tree = Tree {
576            raw: "(2 + 3)) * 5".to_owned(),
577            ..Default::default()
578        };
579
580        tree.parse_pos().unwrap();
581
582        assert_eq!(tree.parse_operators(), Err(Error::UnpairedBrackets));
583    }
584
585    #[test]
586    fn test_error_comma() {
587        let mut tree = Tree {
588            raw: ", 2 + 5".to_owned(),
589            ..Default::default()
590        };
591
592        tree.parse_pos().unwrap();
593        tree.parse_operators().unwrap();
594
595        assert_eq!(tree.parse_node(), Err(Error::CommaNotWithFunction));
596    }
597
598    #[test]
599    fn test_eval_issue_2() {
600        assert_eq!(eval("2 * (4 + 0) + 4"), Ok(to_value(12)));
601        assert_eq!(eval("2 * (2 + 2) + (1 + 3)"), Ok(to_value(12)));
602        assert_eq!(eval("2 * (4) + (4)"), Ok(to_value(12)));
603    }
604}
605
606#[cfg(all(feature = "unstable", test))]
607mod benches {
608    extern crate test;
609    use eval;
610    use tree::Tree;
611    use Expr;
612
613    #[bench]
614    fn bench_deep_brackets(b: &mut test::Bencher) {
615        b.iter(|| eval("(2 + (3 + 4) + (6 + (6 + 7)) + 5)"));
616    }
617
618    #[bench]
619    fn bench_parse_pos(b: &mut test::Bencher) {
620        let mut tree = Tree {
621            raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
622            ..Default::default()
623        };
624
625        b.iter(|| tree.parse_pos().unwrap());
626    }
627
628    #[bench]
629    fn bench_parse_operators(b: &mut test::Bencher) {
630        let mut tree = Tree {
631            raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
632            ..Default::default()
633        };
634
635        tree.parse_pos().unwrap();
636        b.iter(|| tree.parse_operators().unwrap());
637    }
638
639    #[bench]
640    fn bench_parse_nodes(b: &mut test::Bencher) {
641        let mut tree = Tree {
642            raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
643            ..Default::default()
644        };
645
646        tree.parse_pos().unwrap();
647        tree.parse_operators().unwrap();
648        b.iter(|| tree.parse_node().unwrap());
649    }
650
651    #[bench]
652    fn bench_compile(b: &mut test::Bencher) {
653        b.iter(|| {
654            let mut tree = Tree {
655                raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
656                ..Default::default()
657            };
658            tree.parse_pos().unwrap();
659            tree.parse_operators().unwrap();
660            tree.parse_node().unwrap();
661            tree.compile().unwrap();
662        });
663    }
664
665    #[bench]
666    fn bench_exec(b: &mut test::Bencher) {
667        let expr = Expr::new("(2 + (3 + 4) + (6 + (6 + 7)) + 5)")
668            .compile()
669            .unwrap();
670        b.iter(|| expr.exec().unwrap())
671    }
672
673    #[bench]
674    fn bench_eval(b: &mut test::Bencher) {
675        b.iter(|| eval("(2 + (3 + 4) + (6 + (6 + 7)) + 5)"));
676    }
677}