diff --git a/README.md b/README.md index 53b941d..5403297 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [](https://jetro.io) ![GitHub](https://img.shields.io/github/license/mitghi/jetro) -Jetro is a tool for transforming, querying and comparing data in JSON format. +Jetro is a tool with custom DSL for transforming, querying and comparing data in JSON format. ```rust let data = serde_json::json!({ @@ -34,6 +34,17 @@ let output: Option = values.from_index(0); # example +Jetro combines access path with functions which operate on those values matched within the pipeline. + +By convention, functions are denoted using # operator. Functions can be composed. + +- #pick('string' | expression, ...) [ as | as* 'binding_value' ] +- #all +- #sum +- #formats('format with placeholder {} {}', 'key_a', 'key_b') [ as | as* 'binding_value' ] +- #filter('target_key' (>, <, >=, <=, ==, ~=) (string, boolean, number)) + + ```json { "bar": { diff --git a/src/context.rs b/src/context.rs index 0b4a5a3..197ceb3 100644 --- a/src/context.rs +++ b/src/context.rs @@ -82,6 +82,7 @@ pub enum FilterOp { Lq, Gq, Eq, + NotEq, Almost, } @@ -111,6 +112,7 @@ impl FilterOp { "<" => Some(Self::Less), ">" => Some(Self::Gt), "~=" => Some(Self::Almost), + "!=" => Some(Self::NotEq), _ => None, } } @@ -304,6 +306,7 @@ macro_rules! do_comparision { FilterOp::Gt => $lhs > $rhs, FilterOp::Lq => $lhs <= $rhs, FilterOp::Gq => $lhs >= $rhs, + FilterOp::NotEq => $lhs != $rhs, FilterOp::Almost => $lhs.to_lowercase() == $rhs.to_lowercase(), _ => false, } @@ -316,6 +319,7 @@ macro_rules! do_comparision { FilterOp::Gt => $lhs > $rhs, FilterOp::Lq => $lhs <= $rhs, FilterOp::Gq => $lhs >= $rhs, + FilterOp::NotEq => $lhs != $rhs, FilterOp::Almost => { todo!("implement 'almost' operator"); } diff --git a/src/fmt.rs b/src/fmt.rs index 25856d2..cba22e8 100644 --- a/src/fmt.rs +++ b/src/fmt.rs @@ -1,4 +1,5 @@ //! Module containing string formater for built-in #format function. + use crate::context::FormatOp; use dynfmt::{Format, SimpleCurlyFormat}; use serde_json::Value; diff --git a/src/grammar.pest b/src/grammar.pest index 883a1fb..6973468 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -25,7 +25,8 @@ greater_equal = { ">=" } less_equal = { "<=" } equal = { "==" } almost = { "~=" } -cmp = { almost | greater_equal | less_equal | equal | greater | less } +not_euql = { "!=" } +cmp = { almost | not_euql | greater_equal | less_equal | equal | greater | less } true_bool = { "true" } false_bool = { "false" } truthy = { true_bool | false_bool } diff --git a/src/parser.rs b/src/parser.rs index 2d999db..0edb1d2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -722,4 +722,25 @@ mod test { ] ); } + + #[test] + fn filter_not_equal() { + let actions = parse(">/foo/#filter('some_key' != 10)").unwrap(); + assert_eq!( + actions, + vec![ + Filter::Root, + Filter::Child("foo".to_string()), + Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + operand: FilterLogicalOp::None, + left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: "some_key".to_string(), + op: FilterOp::NotEq, + right: FilterInnerRighthand::Number(10), + }))), + right: None, + }))) + ] + ); + } }