allow null to compare
This commit is contained in:
parent
1b690b634c
commit
daf3f5bd4a
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@
|
|||||||
*-test
|
*-test
|
||||||
target/
|
target/
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
|
.vscode
|
||||||
|
142
src/lib.rs
142
src/lib.rs
@ -202,8 +202,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_min_brackets() {
|
fn test_min_brackets() {
|
||||||
assert_eq!(eval("(min(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
|
assert_eq!(
|
||||||
Ok(to_value(100)));
|
eval("(min(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
|
||||||
|
Ok(to_value(100))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -218,8 +220,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_max_brackets() {
|
fn test_max_brackets() {
|
||||||
assert_eq!(eval("(max(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
|
assert_eq!(
|
||||||
Ok(to_value(2500)));
|
eval("(max(30, 5, 245, 20) * 10 + (5 + 5) * 5)"),
|
||||||
|
Ok(to_value(2500))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -232,6 +236,12 @@ mod tests {
|
|||||||
assert_eq!(eval("len(array(2, 3, 4, 5, 6))"), Ok(to_value(5)));
|
assert_eq!(eval("len(array(2, 3, 4, 5, 6))"), Ok(to_value(5)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_null_and_number() {
|
||||||
|
assert_eq!(eval("hos != 0"), Ok(to_value(true)));
|
||||||
|
assert_eq!(eval("hos > 0"), Ok(to_value(false)));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_len_string() {
|
fn test_len_string() {
|
||||||
assert_eq!(eval("len('Hello world!')"), Ok(to_value(12)));
|
assert_eq!(eval("len('Hello world!')"), Ok(to_value(12)));
|
||||||
@ -243,10 +253,10 @@ mod tests {
|
|||||||
object.insert("field1", "value1");
|
object.insert("field1", "value1");
|
||||||
object.insert("field2", "value2");
|
object.insert("field2", "value2");
|
||||||
object.insert("field3", "value3");
|
object.insert("field3", "value3");
|
||||||
assert_eq!(Expr::new("len(object)")
|
assert_eq!(
|
||||||
.value("object", object)
|
Expr::new("len(object)").value("object", object).exec(),
|
||||||
.exec(),
|
Ok(to_value(3))
|
||||||
Ok(to_value(3)));
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -333,14 +343,18 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_single_and_double_quote() {
|
fn test_single_and_double_quote() {
|
||||||
assert_eq!(eval(r#"' """" ' + ' """" '"#),
|
assert_eq!(
|
||||||
Ok(to_value(r#" """" """" "#)));
|
eval(r#"' """" ' + ' """" '"#),
|
||||||
|
Ok(to_value(r#" """" """" "#))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_double_and_single_quote() {
|
fn test_double_and_single_quote() {
|
||||||
assert_eq!(eval(r#"" '''' " + " '''' ""#),
|
assert_eq!(
|
||||||
Ok(to_value(r#" '''' '''' "#)));
|
eval(r#"" '''' " + " '''' ""#),
|
||||||
|
Ok(to_value(r#" '''' '''' "#))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -432,10 +446,12 @@ mod tests {
|
|||||||
let mut object = HashMap::new();
|
let mut object = HashMap::new();
|
||||||
object.insert("foo", "Foo, hello world!");
|
object.insert("foo", "Foo, hello world!");
|
||||||
object.insert("bar", "Bar, hello world!");
|
object.insert("bar", "Bar, hello world!");
|
||||||
assert_eq!(Expr::new("object.foo == 'Foo, hello world!'")
|
assert_eq!(
|
||||||
|
Expr::new("object.foo == 'Foo, hello world!'")
|
||||||
.value("object", object)
|
.value("object", object)
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value(true)));
|
Ok(to_value(true))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -443,10 +459,12 @@ mod tests {
|
|||||||
let mut object = HashMap::new();
|
let mut object = HashMap::new();
|
||||||
object.insert("foo", "Foo, hello world!");
|
object.insert("foo", "Foo, hello world!");
|
||||||
object.insert("bar", "Bar, hello world!");
|
object.insert("bar", "Bar, hello world!");
|
||||||
assert_eq!(Expr::new("object['foo'] == 'Foo, hello world!'")
|
assert_eq!(
|
||||||
|
Expr::new("object['foo'] == 'Foo, hello world!'")
|
||||||
.value("object", object)
|
.value("object", object)
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value(true)));
|
Ok(to_value(true))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -454,11 +472,13 @@ mod tests {
|
|||||||
let mut object = HashMap::new();
|
let mut object = HashMap::new();
|
||||||
object.insert("foo", "Foo, hello world!");
|
object.insert("foo", "Foo, hello world!");
|
||||||
object.insert("bar", "Bar, hello world!");
|
object.insert("bar", "Bar, hello world!");
|
||||||
assert_eq!(Expr::new("object[foo] == 'Foo, hello world!'")
|
assert_eq!(
|
||||||
|
Expr::new("object[foo] == 'Foo, hello world!'")
|
||||||
.value("object", object)
|
.value("object", object)
|
||||||
.value("foo", "foo")
|
.value("foo", "foo")
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value(true)));
|
Ok(to_value(true))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -469,40 +489,54 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_array_access() {
|
fn test_array_access() {
|
||||||
let array = vec!["hello", "world", "!"];
|
let array = vec!["hello", "world", "!"];
|
||||||
assert_eq!(Expr::new("array[1-1] == 'hello' && array[1] == 'world' && array[2] == '!'")
|
assert_eq!(
|
||||||
.value("array", array)
|
Expr::new(
|
||||||
|
"array[1-1] == 'hello' && array[1] == 'world' && array[2] == '!'",
|
||||||
|
).value("array", array)
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value(true)));
|
Ok(to_value(true))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_builtin_is_empty() {
|
fn test_builtin_is_empty() {
|
||||||
assert_eq!(Expr::new("is_empty(array)")
|
assert_eq!(
|
||||||
|
Expr::new("is_empty(array)")
|
||||||
.value("array", Vec::<String>::new())
|
.value("array", Vec::<String>::new())
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value(true)));
|
Ok(to_value(true))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_builtin_min() {
|
fn test_builtin_min() {
|
||||||
assert_eq!(Expr::new("min(array)")
|
assert_eq!(
|
||||||
|
Expr::new("min(array)")
|
||||||
.value("array", vec![23, 34, 45, 2])
|
.value("array", vec![23, 34, 45, 2])
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value(2)));
|
Ok(to_value(2))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_custom_function() {
|
fn test_custom_function() {
|
||||||
assert_eq!(Expr::new("output()")
|
assert_eq!(
|
||||||
.function("output",
|
Expr::new("output()")
|
||||||
|_| Ok(to_value("This is custom function's output")))
|
.function(
|
||||||
|
"output",
|
||||||
|
|_| Ok(to_value("This is custom function's output")),
|
||||||
|
)
|
||||||
.exec(),
|
.exec(),
|
||||||
Ok(to_value("This is custom function's output")));
|
Ok(to_value("This is custom function's output"))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_start_with_non_value_operator() {
|
fn test_error_start_with_non_value_operator() {
|
||||||
let mut tree = Tree { raw: "+ + 5".to_owned(), ..Default::default() };
|
let mut tree = Tree {
|
||||||
|
raw: "+ + 5".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
tree.parse_operators().unwrap();
|
tree.parse_operators().unwrap();
|
||||||
@ -512,7 +546,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_duplicate_operator() {
|
fn test_error_duplicate_operator() {
|
||||||
let mut tree = Tree { raw: "5 + + 5".to_owned(), ..Default::default() };
|
let mut tree = Tree {
|
||||||
|
raw: "5 + + 5".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
tree.parse_operators().unwrap();
|
tree.parse_operators().unwrap();
|
||||||
@ -522,7 +559,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_duplicate_value() {
|
fn test_error_duplicate_value() {
|
||||||
let mut tree = Tree { raw: "2 + 6 5".to_owned(), ..Default::default() };
|
let mut tree = Tree {
|
||||||
|
raw: "2 + 6 5".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
tree.parse_operators().unwrap();
|
tree.parse_operators().unwrap();
|
||||||
@ -532,7 +572,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_unpaired_brackets() {
|
fn test_error_unpaired_brackets() {
|
||||||
let mut tree = Tree { raw: "(2 + 3)) * 5".to_owned(), ..Default::default() };
|
let mut tree = Tree {
|
||||||
|
raw: "(2 + 3)) * 5".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
|
|
||||||
@ -541,7 +584,10 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_error_comma() {
|
fn test_error_comma() {
|
||||||
let mut tree = Tree { raw: ", 2 + 5".to_owned(), ..Default::default() };
|
let mut tree = Tree {
|
||||||
|
raw: ", 2 + 5".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
tree.parse_operators().unwrap();
|
tree.parse_operators().unwrap();
|
||||||
@ -564,16 +610,20 @@ mod benches {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_parse_pos(b: &mut test::Bencher) {
|
fn bench_parse_pos(b: &mut test::Bencher) {
|
||||||
let mut tree =
|
let mut tree = Tree {
|
||||||
Tree { raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(), ..Default::default() };
|
raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
b.iter(|| tree.parse_pos().unwrap());
|
b.iter(|| tree.parse_pos().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_parse_operators(b: &mut test::Bencher) {
|
fn bench_parse_operators(b: &mut test::Bencher) {
|
||||||
let mut tree =
|
let mut tree = Tree {
|
||||||
Tree { raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(), ..Default::default() };
|
raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
b.iter(|| tree.parse_operators().unwrap());
|
b.iter(|| tree.parse_operators().unwrap());
|
||||||
@ -581,8 +631,10 @@ mod benches {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_parse_nodes(b: &mut test::Bencher) {
|
fn bench_parse_nodes(b: &mut test::Bencher) {
|
||||||
let mut tree =
|
let mut tree = Tree {
|
||||||
Tree { raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(), ..Default::default() };
|
raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
tree.parse_operators().unwrap();
|
tree.parse_operators().unwrap();
|
||||||
@ -592,8 +644,10 @@ mod benches {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_compile(b: &mut test::Bencher) {
|
fn bench_compile(b: &mut test::Bencher) {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let mut tree =
|
let mut tree = Tree {
|
||||||
Tree { raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(), ..Default::default() };
|
raw: "(2 + (3 + 4) + (6 + (6 + 7)) + 5)".to_owned(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
tree.parse_pos().unwrap();
|
tree.parse_pos().unwrap();
|
||||||
tree.parse_operators().unwrap();
|
tree.parse_operators().unwrap();
|
||||||
tree.parse_node().unwrap();
|
tree.parse_node().unwrap();
|
||||||
@ -603,7 +657,9 @@ mod benches {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_exec(b: &mut test::Bencher) {
|
fn bench_exec(b: &mut test::Bencher) {
|
||||||
let expr = Expr::new("(2 + (3 + 4) + (6 + (6 + 7)) + 5)").compile().unwrap();
|
let expr = Expr::new("(2 + (3 + 4) + (6 + (6 + 7)) + 5)")
|
||||||
|
.compile()
|
||||||
|
.unwrap();
|
||||||
b.iter(|| expr.exec().unwrap())
|
b.iter(|| expr.exec().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,6 +101,9 @@ impl Math for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gt(&self, value: &Value) -> Result<Value, Error> {
|
fn gt(&self, value: &Value) -> Result<Value, Error> {
|
||||||
|
if self.is_null() || value.is_null() {
|
||||||
|
return Ok(to_value(false));
|
||||||
|
}
|
||||||
if self.is_number() && value.is_number() {
|
if self.is_number() && value.is_number() {
|
||||||
Ok(to_value(self.get_f64() > value.get_f64()))
|
Ok(to_value(self.get_f64() > value.get_f64()))
|
||||||
} else {
|
} else {
|
||||||
@ -109,6 +112,9 @@ impl Math for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lt(&self, value: &Value) -> Result<Value, Error> {
|
fn lt(&self, value: &Value) -> Result<Value, Error> {
|
||||||
|
if self.is_null() || value.is_null() {
|
||||||
|
return Ok(to_value(false));
|
||||||
|
}
|
||||||
if self.is_number() && value.is_number() {
|
if self.is_number() && value.is_number() {
|
||||||
Ok(to_value(self.get_f64() < value.get_f64()))
|
Ok(to_value(self.get_f64() < value.get_f64()))
|
||||||
} else {
|
} else {
|
||||||
@ -117,6 +123,9 @@ impl Math for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ge(&self, value: &Value) -> Result<Value, Error> {
|
fn ge(&self, value: &Value) -> Result<Value, Error> {
|
||||||
|
if self.is_null() || value.is_null() {
|
||||||
|
return Ok(to_value(false));
|
||||||
|
}
|
||||||
if self.is_number() && value.is_number() {
|
if self.is_number() && value.is_number() {
|
||||||
Ok(to_value(self.get_f64() >= value.get_f64()))
|
Ok(to_value(self.get_f64() >= value.get_f64()))
|
||||||
} else {
|
} else {
|
||||||
@ -125,6 +134,9 @@ impl Math for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn le(&self, value: &Value) -> Result<Value, Error> {
|
fn le(&self, value: &Value) -> Result<Value, Error> {
|
||||||
|
if self.is_null() || value.is_null() {
|
||||||
|
return Ok(to_value(false));
|
||||||
|
}
|
||||||
if self.is_number() && value.is_number() {
|
if self.is_number() && value.is_number() {
|
||||||
Ok(to_value(self.get_f64() <= value.get_f64()))
|
Ok(to_value(self.get_f64() <= value.get_f64()))
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user