use crate::jsonpath::ast::function::argument::{
NodesTypeArgument, RegexValueTypeArgument, ValueTypeArgument,
};
use crate::jsonpath::ast::function::{NodesType, ValueType};
use regex::Regex;
use serde_json::Value;
impl ValueTypeArgument {
pub fn eval(
&self,
current_value: &serde_json::Value,
root_value: &serde_json::Value,
) -> ValueType {
match self {
ValueTypeArgument::SingularQuery(filter_query) => {
filter_query.eval(current_value, root_value)
}
ValueTypeArgument::Function(value_type_function) => {
value_type_function.eval(current_value, root_value)
}
ValueTypeArgument::Literal(value) => Some(value.eval()),
}
}
}
impl RegexValueTypeArgument {
pub fn eval(
&self,
current_value: &serde_json::Value,
root_value: &serde_json::Value,
) -> Option<Regex> {
match self {
RegexValueTypeArgument::SingularQuery(filter_query) => {
if let Some(serde_json::Value::String(s)) =
filter_query.eval(current_value, root_value)
{
Regex::new(&s).ok()
} else {
None
}
}
RegexValueTypeArgument::Function(value_type_function) => {
if let Some(Value::String(s)) = value_type_function.eval(current_value, root_value)
{
Regex::new(&s).ok()
} else {
None
}
}
RegexValueTypeArgument::Literal(value) => Some(value.clone()),
}
}
}
impl NodesTypeArgument {
pub fn eval(
&self,
current_value: &serde_json::Value,
root_value: &serde_json::Value,
) -> NodesType {
match self {
NodesTypeArgument::FilterQuery(query) => query.eval(current_value, root_value),
}
}
}
#[cfg(test)]
mod tests {
use crate::jsonpath::ast::literal::{Literal, Number};
use crate::jsonpath::ast::query::{Query, RelativeQuery};
use crate::jsonpath::ast::segment::{ChildSegment, Segment};
use crate::jsonpath::ast::selector::{NameSelector, Selector};
use crate::jsonpath::ast::singular_query::{
RelativeSingularQuery, SingularQuery, SingularQuerySegment,
};
use crate::jsonpath::eval::function::argument::{NodesTypeArgument, ValueTypeArgument};
use serde_json::json;
#[test]
fn test_value_type_argument() {
let argument = ValueTypeArgument::Literal(Literal::String("hello".to_string()));
assert_eq!(argument.eval(&json!({}), &json!({})), Some(json!("hello")));
let argument = ValueTypeArgument::Literal(Literal::Number(Number::Integer(1)));
assert_eq!(argument.eval(&json!({}), &json!({})), Some(json!(1)));
let argument = ValueTypeArgument::SingularQuery(SingularQuery::Relative(
RelativeSingularQuery::new(vec![SingularQuerySegment::Name(NameSelector::new(
"authors".to_string(),
))]),
));
assert_eq!(
argument.eval(&json!({"authors": ["a", "b", "c"]}), &json!({})),
Some(json!(["a", "b", "c"]))
);
}
#[test]
fn test_nodes_type_argument() {
let argument =
NodesTypeArgument::FilterQuery(Query::RelativeQuery(RelativeQuery::new(vec![
Segment::Child(ChildSegment::new(vec![Selector::Name(NameSelector::new(
"books".to_string(),
))])),
])));
assert_eq!(
argument.eval(&json!({"books": ["book1", "book2"]}), &json!({})),
vec![json!(["book1", "book2"])]
);
assert!(argument.eval(&json!({}), &json!({})).is_empty());
}
}