mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-03-16 15:30:50 +00:00
code coverage 90%
This commit is contained in:
parent
cab5177811
commit
8f01598e05
18
src/lib.rs
18
src/lib.rs
@ -412,13 +412,8 @@ pub fn select_as<T: serde::de::DeserializeOwned>(
|
||||
/// ```
|
||||
pub fn delete(value: Value, path: &str) -> Result<Value, JsonPathError> {
|
||||
let mut selector = SelectorMut::default();
|
||||
let ret = selector
|
||||
.str_path(path)?
|
||||
.value(value)
|
||||
.delete()?
|
||||
.take()
|
||||
.unwrap_or(Value::Null);
|
||||
Ok(ret)
|
||||
let value = selector.str_path(path)?.value(value).delete()?;
|
||||
Ok(value.take().unwrap_or(Value::Null))
|
||||
}
|
||||
|
||||
/// Select JSON properties using a jsonpath and transform the result and then replace it. via closure that implements `FnMut` you can transform the selected results.
|
||||
@ -468,11 +463,6 @@ where
|
||||
F: FnMut(&Value) -> Value,
|
||||
{
|
||||
let mut selector = SelectorMut::default();
|
||||
let ret = selector
|
||||
.str_path(path)?
|
||||
.value(value)
|
||||
.replace_with(fun)?
|
||||
.take()
|
||||
.unwrap_or(Value::Null);
|
||||
Ok(ret)
|
||||
let value = selector.str_path(path)?.value(value).replace_with(fun)?;
|
||||
Ok(value.take().unwrap_or(Value::Null))
|
||||
}
|
||||
|
@ -193,13 +193,14 @@ impl Parser {
|
||||
|
||||
fn boolean(tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||
debug!("#boolean");
|
||||
|
||||
fn validation_bool_value(v: &str) -> bool {
|
||||
let b = v.as_bytes();
|
||||
!b.is_empty() && (b[0] == b't' || b[0] == b'T' || b[0] == b'f' || b[0] == b'F')
|
||||
}
|
||||
|
||||
match tokenizer.next_token() {
|
||||
Ok(Token::Key(_, ref v))
|
||||
if {
|
||||
let b = v.as_bytes();
|
||||
!b.is_empty() && (b[0] == b't' || b[0] == b'T' || b[0] == b'f' || b[0] == b'F')
|
||||
} =>
|
||||
{
|
||||
Ok(Token::Key(_, ref v)) if validation_bool_value(v) => {
|
||||
Ok(Self::node(ParseToken::Bool(v.eq_ignore_ascii_case("true"))))
|
||||
}
|
||||
_ => Err(tokenizer.err_msg()),
|
||||
@ -229,10 +230,10 @@ impl Parser {
|
||||
debug!("#array_quote_value");
|
||||
match tokenizer.next_token() {
|
||||
Ok(Token::SingleQuoted(_, val)) | Ok(Token::DoubleQuoted(_, val)) => {
|
||||
if !tokenizer.peek_is(COMMA) {
|
||||
Ok(Self::node(ParseToken::Key(val)))
|
||||
} else {
|
||||
if tokenizer.peek_is(COMMA) {
|
||||
Self::array_keys(tokenizer, val)
|
||||
} else {
|
||||
Ok(Self::node(ParseToken::Key(val)))
|
||||
}
|
||||
}
|
||||
_ => Err(tokenizer.err_msg()),
|
||||
|
@ -94,6 +94,7 @@ impl Token {
|
||||
self.to_simple() == str_token
|
||||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
fn to_simple(&self) -> &'static str {
|
||||
match self {
|
||||
Token::Absolute(_) => ABSOLUTE,
|
||||
|
@ -157,8 +157,8 @@ impl Cmp for CmpAnd {
|
||||
v1 && v2
|
||||
}
|
||||
|
||||
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
|
||||
v1 > 0_f64 && v2 > 0_f64
|
||||
fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
|
||||
@ -177,8 +177,8 @@ impl Cmp for CmpOr {
|
||||
v1 || v2
|
||||
}
|
||||
|
||||
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
|
||||
v1 > 0_f64 || v2 > 0_f64
|
||||
fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
|
||||
@ -190,7 +190,7 @@ impl Cmp for CmpOr {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum ExprTerm<'a> {
|
||||
String(String),
|
||||
Number(Number),
|
||||
@ -434,7 +434,7 @@ fn abs_index(n: isize, len: usize) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum FilterKey {
|
||||
String(String),
|
||||
All,
|
||||
@ -482,28 +482,25 @@ impl<'a, 'b> Selector<'a, 'b> {
|
||||
|
||||
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
||||
debug!("path : {}", path);
|
||||
|
||||
if self.node_ref.is_some() {
|
||||
self.node_ref.take();
|
||||
}
|
||||
|
||||
self.node_ref.take();
|
||||
self.node = Some(Parser::compile(path).map_err(JsonPathError::Path)?);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn node_ref(&self) -> Option<&Node> {
|
||||
if let Some(node) = &self.node {
|
||||
Some(node)
|
||||
} else {
|
||||
None
|
||||
return Some(node);
|
||||
}
|
||||
|
||||
if let Some(node) = &self.node_ref {
|
||||
return Some(*node);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn compiled_path(&mut self, node: &'b Node) -> &mut Self {
|
||||
if self.node.is_some() {
|
||||
self.node.take();
|
||||
}
|
||||
|
||||
self.node.take();
|
||||
self.node_ref = Some(node);
|
||||
self
|
||||
}
|
||||
@ -1195,3 +1192,212 @@ impl SelectorMut {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod select_inner_tests {
|
||||
use serde_json::{Number, Value};
|
||||
|
||||
use select::{Cmp, CmpAnd, CmpEq, CmpGe, CmpGt, CmpLe, CmpLt, CmpNe, CmpOr, ExprTerm};
|
||||
|
||||
#[test]
|
||||
fn to_f64_i64() {
|
||||
let number = 0_i64;
|
||||
let v: Value = serde_json::from_str(&format!("{}", number)).unwrap();
|
||||
if let Value::Number(n) = v {
|
||||
assert_eq!((super::to_f64(&n) - number as f64).abs() == 0_f64, true);
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_f64_f64() {
|
||||
let number = 0.1_f64;
|
||||
let v: Value = serde_json::from_str(&format!("{}", number)).unwrap();
|
||||
if let Value::Number(n) = v {
|
||||
assert_eq!((super::to_f64(&n) - number).abs() == 0_f64, true);
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_f64_u64() {
|
||||
let number = u64::max_value();
|
||||
let v: Value = serde_json::from_str(&format!("{}", number)).unwrap();
|
||||
if let Value::Number(n) = v {
|
||||
assert_eq!((super::to_f64(&n) - number as f64).abs() == 0_f64, true);
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_eq() {
|
||||
let cmp_fn = CmpEq;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "1"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "2"), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_ne() {
|
||||
let cmp_fn = CmpNe;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "1"), false);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "2"), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_gt() {
|
||||
let cmp_fn = CmpGt;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
|
||||
assert_eq!(cmp_fn.cmp_string("a", "a"), false);
|
||||
assert_eq!(cmp_fn.cmp_string("b", "a"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "2"), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_ge() {
|
||||
let cmp_fn = CmpGe;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "1"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("ab", "a"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "2"), false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_lt() {
|
||||
let cmp_fn = CmpLt;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, true), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, false), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
|
||||
assert_eq!(cmp_fn.cmp_string("a", "a"), false);
|
||||
assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "2"), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_le() {
|
||||
let cmp_fn = CmpLe;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, true), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, false), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
|
||||
assert_eq!(cmp_fn.cmp_string("a", "a"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
|
||||
assert_eq!(cmp_fn.cmp_string("abd", "abc"), false);
|
||||
assert_eq!(cmp_fn.cmp_string("1", "2"), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_and() {
|
||||
let cmp_fn = CmpAnd;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, true), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, false), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
|
||||
assert_eq!(cmp_fn.cmp_string("a", "a"), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_or() {
|
||||
let cmp_fn = CmpOr;
|
||||
assert_eq!(cmp_fn.default(), false);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, false), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, true), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(true, true), true);
|
||||
assert_eq!(cmp_fn.cmp_bool(false, false), false);
|
||||
assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
|
||||
assert_eq!(cmp_fn.cmp_string("a", "a"), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmp_json() {
|
||||
let v1 = Value::Bool(true);
|
||||
let v2 = Value::String("1".to_string());
|
||||
let left = [&v1, &v2];
|
||||
let right = [&v1, &v2];
|
||||
let empty: Vec<&Value> = Vec::new();
|
||||
|
||||
assert_eq!(CmpEq.cmp_json(&left, &right), left.to_vec());
|
||||
assert_eq!(CmpNe.cmp_json(&left, &right), left.to_vec());
|
||||
assert_eq!(CmpGt.cmp_json(&left, &right), empty);
|
||||
assert_eq!(CmpGe.cmp_json(&left, &right), empty);
|
||||
assert_eq!(CmpLt.cmp_json(&left, &right), empty);
|
||||
assert_eq!(CmpLe.cmp_json(&left, &right), empty);
|
||||
assert_eq!(CmpAnd.cmp_json(&left, &right), left.to_vec());
|
||||
assert_eq!(CmpOr.cmp_json(&left, &right), left.to_vec());
|
||||
|
||||
assert_eq!(
|
||||
CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
|
||||
vec![&Value::Bool(true)]
|
||||
);
|
||||
assert_eq!(
|
||||
CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
|
||||
empty
|
||||
);
|
||||
assert_eq!(
|
||||
CmpNe.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
|
||||
empty
|
||||
);
|
||||
assert_eq!(
|
||||
CmpNe.cmp_json(&[&Value::Bool(false)], &[&Value::Bool(true)]),
|
||||
vec![&Value::Bool(false)]
|
||||
);
|
||||
assert_eq!(
|
||||
CmpAnd.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
|
||||
vec![&Value::Bool(true)]
|
||||
);
|
||||
assert_eq!(
|
||||
CmpOr.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
|
||||
vec![&Value::Bool(true), &Value::Bool(false)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn value_vec_into() {
|
||||
let v = Value::Bool(true);
|
||||
let vec = &vec![&v];
|
||||
let term: ExprTerm = vec.into();
|
||||
assert_eq!(term, ExprTerm::Bool(true));
|
||||
|
||||
let v = Value::String("a".to_string());
|
||||
let vec = &vec![&v];
|
||||
let term: ExprTerm = vec.into();
|
||||
assert_eq!(term, ExprTerm::String("a".to_string()));
|
||||
|
||||
let v = serde_json::from_str("1.0").unwrap();
|
||||
let vec = &vec![&v];
|
||||
let term: ExprTerm = vec.into();
|
||||
assert_eq!(term, ExprTerm::Number(Number::from_f64(1.0).unwrap()));
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ extern crate jsonpath_lib as jsonpath;
|
||||
extern crate serde_json;
|
||||
|
||||
use common::{read_json, setup};
|
||||
use jsonpath::{Selector, SelectorMut};
|
||||
use jsonpath::{Selector, SelectorMut, Parser};
|
||||
use serde_json::Value;
|
||||
|
||||
mod common;
|
||||
@ -53,3 +53,11 @@ fn selector_mut() {
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selector_node_ref() {
|
||||
let node = Parser::compile("$.*").unwrap();
|
||||
let mut selector = Selector::default();
|
||||
selector.compiled_path(&node);
|
||||
assert!(std::ptr::eq(selector.node_ref().unwrap(), &node));
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user