diff --git a/Cargo.lock b/Cargo.lock index bd59429..f6ed433 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "1.0.2" @@ -11,6 +26,33 @@ dependencies = [ "memchr", ] +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -20,6 +62,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + [[package]] name = "cfg-if" version = "1.0.0" @@ -45,6 +93,22 @@ dependencies = [ "typenum", ] +[[package]] +name = "dhat" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cd11d84628e233de0ce467de10b8633f4ddaecafadefc86e13b84b8739b827" +dependencies = [ + "backtrace", + "lazy_static", + "mintex", + "parking_lot", + "rustc-hash", + "serde", + "serde_json", + "thousands", +] + [[package]] name = "digest" version = "0.10.7" @@ -88,6 +152,12 @@ dependencies = [ "version_check", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + [[package]] name = "itoa" version = "1.0.8" @@ -96,8 +166,9 @@ checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "jetro" -version = "0.2.3" +version = "0.2.4" dependencies = [ + "dhat", "dynfmt", "pest", "pest_derive", @@ -117,18 +188,75 @@ version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mintex" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bec4598fddb13cc7b528819e697852653252b760f1228b7642679bf2ff2cd07" + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + [[package]] name = "pest" version = "2.7.0" @@ -191,6 +319,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.9.1" @@ -220,12 +357,30 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "ryu" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.171" @@ -268,6 +423,12 @@ dependencies = [ "digest", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "syn" version = "2.0.25" @@ -299,6 +460,12 @@ dependencies = [ "syn", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "typenum" version = "1.16.0" @@ -322,3 +489,60 @@ name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/Cargo.toml b/Cargo.toml index 72ef7c4..c651532 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,10 @@ pest = "2.7.0" pest_derive = "2.7.0" serde = { version = "1.0.171", features = ["derive"] } dynfmt = { version = "0.1.5", features = ["curly"] } +dhat = "0.3.3" + +[profile.release] +debug = 1 + +[features] +dhat-heap = [] # if you are doing heap profiling \ No newline at end of file diff --git a/src/context.rs b/src/context.rs index 0e26e95..af0f00a 100644 --- a/src/context.rs +++ b/src/context.rs @@ -11,7 +11,7 @@ use std::fmt; use std::rc::Rc; /// PathOutput is type of fully evaluated jetro expression. -type PathOutput = Rc>>>; +type PathOutput = Vec; /// Path represents the entry for parsing and /// evaluating a jetro path. @@ -207,8 +207,8 @@ pub enum FilterInner { // with No-Op opeator, therefore evaluates to left expression. pub struct FilterAST { pub operator: FilterLogicalOp, - pub left: Option>>, - pub right: Option>>, + pub left: Option, + pub right: Option>, } #[derive(Debug, PartialEq, Clone)] @@ -232,7 +232,7 @@ pub enum Filter { ArrayTo(usize), Slice(usize, usize), Filter(FilterInner), - MultiFilter(Rc>), + MultiFilter(FilterAST), GroupedChild(Vec), Function(Func), } @@ -244,7 +244,7 @@ pub enum Filter { /// more stack items. #[allow(dead_code)] struct StackItem<'a> { - value: Rc, + value: Value, filters: &'a [Filter], stack: Rc>>>, } @@ -252,10 +252,10 @@ struct StackItem<'a> { /// Context binds components required for traversing /// and evaluating a jetro expression. pub(crate) struct Context<'a> { - root: Rc, + root: Value, stack: Rc>>>, registry: Rc>, - pub results: Rc>>>, + pub results: Rc>>, step_results: Rc>>, } @@ -334,11 +334,11 @@ macro_rules! push_to_stack_or_produce { ($results:expr, $stack:expr, $tail:expr, $value:expr) => { let tlen = $tail.len(); if tlen == 0 { - $results.borrow_mut().push(Rc::new($value)); + $results.borrow_mut().push($value); } else { $stack .borrow_mut() - .push(StackItem::new(Rc::new($value), $tail, $stack.clone())); + .push(StackItem::new($value, $tail, $stack.clone())); } }; } @@ -348,11 +348,11 @@ macro_rules! push_to_stack_iter_or_produce { let tlen = $tail.len(); for (_k, v) in $obj { if tlen == 0 { - $results.borrow_mut().push(Rc::new(v.clone())); + $results.borrow_mut().push(v.clone()); } else { $stack .borrow_mut() - .push(StackItem::new(Rc::new(v.clone()), $tail, $stack.clone())); + .push(StackItem::new(v.clone(), $tail, $stack.clone())); } } }; @@ -362,10 +362,9 @@ macro_rules! match_value { ($target_object:expr, $target_map:expr, $target_key:expr, $some_path:expr) => {{ for item in Path::collect_with_filter($target_object.clone(), $some_path.as_slice()) .0 - .borrow() .iter() { - match &*item.clone() { + match item.clone() { Value::Object(ref target_object) => { for (k, v) in target_object { $target_map @@ -548,7 +547,7 @@ impl FilterAST { pub fn new(left: FilterInner) -> Self { Self { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(left))), + left: Some(left), right: None, } } @@ -557,28 +556,24 @@ impl FilterAST { self.operator = operator; } - pub fn link_right( - &mut self, - statement: FilterInner, - operator: FilterLogicalOp, - ) -> Rc> { + pub fn link_right(&mut self, statement: FilterInner, operator: FilterLogicalOp) -> Self { let mut rhs: Self = Self::new(statement); rhs.set_operator(operator); - let inner = Rc::new(RefCell::new(rhs)); + let inner = rhs; let output = inner.clone(); - self.right = Some(inner); + self.right = Some(Rc::new(inner)); output } pub fn eval(&self, value: &Value) -> bool { if self.operator == FilterLogicalOp::None && self.right.is_none() { - return self.left.clone().unwrap().borrow_mut().eval(&value); + return self.left.clone().unwrap().eval(&value); } - let lhs = self.left.clone().unwrap().borrow_mut().eval(&value); - let rhs = self.right.clone().unwrap().borrow_mut().eval(&value); + let lhs = self.left.clone().unwrap().eval(&value); + let rhs = self.right.clone().unwrap().eval(&value); match self.operator { FilterLogicalOp::And => return lhs && rhs, @@ -597,7 +592,7 @@ impl FilterAST { "Filter({:?}) {:?} {:?}", &self.left, &self.operator, - rhs.borrow().repr(), + rhs.repr(), ); } } @@ -641,7 +636,7 @@ impl Filter { } => { match_value!( if *reverse && ctx.is_some() { - ctx.unwrap().root.as_ref() + &ctx.unwrap().root } else { obj }, @@ -654,7 +649,7 @@ impl Filter { PickFilterInner::Subpath(ref some_subpath, reverse) => { match_value!( if *reverse && ctx.is_some() { - ctx.unwrap().root.as_ref() + &ctx.unwrap().root } else { obj }, @@ -722,7 +717,10 @@ impl Path { let mut ctx = Context::new(v, filters.as_slice()); match ctx.collect() { - Ok(_) => Ok(PathResult(ctx.results)), + Ok(_) => { + let x = ctx.results.take().to_owned(); + Ok(PathResult(x)) + } Err(err) => Err(err), } } @@ -732,13 +730,15 @@ impl Path { let mut ctx = Context::new(v, filters); let _ = ctx.collect(); - PathResult(ctx.results) + let x = ctx.results.take().to_owned(); + + PathResult(x) } } impl PathResult { pub fn from_index(&mut self, index: usize) -> Option { - let final_value: &Value = &*self.0.borrow_mut().remove(index); + let final_value: Value = self.0.remove(index); match serde_json::from_value(final_value.clone().take()) { Ok(result) => Some(result), @@ -749,7 +749,7 @@ impl PathResult { impl<'a> StackItem<'a> { pub fn new( - value: Rc, + value: Value, filters: &'a [Filter], stack: Rc>>>, ) -> Self { @@ -771,17 +771,16 @@ impl<'a> StackItem<'a> { impl<'a> Context<'a> { pub fn new(value: Value, filters: &'a [Filter]) -> Self { - let results: Rc>>> = Rc::new(RefCell::new(Vec::new())); + let results: Rc>> = Rc::new(RefCell::new(Vec::new())); let stack: Rc>>> = Rc::new(RefCell::new(Vec::new())); - let rv: Rc = Rc::new(value); let step_results: Rc>> = Rc::new(RefCell::new(Vec::new())); let registry: Rc> = crate::func::default_registry(); stack .borrow_mut() - .push(StackItem::new(rv.clone(), filters, Rc::clone(&stack))); + .push(StackItem::new(value.clone(), filters, Rc::clone(&stack))); Self { - root: rv.clone(), + root: value.clone(), stack, registry, results, @@ -809,7 +808,7 @@ impl<'a> Context<'a> { let values = self.results.to_owned(); self.results = Rc::new(RefCell::new(Vec::new())); for value in values.borrow().clone() { - match *value.as_ref() { + match value { Value::Array(ref inner_array) => { for v in inner_array { if v.is_boolean() { @@ -833,7 +832,7 @@ impl<'a> Context<'a> { let values = self.results.to_owned(); self.results = Rc::new(RefCell::new(Vec::new())); for value in values.borrow().clone() { - match *value.as_ref() { + match value { Value::Array(ref inner_array) => { for v in inner_array { if v.is_number() { @@ -842,7 +841,7 @@ impl<'a> Context<'a> { } } Value::Number(_) => { - sum.add(&*value.as_ref()); + sum.add(&value); } _ => {} } @@ -888,7 +887,7 @@ impl<'a> Context<'a> { }; } - (Filter::GroupedChild(ref vec), Some(tail)) => match *current.value { + (Filter::GroupedChild(ref vec), Some(tail)) => match ¤t.value { Value::Object(ref obj) => { let mut target: Option<&Value> = None; 'ML: for target_key in vec.iter() { @@ -918,14 +917,14 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::MultiFilter(ref ast), Some(tail)) => match *current.value { + (Filter::MultiFilter(ref ast), Some(tail)) => match ¤t.value { Value::Object(ref _obj) => { todo!("implement filter support for object"); } Value::Array(ref array) => { let mut results: Vec = vec![]; for value in array { - if ast.borrow_mut().eval(&value) { + if ast.eval(&value) { results.push(value.clone()); }; } @@ -942,7 +941,7 @@ impl<'a> Context<'a> { todo!("handle unmatched arm of experimental filter"); } }, - (Filter::Filter(ref cond), Some(tail)) => match *current.value { + (Filter::Filter(ref cond), Some(tail)) => match ¤t.value { Value::Object(ref _obj) => { todo!("implement filter support for object"); } @@ -967,7 +966,7 @@ impl<'a> Context<'a> { } }, - (Filter::ArrayIndex(ref index), Some(tail)) => match *current.value { + (Filter::ArrayIndex(ref index), Some(tail)) => match ¤t.value { Value::Array(ref array) => { if *index < array.len() { let new_value = array[*index].clone(); @@ -982,7 +981,7 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::Slice(ref from, ref to), Some(tail)) => match *current.value { + (Filter::Slice(ref from, ref to), Some(tail)) => match ¤t.value { Value::Array(ref array) => { if array.len() >= *to && *from < *to { let new_slice = Value::Array(array[*from..*to].to_vec()); @@ -997,7 +996,7 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::ArrayTo(ref index), Some(tail)) => match *current.value { + (Filter::ArrayTo(ref index), Some(tail)) => match ¤t.value { Value::Array(ref array) => { if array.len() >= *index { let new_array = Value::Array(array[..*index].to_vec()); @@ -1012,7 +1011,7 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::ArrayFrom(ref index), Some(tail)) => match *current.value { + (Filter::ArrayFrom(ref index), Some(tail)) => match ¤t.value { Value::Array(ref array) => { if array.len() >= *index { let new_array = Value::Array(array[*index..].to_vec()); @@ -1027,7 +1026,7 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::Pick(_), Some(tail)) => match *current.value { + (Filter::Pick(_), Some(tail)) => match ¤t.value { Value::Object(_) => { let new_map = current.filters[0] .pick(¤t.value, Some(&self)) @@ -1043,7 +1042,7 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::AnyChild, Some(tail)) => match *current.value { + (Filter::AnyChild, Some(tail)) => match ¤t.value { Value::Object(ref obj) => { push_to_stack_iter_or_produce!(self.results, self.stack, tail, obj); } @@ -1058,7 +1057,7 @@ impl<'a> Context<'a> { _ => {} }, - (Filter::Child(ref name), Some(tail)) => match *current.value { + (Filter::Child(ref name), Some(tail)) => match ¤t.value { Value::Object(ref obj) => match obj.into_iter().find(|(k, _)| *k == name) { Some((_, v)) => { push_to_stack_or_produce!( @@ -1082,7 +1081,7 @@ impl<'a> Context<'a> { }, (Filter::DescendantChild(ref entry), Some(tail)) => match entry { - FilterDescendant::Single(ref descendant) => match *current.value { + FilterDescendant::Single(ref descendant) => match ¤t.value { Value::Object(ref obj) => { for (k, v) in obj { let filters: &[Filter] = if k == descendant { @@ -1092,10 +1091,10 @@ impl<'a> Context<'a> { }; if filters.len() == 0 { - self.results.borrow_mut().push(Rc::new(v.clone())); + self.results.borrow_mut().push(v.clone()); } else { self.stack.borrow_mut().push(StackItem::new( - Rc::new(v.clone()), + v.clone(), filters, self.stack.clone(), )); @@ -1105,7 +1104,7 @@ impl<'a> Context<'a> { Value::Array(ref array) => { for v in array { self.stack.borrow_mut().push(StackItem::new( - Rc::new(v.clone()), + v.clone(), current.filters, self.stack.clone(), )); @@ -1114,7 +1113,7 @@ impl<'a> Context<'a> { _ => {} }, FilterDescendant::Pair(ref descendant, ref target_value) => { - match *current.value { + match ¤t.value { Value::Object(ref obj) => { let mut found_match = false; for (k, v) in obj { @@ -1140,7 +1139,7 @@ impl<'a> Context<'a> { .push(serde_json::Value::Object(obj.clone())); } self.stack.borrow_mut().push(StackItem::new( - Rc::new(v.clone()), + v.clone(), filters, self.stack.clone(), )); @@ -1149,7 +1148,7 @@ impl<'a> Context<'a> { Value::Array(ref array) => { for v in array { self.stack.borrow_mut().push(StackItem::new( - Rc::new(v.clone()), + v.clone(), current.filters, self.stack.clone(), )); @@ -1260,10 +1259,7 @@ mod test { let mut ctx = Context::new(v, &filters); let _ = ctx.collect(); - assert_eq!( - *ctx.results.borrow().clone(), - vec![Rc::new(Value::String("value".to_string()))] - ); + assert_eq!(ctx.results.take(), vec![Value::String("value".to_string())]); } #[test] @@ -1325,10 +1321,8 @@ mod test { .expect("unable to parse"); assert_eq!( - *values.0.borrow().clone(), - vec![Rc::new( - serde_json::json! {{"a": "object_a", "object": "final_value"}} - )] + values.0, + vec![serde_json::json! {{"a": "object_a", "object": "final_value"}}] ); } @@ -1357,10 +1351,8 @@ mod test { .expect("unable to parse"); assert_eq!( - *values.0.borrow().clone(), - vec![Rc::new( - serde_json::json! {{"descendant": "final_value", "foo": "object_a"}} - )] + values.0, + vec![serde_json::json! {{"descendant": "final_value", "foo": "object_a"}}] ); } @@ -1377,10 +1369,7 @@ mod test { let values = Path::collect(serde_json::from_str(&data).unwrap(), ">/values/[1]") .expect("unable to parse"); - assert_eq!( - *values.0.borrow().clone(), - vec![Rc::new(serde_json::json!(2))], - ); + assert_eq!(values.0, vec![serde_json::json!(2)],); } #[test] @@ -1390,11 +1379,8 @@ mod test { let values = Path::collect(data, ">/entry/('foo' | 'bar' | 'another')").expect("unable to parse"); - assert_eq!(values.0.borrow().len(), 1); - assert_eq!( - values.0.borrow()[0], - Rc::new(Value::String(String::from("word"))) - ); + assert_eq!(values.0.len(), 1); + assert_eq!(values.0[0], Value::String(String::from("word"))); } #[test] @@ -1412,12 +1398,12 @@ mod test { let values = Path::collect(data, ">/values/#filter('is_eligable' == true)") .expect("unable to parse"); - assert_eq!(values.0.borrow().len(), 1); + assert_eq!(values.0.len(), 1); assert_eq!( - values.0.borrow()[0], - Rc::new(Value::Array(vec![ + values.0[0], + Value::Array(vec![ serde_json::json!({"name": "foo", "is_eligable": true}) - ])) + ]) ); } @@ -1434,8 +1420,8 @@ mod test { let values = Path::collect(data, ">/..priority/#len"); assert_eq!(values.is_ok(), true); assert_eq!( - *values.unwrap().0.borrow(), - vec![Rc::new(Value::Number(serde_json::Number::from(2)))] + values.unwrap().0, + vec![Value::Number(serde_json::Number::from(2))] ); } @@ -1445,62 +1431,50 @@ mod test { let values = Path::collect(data, ">/entry/values/#filter('priority' == 2)"); assert_eq!(values.is_ok(), true); assert_eq!( - *values.unwrap().0.borrow(), - vec![Rc::new(Value::Array(vec![ + values.unwrap().0, + vec![Value::Array(vec![ serde_json::json!({"name": "steam", "priority": 2}) - ]))] + ])] ); } #[test] fn test_truth() { let data = serde_json::json!({"entry": {"values": [{"name": "gearbox", "priority": 10, "truth_a": true, "truth_b": false, "truth_c": false, "truth_d": true}, {"name": "steam", "priority": 2, "truth_a": false, "truth_b": true, "truth_c": false, "truth_d": true}]}}); - let tests: Vec<(String, Vec>)> = vec![ - ( - ">/..truth_a/#all".to_string(), - vec![Rc::new(Value::Bool(false))], - ), - ( - ">/..truth_b/#all".to_string(), - vec![Rc::new(Value::Bool(false))], - ), - ( - ">/..truth_c/#all".to_string(), - vec![Rc::new(Value::Bool(false))], - ), - ( - ">/..truth_d/#all".to_string(), - vec![Rc::new(Value::Bool(true))], - ), + let tests: Vec<(String, Vec)> = vec![ + (">/..truth_a/#all".to_string(), vec![Value::Bool(false)]), + (">/..truth_b/#all".to_string(), vec![Value::Bool(false)]), + (">/..truth_c/#all".to_string(), vec![Value::Bool(false)]), + (">/..truth_d/#all".to_string(), vec![Value::Bool(true)]), ]; for (path, expect) in tests.iter() { let values = Path::collect(data.clone(), path).unwrap(); - assert_eq!(*values.0.borrow(), *expect); + assert_eq!(values.0, *expect); } } #[test] fn test_float_filter_evaluation() { let data = serde_json::json!({"entry": {"values": [{"name": "gearbox", "some_float": 10.1112}, {"name": "steam", "some_float": 2.48}]}}); - let tests: Vec<(String, Vec>)> = vec![ + let tests: Vec<(String, Vec)> = vec![ ( ">/entry/values/#filter('some_float' >= 10.1112)".to_string(), - vec![Rc::new(Value::Array(vec![ + vec![Value::Array(vec![ serde_json::json!({"name": "gearbox", "some_float": 10.1112}), - ]))], + ])], ), ( ">/entry/values/#filter('some_float' == 2.48)".to_string(), - vec![Rc::new(Value::Array(vec![ + vec![Value::Array(vec![ serde_json::json!({"name": "steam", "some_float": 2.48}), - ]))], + ])], ), ]; for (path, expect) in tests.iter() { let values = Path::collect(data.clone(), path).unwrap(); - assert_eq!(*values.0.borrow(), *expect); + assert_eq!(values.0, *expect); } } @@ -1510,11 +1484,11 @@ mod test { serde_json::json!({"entry": {"values": [{"name": "gearbox"}, {"name": "steam"}]}}); let result = Path::collect(data, ">/entry/values/#reverse()").unwrap(); assert_eq!( - *result.0.borrow(), - vec![Rc::new(Value::Array(vec![ + result.0, + vec![Value::Array(vec![ serde_json::json!({"name": "steam"}), serde_json::json!({"name": "gearbox"}) - ]))] + ])] ); } @@ -1527,11 +1501,11 @@ mod test { ) .unwrap(); assert_eq!( - *result.0.borrow(), - vec![Rc::new(Value::Array(vec![ + result.0, + vec![Value::Array(vec![ serde_json::json!({"field": "field", "name": "tool", "release": 2000}), serde_json::json!({"field": "seal", "name": "pneuma", "release": 2100}) - ]))] + ])] ); } @@ -1541,11 +1515,11 @@ mod test { serde_json::json!({"entry": {"values": [{"name": "gearbox"}, {"name": "steam"}]}}); let result = Path::collect(data, ">/..values/#map(x: x.name)").unwrap(); assert_eq!( - *result.0.borrow(), - vec![Rc::new(Value::Array(vec![ + result.0, + vec![Value::Array(vec![ Value::String("gearbox".to_string()), Value::String("steam".to_string()), - ]))] + ])] ); } @@ -1554,11 +1528,11 @@ mod test { let data = serde_json::json!({"entry": {"values": [{"name": "gearbox"}, {"name": "gearbox", "test": "2000"}]}}); let result = Path::collect(data, ">/..('name'='gearbox')").unwrap(); assert_eq!( - *result.0.borrow(), - vec![Rc::new(Value::Array(vec![ + result.0, + vec![Value::Array(vec![ serde_json::json!({"name": "gearbox"}), serde_json::json!({"name": "gearbox", "test": "2000"}) - ]))] + ])] ); } } diff --git a/src/func.rs b/src/func.rs index d0e864a..1fbb341 100644 --- a/src/func.rs +++ b/src/func.rs @@ -277,18 +277,18 @@ impl MapFn { Value::Array(ref array) => { for item in array { let result = Path::collect_with_filter(item.clone(), &subpath); - if result.0.borrow().len() == 0 { + if result.0.len() == 0 { return Err(Error::FuncEval( "map statement do not evaluates to anything".to_owned(), )); } - let head = result.0.borrow()[0].clone(); - output.push((*head).clone()); + let head = result.0[0].clone(); + output.push(head.clone()); } } _ => {} }; - return Ok(output); + Ok(output) } } diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e1e9e71 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,18 @@ +#[cfg(feature = "dhat-heap")] +#[global_allocator] +static ALLOC: dhat::Alloc = dhat::Alloc; + +use jetro; + +fn tst() { + let v = serde_json::json!({"some": "value", "another": {"nested": [{"v": "test"}]}}); + let result = jetro::context::Path::collect(v, ">/..v"); +} + +fn main() { + #[cfg(feature = "dhat-heap")] + let _profiler = dhat::Profiler::new_heap(); + for i in 0..100 { + tst(); + } +} diff --git a/src/parser.rs b/src/parser.rs index 68875d1..24cd363 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -174,8 +174,8 @@ pub(crate) fn parse<'a>(input: &'a str) -> Result, pest::error::Erro Rule::filterFn => { let rule = token.into_inner().nth(1).unwrap().into_inner().into_iter(); - let mut fast_root: Option>> = None; - let mut current: Option>> = None; + let mut fast_root: Option = None; + let mut current: Option = None; for item in rule.into_iter() { let rule = item.as_rule(); @@ -246,22 +246,21 @@ pub(crate) fn parse<'a>(input: &'a str) -> Result, pest::error::Erro }; if fast_root.is_none() { - fast_root = Some(Rc::new(RefCell::new(FilterAST::new( + fast_root = Some(FilterAST::new( filter_inner.clone(), - )))); + )); current = fast_root.clone(); } else { - let node = current.clone().unwrap(); + let mut node = current.clone().unwrap(); let rhs = node - .borrow_mut() .link_right(filter_inner, FilterLogicalOp::None); current = Some(rhs); } } Rule::logical_cmp => { let op = FilterLogicalOp::get(elem.as_str()).unwrap(); - let node = current.clone().unwrap(); - node.borrow_mut().set_operator(op.clone()); + let mut node = current.clone().unwrap(); + node.set_operator(op.clone()); } _ => { todo!("implement unmatched arm"); @@ -614,15 +613,15 @@ mod test { vec![ Filter::Root, Filter::DescendantChild(FilterDescendant::Single("meows".to_string())), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "some".to_string(), op: FilterOp::Eq, right: FilterInnerRighthand::String("value".to_string()), - }))), + }), right: None, - }))) + }) ] ); } @@ -652,15 +651,15 @@ mod test { vec![ Filter::Root, Filter::Child("foo".to_string()), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "is_furry".to_string(), op: FilterOp::Eq, right: FilterInnerRighthand::Bool(true) - }))), + }), right: None, - }))) + }) ] ); } @@ -672,15 +671,15 @@ mod test { vec![ Filter::Root, Filter::Child("foo".to_string()), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "some_value".to_string(), op: FilterOp::Eq, right: FilterInnerRighthand::Number(1234), - }))), + }), right: None, - }))) + }) ], ); } @@ -693,15 +692,15 @@ mod test { vec![ Filter::Root, Filter::Child("foo".to_string()), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "some_value".to_string(), op: FilterOp::Eq, right: FilterInnerRighthand::Float(2.48), - }))), + }), right: None, - }))) + }) ], ); } @@ -738,20 +737,20 @@ mod test { current = root.clone(); let new_node = current.borrow_mut().link_right(rhs, FilterLogicalOp::None); - current = new_node; + current = Rc::new(RefCell::new(new_node)); current.borrow_mut().set_operator(FilterLogicalOp::Or); let new_node = current .borrow_mut() .link_right(standalone_lhs, FilterLogicalOp::None); - current = new_node; + current = Rc::new(RefCell::new(new_node)); _ = current; assert_eq!(root.borrow().operator, FilterLogicalOp::And); let lhs = &root.borrow().left.clone().unwrap().clone(); - match *lhs.borrow() { + match *lhs { FilterInner::Cond { left: _, ref op, @@ -767,12 +766,11 @@ mod test { .clone() .unwrap() .clone() - .borrow() .left .clone() .unwrap() .clone(); - match *rhs_lhs.borrow() { + match *rhs_lhs{ FilterInner::Cond { left: _, ref op, @@ -847,15 +845,15 @@ mod test { vec![ Filter::Root, Filter::Child("foo".to_string()), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "some_key".to_string(), op: FilterOp::Almost, right: FilterInnerRighthand::String("test".to_string()), - },))), + },), right: None - }))) + }) ] ); } @@ -868,15 +866,15 @@ mod test { vec![ Filter::Root, Filter::Child("foo".to_string()), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "some_key".to_string(), op: FilterOp::NotEq, right: FilterInnerRighthand::Number(10), - }))), + }), right: None, - }))) + }) ] ); } @@ -1016,15 +1014,15 @@ mod test { "recursive".to_string() )), Filter::Child("value".to_string()), - Filter::MultiFilter(Rc::new(RefCell::new(FilterAST { + Filter::MultiFilter(FilterAST { operator: FilterLogicalOp::None, - left: Some(Rc::new(RefCell::new(FilterInner::Cond { + left: Some(FilterInner::Cond { left: "some_key".to_string(), op: FilterOp::Gt, right: FilterInnerRighthand::Number(10), - }))), + }), right: None, - }))), + }), ], }, PickFilterInner::KeyedSubpath {