use crate::jsonpath::ast::expr::{AndExpr, LogicalExpr, NotExpr, OrExpr, TestExpr, TestExprKind};
impl LogicalExpr {
pub fn eval(&self, current_value: &serde_json::Value, root_value: &serde_json::Value) -> bool {
match self {
LogicalExpr::Comparison(comparison_expr) => {
comparison_expr.eval(current_value, root_value)
}
LogicalExpr::Test(test_expr) => test_expr.eval(current_value, root_value),
LogicalExpr::And(and_expr) => and_expr.eval(current_value, root_value),
LogicalExpr::Or(or_expr) => or_expr.eval(current_value, root_value),
LogicalExpr::Not(not_expr) => not_expr.eval(current_value, root_value),
}
}
}
impl TestExpr {
pub fn eval(&self, current_value: &serde_json::Value, root_value: &serde_json::Value) -> bool {
let value = match self.kind() {
TestExprKind::FilterQuery(filter_query) => {
!filter_query.eval(current_value, root_value).is_empty()
}
TestExprKind::LogicalTypeFunction(logical_type_function) => {
logical_type_function.eval(current_value, root_value)
}
};
if self.not() { !value } else { value }
}
}
impl AndExpr {
pub fn eval(&self, current_value: &serde_json::Value, root_value: &serde_json::Value) -> bool {
for operand in self.operands() {
if !operand.eval(current_value, root_value) {
return false;
}
}
true
}
}
impl OrExpr {
pub fn eval(&self, current_value: &serde_json::Value, root_value: &serde_json::Value) -> bool {
for operand in self.operands() {
if operand.eval(current_value, root_value) {
return true;
}
}
false
}
}
impl NotExpr {
pub fn eval(&self, current_value: &serde_json::Value, root_value: &serde_json::Value) -> bool {
!self.expr().eval(current_value, root_value)
}
}
#[cfg(test)]
mod tests {
use crate::jsonpath::ast::comparison::{Comparable, ComparisonExpr, ComparisonOp};
use crate::jsonpath::ast::expr::{AndExpr, LogicalExpr, OrExpr, TestExpr, TestExprKind};
use crate::jsonpath::ast::literal::{Literal, Number};
use crate::jsonpath::ast::query::{AbsoluteQuery, Query, RelativeQuery};
use crate::jsonpath::ast::segment::{ChildSegment, Segment};
use crate::jsonpath::ast::selector::{NameSelector, Selector, WildcardSelector};
use crate::jsonpath::ast::singular_query::{RelativeSingularQuery, SingularQuery};
use serde_json::json;
#[test]
fn test_eval_test_expr() {
let test_expr = TestExpr::new(
false,
TestExprKind::FilterQuery(Query::RelativeQuery(RelativeQuery::new(vec![
Segment::Child(ChildSegment::new(vec![Selector::Name(NameSelector::new(
"b".to_string(),
))])),
]))),
);
assert!(test_expr.eval(&serde_json::json!({"b": "j"}), &serde_json::json!({})));
assert!(!test_expr.eval(&serde_json::json!(3), &serde_json::json!({})));
let test_expr = TestExpr::new(
false,
TestExprKind::FilterQuery(Query::AbsoluteQuery(AbsoluteQuery::new(vec![
Segment::Child(ChildSegment::new(vec![Selector::Wildcard(
WildcardSelector,
)])),
Segment::Child(ChildSegment::new(vec![Selector::Name(NameSelector::new(
"name".to_string(),
))])),
]))),
);
assert!(test_expr.eval(
&serde_json::json!({"name": "bob"}),
&serde_json::json!([1, {"name": "bob"}])
));
assert!(!test_expr.eval(
&serde_json::json!({"name": "bob"}),
&serde_json::json!([1, 2])
));
}
#[test]
fn test_eval_or_expr() {
let or_expr = LogicalExpr::Or(OrExpr::new(vec![
LogicalExpr::Comparison(ComparisonExpr::new(
Comparable::SingularQuery(SingularQuery::Relative(RelativeSingularQuery::new(
vec![],
))),
Comparable::Literal(Literal::Number(Number::Integer(2))),
ComparisonOp::Less,
)),
LogicalExpr::Comparison(ComparisonExpr::new(
Comparable::SingularQuery(SingularQuery::Relative(RelativeSingularQuery::new(
vec![],
))),
Comparable::Literal(Literal::Number(Number::Integer(4))),
ComparisonOp::Greater,
)),
]));
assert!(or_expr.eval(&json!(1), &json!([1, 2, 3, 4, 5, 6])));
assert!(!or_expr.eval(&json!(3), &json!([1, 2, 3, 4, 5, 6])));
}
#[test]
fn test_eval_and_expr() {
let and_expr = LogicalExpr::And(AndExpr::new(vec![
LogicalExpr::Comparison(ComparisonExpr::new(
Comparable::SingularQuery(SingularQuery::Relative(RelativeSingularQuery::new(
vec![],
))),
Comparable::Literal(Literal::Number(Number::Integer(1))),
ComparisonOp::Greater,
)),
LogicalExpr::Comparison(ComparisonExpr::new(
Comparable::SingularQuery(SingularQuery::Relative(RelativeSingularQuery::new(
vec![],
))),
Comparable::Literal(Literal::Number(Number::Integer(4))),
ComparisonOp::Less,
)),
]));
assert!(!and_expr.eval(&json!(1), &json!([1, 2, 3, 4, 5, 6])));
assert!(and_expr.eval(&json!(2), &json!([1, 2, 3, 4, 5, 6])));
}
}