diff --git a/Cargo.toml b/Cargo.toml index c2a4bd6..740ae78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rs-jsonpath" -version = "1.0.0" +version = "0.1.0" authors = ["freestrings "] [dependencies] @@ -12,3 +12,11 @@ indexmap = "1.0.2" [dev-dependencies] bencher = "0.1.5" + +[lib] +name = "jsonpath" +path = "src/lib.rs" + +[[bin]] +name = "jsonpath" +path = "src/bin.rs" \ No newline at end of file diff --git a/benches/bench.rs b/benches/bench.rs index 606e165..69538e5 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,5 +1,5 @@ #![feature(test)] -extern crate rs_jsonpath; +extern crate jsonpath; extern crate serde_json; extern crate test; diff --git a/src/bin.rs b/src/bin.rs new file mode 100644 index 0000000..ea3850b --- /dev/null +++ b/src/bin.rs @@ -0,0 +1,2 @@ +fn main() { +} \ No newline at end of file diff --git a/src/jsonpath/json_filter/mod.rs b/src/jsonpath/json_filter/mod.rs index a45d964..b882466 100644 --- a/src/jsonpath/json_filter/mod.rs +++ b/src/jsonpath/json_filter/mod.rs @@ -1,9 +1,8 @@ mod cmp; mod term; -mod value_filter; +pub mod value_filter; mod value_wrapper; - #[cfg(test)] mod tests { extern crate env_logger; diff --git a/src/jsonpath/json_filter/value_filter.rs b/src/jsonpath/json_filter/value_filter.rs index fb8b64e..2f7ba03 100644 --- a/src/jsonpath/json_filter/value_filter.rs +++ b/src/jsonpath/json_filter/value_filter.rs @@ -260,6 +260,15 @@ impl JsonValueFilter { }) } + pub fn new_from_value(json: Value) -> result::Result { + Ok(JsonValueFilter { + json: Rc::new(Box::new(json)), + filter_stack: Vec::new(), + token_stack: Vec::new(), + term_stack: Vec::new(), + }) + } + fn is_peek_token_array(&self) -> bool { if let Some(ParseToken::Array) = self.token_stack.last() { true @@ -309,6 +318,13 @@ impl JsonValueFilter { } } + pub fn take_value(&mut self) -> Value { + match self.filter_stack.last_mut() { + Some(v) => v.vw.get_val_mut().take(), + _ => Value::Null + } + } + fn token_union(&mut self, indices: Vec) { self.token_stack.pop(); diff --git a/src/jsonpath/mod.rs b/src/jsonpath/mod.rs index 97d5fa0..7d8f948 100644 --- a/src/jsonpath/mod.rs +++ b/src/jsonpath/mod.rs @@ -1,4 +1,4 @@ mod path_reader; mod tokenizer; -mod parser; -mod json_filter; \ No newline at end of file +pub mod parser; +pub mod json_filter; \ No newline at end of file diff --git a/src/jsonpath/parser.rs b/src/jsonpath/parser.rs index 59a5cab..031a000 100644 --- a/src/jsonpath/parser.rs +++ b/src/jsonpath/parser.rs @@ -34,7 +34,7 @@ mod utils { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum ParseToken { // '$' Absolute, @@ -64,7 +64,7 @@ pub enum ParseToken { Eof, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum FilterToken { Equal, NotEqual, @@ -76,7 +76,7 @@ pub enum FilterToken { Or, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Node { left: Option>, right: Option>, @@ -92,6 +92,10 @@ impl<'a> Parser<'a> { Parser { tokenizer: PreloadedTokenizer::new(input) } } + pub fn compile(&mut self) -> Result { + Ok(self.json_path()?) + } + pub fn parse(&mut self, visitor: &mut V) -> Result<()> { let node = self.json_path()?; visitor.visit(node); diff --git a/src/lib.rs b/src/lib.rs index ff7b8c4..348441f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,4 +6,35 @@ extern crate serde; extern crate serde_json; extern crate core; extern crate indexmap; -pub mod jsonpath; \ No newline at end of file + +mod jsonpath; + +use jsonpath::parser::*; +use jsonpath::json_filter::value_filter::*; + +use std::result; +use serde_json::Value; + +type Result = result::Result; + +pub fn compile<'a>(path: &'a str) -> impl FnMut(Value) -> Result + 'a { + let mut parser = Parser::new(path); + let node = parser.compile(); + move |json| { + match &node { + Ok(n) => { + let mut jf = JsonValueFilter::new_from_value(json)?; + jf.visit(n.clone()); + Ok(jf.take_value()) + }, + Err(e) => Err(e.clone()) + } + } +} + +pub fn filter(json: Value, path: &str) -> Result { + let mut jf = JsonValueFilter::new_from_value(json)?; + let mut parser = Parser::new(path); + parser.parse(&mut jf)?; + Ok(jf.take_value()) +} \ No newline at end of file