resolver/builtin/
mod.rs

1
2use crate::{Function, Functions, Value, to_value};
3use crate::math::Math;
4use crate::error::Error;
5
6
7pub struct BuiltIn {}
8
9impl BuiltIn {
10    pub fn new() -> Functions {
11        let mut functions = Functions::new();
12        functions.insert("min".to_owned(), create_min_fuction());
13        functions.insert("max".to_owned(), create_max_fuction());
14        functions.insert("len".to_owned(), create_len_fuction());
15        functions.insert("is_empty".to_owned(), create_is_empty_fuction());
16        functions.insert("array".to_owned(), create_array_function());
17        functions
18    }
19}
20
21#[derive(PartialEq)]
22enum Compare {
23    Min,
24    Max,
25}
26
27fn create_min_fuction() -> Function {
28    compare(Compare::Min)
29}
30
31fn create_max_fuction() -> Function {
32    compare(Compare::Max)
33}
34
35fn compare(compare: Compare) -> Function {
36    Function {
37        max_args: None,
38        min_args: Some(1),
39        compiled: Box::new(move |values| {
40            let mut prev: Result<Value, Error> = Err(Error::Custom("can't find min value."
41                .to_owned()));
42
43            for value in values {
44                match value {
45                    Value::Array(array) => {
46                        for value in array {
47                            if prev.is_ok() {
48                                if compare == Compare::Min {
49                                    if value.lt(prev.as_ref().unwrap())? == to_value(true) {
50                                        prev = Ok(value)
51                                    }
52                                } else if value.gt(prev.as_ref().unwrap())? == to_value(true) {
53                                    prev = Ok(value)
54                                }
55                            } else {
56                                prev = Ok(value);
57                            }
58                        }
59                    }
60                    _ => {
61                        if prev.is_ok() {
62                            if compare == Compare::Min {
63                                if value.lt(prev.as_ref().unwrap())? == to_value(true) {
64                                    prev = Ok(value)
65                                }
66                            } else if value.gt(prev.as_ref().unwrap())? == to_value(true) {
67                                prev = Ok(value)
68                            }
69                        } else {
70                            prev = Ok(value);
71                        }
72                    }
73                }
74            }
75            prev
76        }),
77    }
78}
79
80
81fn create_is_empty_fuction() -> Function {
82    Function {
83        max_args: Some(1),
84        min_args: Some(1),
85        compiled: Box::new(|values| match *values.first().unwrap() {
86            Value::String(ref string) => Ok(to_value(string.is_empty())),
87            Value::Array(ref array) => Ok(to_value(array.is_empty())),
88            Value::Object(ref object) => Ok(to_value(object.is_empty())),
89            Value::Null => Ok(to_value(true)),
90            _ => Ok(to_value(false)),
91        }),
92    }
93}
94
95fn create_len_fuction() -> Function {
96    Function {
97        max_args: Some(1),
98        min_args: Some(1),
99        compiled: Box::new(|values| {
100            let value = values.first().unwrap();
101            match *value {
102                Value::String(ref string) => Ok(to_value(string.len())),
103                Value::Array(ref array) => Ok(to_value(array.len())),
104                Value::Object(ref object) => Ok(to_value(object.len())),
105                Value::Null => Ok(to_value(0)),
106                _ => {
107                    Err(Error::Custom(format!("len() only accept string, array, object and \
108                                               null. But the given is: {:?}",
109                                              value)))
110                }
111            }
112        }),
113    }
114}
115
116fn create_array_function() -> Function {
117    Function::new(|values| Ok(to_value(values)))
118}