Refacto passing reference rather than owned value

This commit is contained in:
Fabrice Reix 2023-04-24 08:49:12 +02:00
parent dc1306a77a
commit a68fa6f6ca
No known key found for this signature in database
GPG Key ID: BF5213154B2E7155
3 changed files with 48 additions and 48 deletions

View File

@ -23,12 +23,12 @@ use super::ast::*;
pub type JsonpathResult = Vec<serde_json::Value>;
impl Query {
pub fn eval(self, value: serde_json::Value) -> JsonpathResult {
let mut results = vec![value];
pub fn eval(self, value: &serde_json::Value) -> JsonpathResult {
let mut results = vec![value.clone()];
for selector in self.selectors {
results = results
.iter()
.flat_map(|value| selector.clone().eval(value.clone()))
.flat_map(|value| selector.clone().eval(value))
.collect();
}
results
@ -36,13 +36,13 @@ impl Query {
}
impl Selector {
pub fn eval(self, root: serde_json::Value) -> JsonpathResult {
pub fn eval(self, root: &serde_json::Value) -> JsonpathResult {
match self {
Selector::Wildcard | Selector::ArrayWildcard => {
let mut elements = vec![];
if let serde_json::Value::Array(values) = root {
for value in values {
elements.push(value);
elements.push(value.clone());
}
} else if let serde_json::Value::Object(key_values) = root {
for value in key_values.values() {
@ -101,14 +101,14 @@ impl Selector {
elements.push(elem.clone());
}
for value in obj.values() {
for element in Selector::RecursiveKey(key.clone()).eval(value.clone()) {
for element in Selector::RecursiveKey(key.clone()).eval(value) {
elements.push(element);
}
}
}
serde_json::Value::Array(values) => {
for value in values {
for element in Selector::RecursiveKey(key.clone()).eval(value.clone()) {
for element in Selector::RecursiveKey(key.clone()).eval(value) {
elements.push(element);
}
}
@ -123,7 +123,7 @@ impl Selector {
serde_json::Value::Object(map) => {
for elem in map.values() {
elements.push(elem.clone());
for element in Selector::RecursiveWildcard.eval(elem.clone()) {
for element in Selector::RecursiveWildcard.eval(elem) {
elements.push(element);
}
}
@ -131,7 +131,7 @@ impl Selector {
serde_json::Value::Array(values) => {
for elem in values {
elements.push(elem.clone());
for element in Selector::RecursiveWildcard.eval(elem.clone()) {
for element in Selector::RecursiveWildcard.eval(elem) {
elements.push(element);
}
}
@ -266,7 +266,7 @@ mod tests {
#[test]
pub fn test_query() {
assert_eq!(
Query { selectors: vec![] }.eval(json_root()),
Query { selectors: vec![] }.eval(&json_root()),
vec![json_root()]
);
@ -274,7 +274,7 @@ mod tests {
Query {
selectors: vec![Selector::NameChild("store".to_string())]
}
.eval(json_root()),
.eval(&json_root()),
vec![json_store()]
);
@ -287,7 +287,7 @@ mod tests {
],
};
assert_eq!(
query.eval(json_root()),
query.eval(&json_root()),
vec![json!("Sayings of the Century")]
);
@ -307,7 +307,7 @@ mod tests {
],
};
assert_eq!(
query.eval(json_root()),
query.eval(&json_root()),
vec![json!("Sayings of the Century"), json!("Moby Dick")]
);
@ -316,7 +316,7 @@ mod tests {
selectors: vec![Selector::RecursiveKey("author".to_string())],
};
assert_eq!(
query.eval(json_root()),
query.eval(&json_root()),
vec![
json!("Nigel Rees"),
json!("Evelyn Waugh"),
@ -335,7 +335,7 @@ mod tests {
],
};
assert_eq!(
query.eval(json_root()),
query.eval(&json_root()),
vec![
json!("Nigel Rees"),
json!("Evelyn Waugh"),
@ -348,11 +348,11 @@ mod tests {
#[test]
pub fn test_selector_array_index() {
assert_eq!(
Selector::ArrayIndex(vec![0]).eval(json_books()),
Selector::ArrayIndex(vec![0]).eval(&json_books()),
vec![json_first_book()]
);
assert_eq!(
Selector::ArrayIndex(vec![1, 2]).eval(json_books()),
Selector::ArrayIndex(vec![1, 2]).eval(&json_books()),
vec![json_second_book(), json_third_book()]
);
}
@ -360,7 +360,7 @@ mod tests {
#[test]
pub fn test_selector_array_wildcard() {
assert_eq!(
Selector::ArrayWildcard {}.eval(json_books()),
Selector::ArrayWildcard {}.eval(&json_books()),
vec![
json_first_book(),
json_second_book(),
@ -377,7 +377,7 @@ mod tests {
start: None,
end: Some(2),
})
.eval(json_books()),
.eval(&json_books()),
vec![json_first_book(), json_second_book(),]
);
}
@ -385,7 +385,7 @@ mod tests {
#[test]
pub fn test_recursive_key() {
assert_eq!(
Selector::RecursiveKey("author".to_string()).eval(json_root()),
Selector::RecursiveKey("author".to_string()).eval(&json_root()),
vec![
json!("Nigel Rees"),
json!("Evelyn Waugh"),
@ -400,7 +400,7 @@ mod tests {
pub fn test_array_index() {
let value = json!(["first", "second", "third", "forth", "fifth"]);
assert_eq!(
Selector::ArrayIndex(vec![2]).eval(value),
Selector::ArrayIndex(vec![2]).eval(&value),
vec![json!("third")]
);
}

View File

@ -163,7 +163,7 @@ fn test_bookstore_path() {
// the authors of all books in the store
let expr = jsonpath::parse("$.store.book[*].author").unwrap();
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![
json!("Nigel Rees"),
json!("Evelyn Waugh"),
@ -175,7 +175,7 @@ fn test_bookstore_path() {
// all authors
let expr = jsonpath::parse("$..author").unwrap();
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![
json!("Nigel Rees"),
json!("Evelyn Waugh"),
@ -190,7 +190,7 @@ fn test_bookstore_path() {
// But you expect that order stays the same
// that's why bicycle and boot are inverted
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![bicycle_value(), book_value(),]
);
@ -199,7 +199,7 @@ fn test_bookstore_path() {
// Attention, there is no ordering on object keys with serde_json
// But you expect that order stays the same
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![
json!(19.95),
json!(8.95),
@ -211,38 +211,38 @@ fn test_bookstore_path() {
// the third book
let expr = jsonpath::parse("$..book[2]").unwrap();
assert_eq!(expr.eval(bookstore_value()), vec![book2_value()]);
assert_eq!(expr.eval(&bookstore_value()), vec![book2_value()]);
// the last book in order
// The following expression is not supported
// (@.length-1)
// use python-like indexing instead
let expr = jsonpath::parse("$..book[-1:]").unwrap();
assert_eq!(expr.eval(bookstore_value()), vec![book3_value()]);
assert_eq!(expr.eval(&bookstore_value()), vec![book3_value()]);
// the first two books
let expr = jsonpath::parse("$..book[0,1]").unwrap();
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![book0_value(), book1_value()]
);
let expr = jsonpath::parse("$..book[:2]").unwrap();
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![book0_value(), book1_value()]
);
// filter all books with isbn number
let expr = jsonpath::parse("$..book[?(@.isbn)]").unwrap();
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![book2_value(), book3_value(),]
);
// filter all books cheapier than 10
let expr = jsonpath::parse("$..book[?(@.price<10)]").unwrap();
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![book0_value(), book2_value(),]
);
@ -251,7 +251,7 @@ fn test_bookstore_path() {
// Order is reproducible
// but does not keep same order of json input!
assert_eq!(
expr.eval(bookstore_value()),
expr.eval(&bookstore_value()),
vec![
store_value(),
bicycle_value(),
@ -290,22 +290,22 @@ fn test_bookstore_additional() {
// Find books more expensive than 100
let expr = jsonpath::parse("$.store.book[?(@.price>100)]").unwrap();
assert_eq!(expr.eval(bookstore_value()), no_result);
assert_eq!(expr.eval(&bookstore_value()), no_result);
// find all authors for reference book
let expr = jsonpath::parse("$..book[?(@.category=='reference')].author").unwrap();
assert_eq!(expr.eval(bookstore_value()), vec![json!("Nigel Rees")]);
assert_eq!(expr.eval(&bookstore_value()), vec![json!("Nigel Rees")]);
}
#[test]
fn test_array() {
let array = json!([0, 1, 2, 3]);
let expr = jsonpath::parse("$[2]").unwrap();
assert_eq!(expr.eval(array), vec![json!(2)]);
assert_eq!(expr.eval(&array), vec![json!(2)]);
let expr = jsonpath::parse("$[0].name").unwrap();
let array = json!([{"name": "Bob"},{"name": "Bill"}]);
assert_eq!(expr.eval(array), vec![json!("Bob")]);
assert_eq!(expr.eval(&array), vec![json!("Bob")]);
}
#[test]
@ -321,26 +321,26 @@ fn test_key_access() {
// Bracket notation
let expr = jsonpath::parse("$['-']").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("hyphen")]);
assert_eq!(expr.eval(&obj), vec![json!("hyphen")]);
let expr = jsonpath::parse("$['_']").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("underscore")]);
assert_eq!(expr.eval(&obj), vec![json!("underscore")]);
let expr = jsonpath::parse("$['*']").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("asterisk")]);
assert_eq!(expr.eval(&obj), vec![json!("asterisk")]);
let expr = jsonpath::parse("$['\\'']").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("single_quote")]);
assert_eq!(expr.eval(&obj), vec![json!("single_quote")]);
let expr = jsonpath::parse("$['\"']").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("double_quote")]);
assert_eq!(expr.eval(&obj), vec![json!("double_quote")]);
let expr = jsonpath::parse("$['✈']").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("plane")]);
assert_eq!(expr.eval(&obj), vec![json!("plane")]);
// Dot notation
let expr = jsonpath::parse("$._").unwrap();
assert_eq!(expr.eval(obj.clone()), vec![json!("underscore")]);
assert_eq!(expr.eval(&obj), vec![json!("underscore")]);
// Asterisk
// return all elements
@ -356,7 +356,7 @@ fn test_key_access() {
];
let expr = jsonpath::parse("$.*").unwrap();
let results = expr.eval(obj.clone());
let results = expr.eval(&obj);
let mut results = results
.iter()
.map(|e| e.as_str().unwrap())
@ -365,7 +365,7 @@ fn test_key_access() {
assert_eq!(results, values);
let expr = jsonpath::parse("$[*]").unwrap();
let results = expr.eval(obj);
let results = expr.eval(&obj);
let mut results = results
.iter()
.map(|e| e.as_str().unwrap())
@ -403,10 +403,10 @@ fn fruit_prices_value() -> serde_json::Value {
#[test]
fn test_filter_nested_object() {
let expr = jsonpath::parse("$.fruit[?(@.price.US==200)].name").unwrap();
assert_eq!(expr.eval(fruit_prices_value()), vec![json!("grape")]);
assert_eq!(expr.eval(&fruit_prices_value()), vec![json!("grape")]);
let expr = jsonpath::parse("$.fruit[?(@.pricex.US==200)].name").unwrap();
assert!(expr.eval(fruit_prices_value()).is_empty());
assert!(expr.eval(&fruit_prices_value()).is_empty());
}
#[test]

View File

@ -209,7 +209,7 @@ fn eval_query_jsonpath(
}
Ok(v) => v,
};
let results = jsonpath_query.eval(value);
let results = jsonpath_query.eval(&value);
if results.is_empty() {
Ok(None)
} else if results.len() == 1 {