mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-04-25 01:12:17 +00:00
filter, collector 정리
This commit is contained in:
parent
7991bba51d
commit
c99879cfbb
@ -61,20 +61,295 @@ impl fmt::Display for JsonPathError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug)]
|
||||||
|
struct FilterTerms<'a>(Vec<Option<ExprTerm<'a>>>);
|
||||||
|
|
||||||
|
impl<'a> FilterTerms<'a> {
|
||||||
|
fn new_filter_context(&mut self) {
|
||||||
|
self.0.push(None);
|
||||||
|
debug!("new_filter_context: {:?}", self.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_term_empty(&self) -> bool {
|
||||||
|
self.0.is_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_term(&mut self, term: Option<ExprTerm<'a>>) {
|
||||||
|
self.0.push(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_term(&mut self) -> Option<Option<ExprTerm<'a>>> {
|
||||||
|
self.0.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_json_term<F: Fn(&Vec<&'a Value>, &mut Vec<&'a Value>, &mut HashSet<usize>) -> FilterKey>(
|
||||||
|
&mut self,
|
||||||
|
e: ExprTerm<'a>,
|
||||||
|
fun: F,
|
||||||
|
) {
|
||||||
|
debug!("filter_json_term: {:?}", e);
|
||||||
|
|
||||||
|
if let ExprTerm::Json(rel, fk, vec) = e {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
let mut not_matched = HashSet::new();
|
||||||
|
let filter_key = if let Some(FilterKey::String(key)) = fk {
|
||||||
|
let key_contained = &vec.iter().map(|v| match v {
|
||||||
|
Value::Object(map) if map.contains_key(&key) => map.get(&key).unwrap(),
|
||||||
|
_ => v,
|
||||||
|
}).collect();
|
||||||
|
fun(key_contained, &mut tmp, &mut not_matched)
|
||||||
|
} else {
|
||||||
|
fun(&vec, &mut tmp, &mut not_matched)
|
||||||
|
};
|
||||||
|
|
||||||
|
if rel.is_some() {
|
||||||
|
self.0.push(Some(ExprTerm::Json(rel, Some(filter_key), tmp)));
|
||||||
|
} else {
|
||||||
|
let filtered: Vec<&Value> = vec.iter().enumerate()
|
||||||
|
.filter(
|
||||||
|
|(idx, _)| !not_matched.contains(idx)
|
||||||
|
)
|
||||||
|
.map(|(_, v)| *v)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
self.0.push(Some(ExprTerm::Json(Some(filtered), Some(filter_key), tmp)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!("unexpected: ExprTerm: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_json_term<F: Fn(&Vec<&'a Value>, &mut Vec<&'a Value>, &mut HashSet<usize>) -> FilterKey>(
|
||||||
|
&mut self,
|
||||||
|
current: &Option<Vec<&'a Value>>,
|
||||||
|
fun: F,
|
||||||
|
) {
|
||||||
|
debug!("push_json_term: {:?}", ¤t);
|
||||||
|
|
||||||
|
if let Some(current) = ¤t {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
let mut not_matched = HashSet::new();
|
||||||
|
let filter_key = fun(current, &mut tmp, &mut not_matched);
|
||||||
|
self.0.push(Some(ExprTerm::Json(None, Some(filter_key), tmp)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter<F: Fn(&Vec<&'a Value>, &mut Vec<&'a Value>, &mut HashSet<usize>) -> FilterKey>(
|
||||||
|
&mut self,
|
||||||
|
current: &Option<Vec<&'a Value>>,
|
||||||
|
fun: F,
|
||||||
|
) {
|
||||||
|
if let Some(peek) = self.0.pop() {
|
||||||
|
if let Some(e) = peek {
|
||||||
|
self.filter_json_term(e, fun);
|
||||||
|
} else {
|
||||||
|
self.push_json_term(current, fun);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_all_with_str(&mut self, current: &Option<Vec<&'a Value>>, key: &str) {
|
||||||
|
self.filter(current, |vec, tmp, _| {
|
||||||
|
ValueWalker::all_with_str(&vec, tmp, key, true);
|
||||||
|
FilterKey::All
|
||||||
|
});
|
||||||
|
|
||||||
|
debug!("filter_all_with_str : {}, {:?}", key, self.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter_next_with_str(&mut self, current: &Option<Vec<&'a Value>>, key: &str) {
|
||||||
|
self.filter(current, |vec, tmp, not_matched| {
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
for (idx, v) in vec.iter().enumerate() {
|
||||||
|
match v {
|
||||||
|
Value::Object(map) => {
|
||||||
|
if map.contains_key(key) {
|
||||||
|
let ptr = *v as *const Value;
|
||||||
|
if !visited.contains(&ptr) {
|
||||||
|
visited.insert(ptr);
|
||||||
|
tmp.push(v)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
not_matched.insert(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(vec) => {
|
||||||
|
not_matched.insert(idx);
|
||||||
|
for v in vec {
|
||||||
|
ValueWalker::walk_dedup(v, tmp, key, &mut visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
not_matched.insert(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterKey::String(key.to_owned())
|
||||||
|
});
|
||||||
|
|
||||||
|
debug!("filter_next_with_str : {}, {:?}", key, self.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_next_with_num(&mut self, current: &Option<Vec<&'a Value>>, index: f64) -> Option<Vec<&'a Value>> {
|
||||||
|
fn _collect<'a>(tmp: &mut Vec<&'a Value>, vec: &'a [Value], index: f64) {
|
||||||
|
let index = abs_index(index as isize, vec.len());
|
||||||
|
if let Some(v) = vec.get(index) {
|
||||||
|
tmp.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(current) = current {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
for c in current {
|
||||||
|
match c {
|
||||||
|
Value::Object(map) => {
|
||||||
|
for k in map.keys() {
|
||||||
|
if let Some(Value::Array(vec)) = map.get(k) {
|
||||||
|
_collect(&mut tmp, vec, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(vec) => {
|
||||||
|
_collect(&mut tmp, vec, index);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tmp.is_empty() {
|
||||||
|
self.0.pop();
|
||||||
|
return Some(vec![&Value::Null]);
|
||||||
|
} else {
|
||||||
|
return Some(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"collect_next_with_num : {:?}, {:?}",
|
||||||
|
&index, ¤t
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_next_all(&mut self, current: &Option<Vec<&'a Value>>) -> Option<Vec<&'a Value>> {
|
||||||
|
if let Some(current) = current {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
for c in current {
|
||||||
|
match c {
|
||||||
|
Value::Object(map) => {
|
||||||
|
for (_, v) in map {
|
||||||
|
tmp.push(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(vec) => {
|
||||||
|
for v in vec {
|
||||||
|
tmp.push(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Some(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("collect_next_all : {:?}", ¤t);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_next_with_str(&mut self, current: &Option<Vec<&'a Value>>, keys: &[String]) -> Option<Vec<&'a Value>> {
|
||||||
|
if let Some(current) = current {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
for c in current {
|
||||||
|
if let Value::Object(map) = c {
|
||||||
|
for key in keys {
|
||||||
|
if let Some(v) = map.get(key) {
|
||||||
|
tmp.push(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tmp.is_empty() {
|
||||||
|
self.0.pop();
|
||||||
|
return Some(vec![&Value::Null]);
|
||||||
|
} else {
|
||||||
|
return Some(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"collect_next_with_str : {:?}, {:?}",
|
||||||
|
keys, ¤t
|
||||||
|
);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_all(&mut self, current: &Option<Vec<&'a Value>>) -> Option<Vec<&'a Value>> {
|
||||||
|
if let Some(current) = current {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
ValueWalker::all(¤t, &mut tmp);
|
||||||
|
return Some(tmp);
|
||||||
|
}
|
||||||
|
debug!("collect_all: {:?}", ¤t);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_all_with_str(&mut self, current: &Option<Vec<&'a Value>>, key: &str) -> Option<Vec<&'a Value>> {
|
||||||
|
if let Some(current) = current {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
ValueWalker::all_with_str(¤t, &mut tmp, key, false);
|
||||||
|
return Some(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("collect_all_with_str: {}, {:?}", key, ¤t);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_all_with_num(&mut self, current: &Option<Vec<&'a Value>>, index: f64) -> Option<Vec<&'a Value>> {
|
||||||
|
if let Some(current) = current {
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
ValueWalker::all_with_num(¤t, &mut tmp, index);
|
||||||
|
return Some(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("collect_all_with_num: {}, {:?}", index, ¤t);
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Selector<'a, 'b> {
|
pub struct Selector<'a, 'b> {
|
||||||
node: Option<Node>,
|
node: Option<Node>,
|
||||||
node_ref: Option<&'b Node>,
|
node_ref: Option<&'b Node>,
|
||||||
value: Option<&'a Value>,
|
value: Option<&'a Value>,
|
||||||
tokens: Vec<ParseToken>,
|
tokens: Vec<ParseToken>,
|
||||||
terms: Vec<Option<ExprTerm<'a>>>,
|
|
||||||
current: Option<Vec<&'a Value>>,
|
current: Option<Vec<&'a Value>>,
|
||||||
selectors: Vec<Selector<'a, 'b>>,
|
selectors: Vec<Selector<'a, 'b>>,
|
||||||
|
selector_filter: FilterTerms<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Selector<'a, 'b> {
|
impl<'a, 'b> Selector<'a, 'b> {
|
||||||
|
pub fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Selector::default()
|
Self {
|
||||||
|
node: None,
|
||||||
|
node_ref: None,
|
||||||
|
value: None,
|
||||||
|
tokens: Vec::new(),
|
||||||
|
current: None,
|
||||||
|
selectors: Vec::new(),
|
||||||
|
selector_filter: FilterTerms(Vec::new()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
pub fn str_path(&mut self, path: &str) -> Result<&mut Self, JsonPathError> {
|
||||||
@ -168,250 +443,6 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_filter_context(&mut self) {
|
|
||||||
self.terms.push(None);
|
|
||||||
debug!("new_filter_context: {:?}", self.terms);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_filter<F: Fn(&Vec<&'a Value>, &mut Vec<&'a Value>, &mut HashSet<usize>) -> FilterKey>(&mut self, fun: F) {
|
|
||||||
fn get_parent<'a>(prev: Option<Vec<&'a Value>>, current_value: &[&'a Value], not_matched: HashSet<usize>) -> Option<Vec<&'a Value>> {
|
|
||||||
if prev.is_some() {
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
let filtered: Vec<&Value> = current_value.iter().enumerate().filter(|(idx, _)| !not_matched.contains(idx))
|
|
||||||
.map(|(_, v)| *v)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
Some(filtered)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if let Some(peek) = self.terms.pop() {
|
|
||||||
match peek {
|
|
||||||
Some(v) => {
|
|
||||||
debug!("in_filter 1.: {:?}", v);
|
|
||||||
|
|
||||||
match v {
|
|
||||||
ExprTerm::Json(rel, fk, vec) => {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
let mut not_matched = HashSet::new();
|
|
||||||
let filter_key = if let Some(FilterKey::String(key)) = fk {
|
|
||||||
let key_contained = &vec.iter().map(|v| match v {
|
|
||||||
Value::Object(map) if map.contains_key(&key) => map.get(&key).unwrap(),
|
|
||||||
_ => v,
|
|
||||||
}).collect();
|
|
||||||
fun(key_contained, &mut tmp, &mut not_matched)
|
|
||||||
} else {
|
|
||||||
fun(&vec, &mut tmp, &mut not_matched)
|
|
||||||
};
|
|
||||||
|
|
||||||
let parent = get_parent(rel, &vec, not_matched);
|
|
||||||
self.terms.push(Some(ExprTerm::Json(parent, Some(filter_key), tmp)));
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
debug!("in_filter 2.: {:?}", &self.current);
|
|
||||||
|
|
||||||
if let Some(current) = &self.current {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
let mut not_matched = HashSet::new();
|
|
||||||
let filter_key = fun(current, &mut tmp, &mut not_matched);
|
|
||||||
self.terms.push(Some(ExprTerm::Json(None, Some(filter_key), tmp)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn all_in_filter_with_str(&mut self, key: &str) {
|
|
||||||
self.in_filter(|vec, tmp, _| {
|
|
||||||
ValueWalker::all_with_str(&vec, tmp, key, true);
|
|
||||||
FilterKey::All
|
|
||||||
});
|
|
||||||
|
|
||||||
debug!("all_in_filter_with_str : {}, {:?}", key, self.terms);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_in_filter_with_str(&mut self, key: &str) {
|
|
||||||
fn _collect<'a>(
|
|
||||||
v: &'a Value,
|
|
||||||
tmp: &mut Vec<&'a Value>,
|
|
||||||
key: &str,
|
|
||||||
visited: &mut HashSet<*const Value>,
|
|
||||||
not_matched: &mut HashSet<usize>,
|
|
||||||
) {
|
|
||||||
match v {
|
|
||||||
Value::Object(map) => {
|
|
||||||
if map.contains_key(key) {
|
|
||||||
let ptr = v as *const Value;
|
|
||||||
if !visited.contains(&ptr) {
|
|
||||||
visited.insert(ptr);
|
|
||||||
tmp.push(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Array(vec) => {
|
|
||||||
for v in vec {
|
|
||||||
_collect(v, tmp, key, visited, not_matched);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.in_filter(|vec, tmp, not_matched| {
|
|
||||||
let mut visited = HashSet::new();
|
|
||||||
for (idx, v) in vec.iter().enumerate() {
|
|
||||||
match v {
|
|
||||||
Value::Object(map) => {
|
|
||||||
if map.contains_key(key) {
|
|
||||||
let ptr = *v as *const Value;
|
|
||||||
if !visited.contains(&ptr) {
|
|
||||||
visited.insert(ptr);
|
|
||||||
tmp.push(v)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
not_matched.insert(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Array(vec) => {
|
|
||||||
not_matched.insert(idx);
|
|
||||||
for v in vec {
|
|
||||||
_collect(v, tmp, key, &mut visited, not_matched);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
not_matched.insert(idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FilterKey::String(key.to_owned())
|
|
||||||
});
|
|
||||||
|
|
||||||
debug!("next_in_filter_with_str : {}, {:?}", key, self.terms);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_from_current_with_num(&mut self, index: f64) {
|
|
||||||
fn _collect<'a>(tmp: &mut Vec<&'a Value>, vec: &'a [Value], index: f64) {
|
|
||||||
let index = abs_index(index as isize, vec.len());
|
|
||||||
if let Some(v) = vec.get(index) {
|
|
||||||
tmp.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(current) = self.current.take() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
for c in current {
|
|
||||||
match c {
|
|
||||||
Value::Object(map) => {
|
|
||||||
for k in map.keys() {
|
|
||||||
if let Some(Value::Array(vec)) = map.get(k) {
|
|
||||||
_collect(&mut tmp, vec, index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Array(vec) => {
|
|
||||||
_collect(&mut tmp, vec, index);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.is_empty() {
|
|
||||||
self.terms.pop();
|
|
||||||
self.current = Some(vec![&Value::Null]);
|
|
||||||
} else {
|
|
||||||
self.current = Some(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"next_from_current_with_num : {:?}, {:?}",
|
|
||||||
&index, self.current
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_all_from_current(&mut self) {
|
|
||||||
if let Some(current) = self.current.take() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
for c in current {
|
|
||||||
match c {
|
|
||||||
Value::Object(map) => {
|
|
||||||
for (_, v) in map {
|
|
||||||
tmp.push(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Array(vec) => {
|
|
||||||
for v in vec {
|
|
||||||
tmp.push(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.current = Some(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("next_all_from_current : {:?}", self.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_from_current_with_str(&mut self, keys: &[String]) {
|
|
||||||
if let Some(current) = self.current.take() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
for c in current {
|
|
||||||
if let Value::Object(map) = c {
|
|
||||||
for key in keys {
|
|
||||||
if let Some(v) = map.get(key) {
|
|
||||||
tmp.push(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp.is_empty() {
|
|
||||||
self.current = Some(vec![&Value::Null]);
|
|
||||||
} else {
|
|
||||||
self.current = Some(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!(
|
|
||||||
"next_from_current_with_str : {:?}, {:?}",
|
|
||||||
keys, self.current
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn all_from_current(&mut self) {
|
|
||||||
if let Some(current) = self.current.take() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
ValueWalker::all(¤t, &mut tmp);
|
|
||||||
self.current = Some(tmp);
|
|
||||||
}
|
|
||||||
debug!("all_from_current: {:?}", self.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn all_from_current_with_str(&mut self, key: &str) {
|
|
||||||
if let Some(current) = self.current.take() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
ValueWalker::all_with_str(¤t, &mut tmp, key, false);
|
|
||||||
self.current = Some(tmp);
|
|
||||||
}
|
|
||||||
debug!("all_from_current_with_str: {}, {:?}", key, self.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn all_from_current_with_num(&mut self, index: f64) {
|
|
||||||
if let Some(current) = self.current.take() {
|
|
||||||
let mut tmp = Vec::new();
|
|
||||||
ValueWalker::all_with_num(¤t, &mut tmp, index);
|
|
||||||
self.current = Some(tmp);
|
|
||||||
}
|
|
||||||
debug!("all_from_current_with_num: {}, {:?}", index, self.current);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_absolute_path_filter(&mut self, token: &ParseToken) -> bool {
|
fn compute_absolute_path_filter(&mut self, token: &ParseToken) -> bool {
|
||||||
if !self.selectors.is_empty() {
|
if !self.selectors.is_empty() {
|
||||||
match token {
|
match token {
|
||||||
@ -422,9 +453,9 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
let term = current.into();
|
let term = current.into();
|
||||||
|
|
||||||
if let Some(s) = self.selectors.last_mut() {
|
if let Some(s) = self.selectors.last_mut() {
|
||||||
s.terms.push(Some(term));
|
s.selector_filter.push_term(Some(term));
|
||||||
} else {
|
} else {
|
||||||
self.terms.push(Some(term));
|
self.selector_filter.push_term(Some(term));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
@ -466,47 +497,47 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
let array_token = self.tokens.pop();
|
let array_token = self.tokens.pop();
|
||||||
if let Some(ParseToken::Leaves) = self.tokens.last() {
|
if let Some(ParseToken::Leaves) = self.tokens.last() {
|
||||||
self.tokens.pop();
|
self.tokens.pop();
|
||||||
self.all_from_current();
|
self.current = self.selector_filter.collect_all(&self.current);
|
||||||
}
|
}
|
||||||
self.tokens.push(array_token.unwrap());
|
self.tokens.push(array_token.unwrap());
|
||||||
}
|
}
|
||||||
self.new_filter_context();
|
self.selector_filter.new_filter_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_array_eof(&mut self) {
|
fn visit_array_eof(&mut self) {
|
||||||
if self.is_last_before_token_match(ParseToken::Array) {
|
if self.is_last_before_token_match(ParseToken::Array) {
|
||||||
if let Some(Some(e)) = self.terms.pop() {
|
if let Some(Some(e)) = self.selector_filter.pop_term() {
|
||||||
if let ExprTerm::String(key) = e {
|
if let ExprTerm::String(key) = e {
|
||||||
self.next_in_filter_with_str(&key);
|
self.selector_filter.filter_next_with_str(&self.current, &key);
|
||||||
self.tokens.pop();
|
self.tokens.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.terms.push(Some(e));
|
self.selector_filter.push_term(Some(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_last_before_token_match(ParseToken::Leaves) {
|
if self.is_last_before_token_match(ParseToken::Leaves) {
|
||||||
self.tokens.pop();
|
self.tokens.pop();
|
||||||
self.tokens.pop();
|
self.tokens.pop();
|
||||||
if let Some(Some(e)) = self.terms.pop() {
|
if let Some(Some(e)) = self.selector_filter.pop_term() {
|
||||||
if let ExprTerm::Number(n) = &e {
|
if let ExprTerm::Number(n) = &e {
|
||||||
self.all_from_current_with_num(to_f64(n));
|
self.current = self.selector_filter.collect_all_with_num(&self.current, to_f64(n));
|
||||||
self.terms.pop();
|
self.selector_filter.pop_term();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.terms.push(Some(e));
|
self.selector_filter.push_term(Some(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(Some(e)) = self.terms.pop() {
|
if let Some(Some(e)) = self.selector_filter.pop_term() {
|
||||||
match e {
|
match e {
|
||||||
ExprTerm::Number(n) => {
|
ExprTerm::Number(n) => {
|
||||||
self.next_from_current_with_num(to_f64(&n));
|
self.current = self.selector_filter.collect_next_with_num(&self.current, to_f64(&n));
|
||||||
}
|
}
|
||||||
ExprTerm::String(key) => {
|
ExprTerm::String(key) => {
|
||||||
self.next_from_current_with_str(&[key]);
|
self.current = self.selector_filter.collect_next_with_str(&self.current, &[key]);
|
||||||
}
|
}
|
||||||
ExprTerm::Json(rel, _, v) => {
|
ExprTerm::Json(rel, _, v) => {
|
||||||
if v.is_empty() {
|
if v.is_empty() {
|
||||||
@ -543,38 +574,42 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
match self.tokens.last() {
|
match self.tokens.last() {
|
||||||
Some(ParseToken::Leaves) => {
|
Some(ParseToken::Leaves) => {
|
||||||
self.tokens.pop();
|
self.tokens.pop();
|
||||||
self.all_from_current();
|
self.current = self.selector_filter.collect_all(&self.current);
|
||||||
}
|
}
|
||||||
Some(ParseToken::In) => {
|
Some(ParseToken::In) => {
|
||||||
self.tokens.pop();
|
self.tokens.pop();
|
||||||
self.next_all_from_current();
|
self.current = self.selector_filter.collect_next_all(&self.current);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.next_all_from_current();
|
self.current = self.selector_filter.collect_next_all(&self.current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_key(&mut self, key: &str) {
|
fn visit_key(&mut self, key: &str) {
|
||||||
if let Some(ParseToken::Array) = self.tokens.last() {
|
if let Some(ParseToken::Array) = self.tokens.last() {
|
||||||
self.terms.push(Some(ExprTerm::String(key.to_string())));
|
self.selector_filter.push_term(Some(ExprTerm::String(key.to_string())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(t) = self.tokens.pop() {
|
if let Some(t) = self.tokens.pop() {
|
||||||
if self.terms.is_empty() {
|
if self.selector_filter.is_term_empty() {
|
||||||
match t {
|
match t {
|
||||||
ParseToken::Leaves => self.all_from_current_with_str(key),
|
ParseToken::Leaves => {
|
||||||
ParseToken::In => self.next_from_current_with_str(&[key.to_string()]),
|
self.current = self.selector_filter.collect_all_with_str(&self.current, key)
|
||||||
|
}
|
||||||
|
ParseToken::In => {
|
||||||
|
self.current = self.selector_filter.collect_next_with_str(&self.current, &[key.to_string()])
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match t {
|
match t {
|
||||||
ParseToken::Leaves => {
|
ParseToken::Leaves => {
|
||||||
self.all_in_filter_with_str(key);
|
self.selector_filter.filter_all_with_str(&self.current, key);
|
||||||
}
|
}
|
||||||
ParseToken::In => {
|
ParseToken::In => {
|
||||||
self.next_in_filter_with_str(key);
|
self.selector_filter.filter_next_with_str(&self.current, key);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -583,19 +618,19 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_keys(&mut self, keys: &[String]) {
|
fn visit_keys(&mut self, keys: &[String]) {
|
||||||
if !self.terms.is_empty() {
|
if !self.selector_filter.is_term_empty() {
|
||||||
unimplemented!("keys in filter");
|
unimplemented!("keys in filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ParseToken::Array) = self.tokens.pop() {
|
if let Some(ParseToken::Array) = self.tokens.pop() {
|
||||||
self.next_from_current_with_str(keys);
|
self.current = self.selector_filter.collect_next_with_str(&self.current, keys);
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_filter(&mut self, ft: &FilterToken) {
|
fn visit_filter(&mut self, ft: &FilterToken) {
|
||||||
let right = match self.terms.pop() {
|
let right = match self.selector_filter.pop_term() {
|
||||||
Some(Some(right)) => right,
|
Some(Some(right)) => right,
|
||||||
Some(None) => ExprTerm::Json(
|
Some(None) => ExprTerm::Json(
|
||||||
None,
|
None,
|
||||||
@ -608,7 +643,7 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
_ => panic!("empty term right"),
|
_ => panic!("empty term right"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let left = match self.terms.pop() {
|
let left = match self.selector_filter.pop_term() {
|
||||||
Some(Some(left)) => left,
|
Some(Some(left)) => left,
|
||||||
Some(None) => ExprTerm::Json(
|
Some(None) => ExprTerm::Json(
|
||||||
None,
|
None,
|
||||||
@ -634,12 +669,12 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(e) = ret {
|
if let Some(e) = ret {
|
||||||
self.terms.push(Some(e));
|
self.selector_filter.push_term(Some(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_range(&mut self, from: &Option<isize>, to: &Option<isize>, step: &Option<usize>) {
|
fn visit_range(&mut self, from: &Option<isize>, to: &Option<isize>, step: &Option<usize>) {
|
||||||
if !self.terms.is_empty() {
|
if !self.selector_filter.is_term_empty() {
|
||||||
unimplemented!("range syntax in filter");
|
unimplemented!("range syntax in filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,7 +713,7 @@ impl<'a, 'b> Selector<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_union(&mut self, indices: &[isize]) {
|
fn visit_union(&mut self, indices: &[isize]) {
|
||||||
if !self.terms.is_empty() {
|
if !self.selector_filter.is_term_empty() {
|
||||||
unimplemented!("union syntax in filter");
|
unimplemented!("union syntax in filter");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,13 +755,12 @@ impl<'a, 'b> NodeVisitor for Selector<'a, 'b> {
|
|||||||
ParseToken::ArrayEof => self.visit_array_eof(),
|
ParseToken::ArrayEof => self.visit_array_eof(),
|
||||||
ParseToken::All => self.visit_all(),
|
ParseToken::All => self.visit_all(),
|
||||||
ParseToken::Bool(b) => {
|
ParseToken::Bool(b) => {
|
||||||
self.terms.push(Some(ExprTerm::Bool(*b)));
|
self.selector_filter.push_term(Some(ExprTerm::Bool(*b)));
|
||||||
}
|
}
|
||||||
ParseToken::Key(key) => self.visit_key(key),
|
ParseToken::Key(key) => self.visit_key(key),
|
||||||
ParseToken::Keys(keys) => self.visit_keys(keys),
|
ParseToken::Keys(keys) => self.visit_keys(keys),
|
||||||
ParseToken::Number(v) => {
|
ParseToken::Number(v) => {
|
||||||
self.terms
|
self.selector_filter.push_term(Some(ExprTerm::Number(Number::from_f64(*v).unwrap())));
|
||||||
.push(Some(ExprTerm::Number(Number::from_f64(*v).unwrap())));
|
|
||||||
}
|
}
|
||||||
ParseToken::Filter(ref ft) => self.visit_filter(ft),
|
ParseToken::Filter(ref ft) => self.visit_filter(ft),
|
||||||
ParseToken::Range(from, to, step) => self.visit_range(from, to, step),
|
ParseToken::Range(from, to, step) => self.visit_range(from, to, step),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
pub(super) struct ValueWalker;
|
pub(super) struct ValueWalker;
|
||||||
|
|
||||||
@ -46,19 +47,13 @@ impl<'a> ValueWalker {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk<F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F)
|
fn walk<F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option<Vec<&Value>> {
|
||||||
where
|
|
||||||
F: Fn(&Value) -> Option<Vec<&Value>>,
|
|
||||||
{
|
|
||||||
for v in vec {
|
for v in vec {
|
||||||
Self::_walk(v, tmp, fun);
|
Self::_walk(v, tmp, fun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _walk<F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F)
|
fn _walk<F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option<Vec<&Value>> {
|
||||||
where
|
|
||||||
F: Fn(&Value) -> Option<Vec<&Value>>,
|
|
||||||
{
|
|
||||||
if let Some(mut ret) = fun(v) {
|
if let Some(mut ret) = fun(v) {
|
||||||
tmp.append(&mut ret);
|
tmp.append(&mut ret);
|
||||||
}
|
}
|
||||||
@ -77,5 +72,28 @@ impl<'a> ValueWalker {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn walk_dedup(v: &'a Value,
|
||||||
|
tmp: &mut Vec<&'a Value>,
|
||||||
|
key: &str,
|
||||||
|
visited: &mut HashSet<*const Value>, ) {
|
||||||
|
match v {
|
||||||
|
Value::Object(map) => {
|
||||||
|
if map.contains_key(key) {
|
||||||
|
let ptr = v as *const Value;
|
||||||
|
if !visited.contains(&ptr) {
|
||||||
|
visited.insert(ptr);
|
||||||
|
tmp.push(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Array(vec) => {
|
||||||
|
for v in vec {
|
||||||
|
Self::walk_dedup(v, tmp, key, visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user