use crate::jsonpath::ast::segment::{ChildSegment, DescendantSegment, Segment};
use crate::jsonpath::eval::NodeList;
impl Segment {
pub fn eval(
&self,
current_value: &serde_json::Value,
root_value: &serde_json::Value,
) -> NodeList {
match self {
Segment::Child(child_segment) => child_segment.eval(current_value, root_value),
Segment::Descendant(descendant_segment) => {
descendant_segment.eval(current_value, root_value)
}
}
}
}
impl ChildSegment {
pub fn eval(
&self,
current_value: &serde_json::Value,
root_value: &serde_json::Value,
) -> NodeList {
let mut results = vec![];
for selector in self.selectors() {
results.append(&mut selector.eval(current_value, root_value));
}
results
}
}
impl DescendantSegment {
pub fn eval(
&self,
current_value: &serde_json::Value,
root_value: &serde_json::Value,
) -> NodeList {
let mut nodes = vec![];
for descendent in &descendants(current_value) {
for selector in self.selectors() {
nodes.append(&mut selector.eval(descendent, root_value));
}
}
nodes
}
}
fn descendants(node: &serde_json::Value) -> NodeList {
let mut nodes = vec![node.clone()];
match node {
serde_json::Value::Object(map) => {
for (_, value) in map {
nodes.append(&mut descendants(value));
}
}
serde_json::Value::Array(values) => {
for value in values {
nodes.append(&mut descendants(value));
}
}
_ => {}
}
nodes
}
#[cfg(test)]
mod tests {
use super::*;
use crate::jsonpath::ast::selector::{IndexSelector, NameSelector, Selector, WildcardSelector};
#[allow(unused_imports)]
use serde_json::json;
#[test]
fn test_segment() {
let current_value = json!({"greeting": "Hello"});
let root_value = json!("unused");
assert_eq!(
Segment::Child(ChildSegment::new(vec![Selector::Name(NameSelector::new(
"greeting".to_string()
)),]))
.eval(¤t_value, &root_value),
vec![json!("Hello")]
);
}
#[test]
fn test_child_segment() {
let current_value = json!({"greeting": "Hello"});
let root_value = json!("unused");
assert_eq!(
ChildSegment::new(vec![Selector::Name(NameSelector::new(
"greeting".to_string()
)),])
.eval(¤t_value, &root_value),
vec![json!("Hello")]
);
}
#[test]
fn test_descendant_segment() {
let current_value = json!({
"o": {"j": 1, "k": 2},
"a": [5, 3, [{"j": 4}, {"k": 6}]]
});
let root_value = json!("unused");
assert_eq!(
DescendantSegment::new(vec![Selector::Name(NameSelector::new("j".to_string()))])
.eval(¤t_value, &root_value),
vec![json!(4), json!(1),]
);
assert_eq!(
DescendantSegment::new(vec![Selector::Index(IndexSelector::new(0))])
.eval(¤t_value, &root_value),
vec![json!(5), json!({"j": 4}),]
);
assert_eq!(
DescendantSegment::new(vec![Selector::Wildcard(WildcardSelector)])
.eval(¤t_value, &root_value),
vec![
json!([5, 3, [{"j": 4}, {"k": 6}]]),
json!({"j": 1, "k": 2}),
json!(5),
json!(3),
json!([{"j": 4}, {"k": 6}]),
json!({"j": 4}),
json!({"k": 6}),
json!(4),
json!(6),
json!(1),
json!(2),
]
);
}
#[test]
fn test_descendants() {
assert_eq!(descendants(&json!("Hello")), vec![json!("Hello")]);
assert_eq!(
descendants(&json!([1, 2, 3])),
vec![json!([1, 2, 3]), json!(1), json!(2), json!(3)]
);
assert_eq!(
descendants(&json!({"name": "Bob"})),
vec![json!({"name": "Bob"}), json!("Bob")]
);
}
}