From b8c82a9126d39ad4ccd8078b3d5735b46e09768c Mon Sep 17 00:00:00 2001 From: freestrings Date: Sun, 22 Mar 2020 23:22:53 +0900 Subject: [PATCH] =?UTF-8?q?walk=EB=A5=98=20=ED=95=A8=EC=88=98=EB=A5=BC=20?= =?UTF-8?q?=20ValueWalker=EB=A1=9C=20=EC=98=AE=EA=B9=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/select/mod.rs | 103 ++++++------------------------------- src/select/value_walker.rs | 80 ++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 88 deletions(-) create mode 100644 src/select/value_walker.rs diff --git a/src/select/mod.rs b/src/select/mod.rs index ad45744..7cd576a 100644 --- a/src/select/mod.rs +++ b/src/select/mod.rs @@ -1,3 +1,5 @@ +mod value_walker; + use std::collections::HashSet; use std::fmt; @@ -6,6 +8,7 @@ use serde_json::{Number, Value}; use serde_json::map::Entry; use parser::*; +use self::value_walker::ValueWalker; fn to_f64(n: &Number) -> f64 { if n.is_i64() { @@ -17,6 +20,14 @@ fn to_f64(n: &Number) -> f64 { } } +fn abs_index(n: isize, len: usize) -> usize { + if n < 0_isize { + (n + len as isize).max(0) as usize + } else { + n.min(len as isize) as usize + } +} + trait Cmp { fn cmp_bool(&self, v1: bool, v2: bool) -> bool; @@ -390,89 +401,6 @@ impl<'a> Into> for &Vec<&'a Value> { } } -fn walk_all_with_num<'a>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, index: f64) { - walk(vec, tmp, &|v| if v.is_array() { - if let Some(item) = v.get(index as usize) { - Some(vec![item]) - } else { - None - } - } else { - None - }); -} - -fn walk_all_with_str<'a>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) { - if is_filter { - walk(vec, tmp, &|v| match v { - Value::Object(map) if map.contains_key(key) => Some(vec![v]), - _ => None, - }); - } else { - walk(vec, tmp, &|v| match v { - Value::Object(map) => match map.get(key) { - Some(v) => Some(vec![v]), - _ => None, - }, - _ => None, - }); - } -} - -fn walk_all<'a>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>) { - walk(vec, tmp, &|v| match v { - Value::Array(vec) => Some(vec.iter().collect()), - Value::Object(map) => { - let mut tmp = Vec::new(); - for (_, v) in map { - tmp.push(v); - } - Some(tmp) - } - _ => None, - }); -} - -fn walk<'a, F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F) - where - F: Fn(&Value) -> Option>, -{ - fn _walk<'a, F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) - where - F: Fn(&Value) -> Option>, - { - if let Some(mut ret) = fun(v) { - tmp.append(&mut ret); - } - - match v { - Value::Array(vec) => { - for v in vec { - _walk(v, tmp, fun); - } - } - Value::Object(map) => { - for (_, v) in map { - _walk(&v, tmp, fun); - } - } - _ => {} - } - } - - for v in vec { - _walk(v, tmp, fun); - } -} - -fn abs_index(n: isize, len: usize) -> usize { - if n < 0_isize { - (n + len as isize).max(0) as usize - } else { - n.min(len as isize) as usize - } -} - #[derive(Debug, PartialEq)] enum FilterKey { String(String), @@ -670,7 +598,7 @@ impl<'a, 'b> Selector<'a, 'b> { fn all_in_filter_with_str(&mut self, key: &str) { self.in_filter(|vec, tmp, _| { - walk_all_with_str(&vec, tmp, key, true); + ValueWalker::all_with_str(&vec, tmp, key, true); FilterKey::All }); @@ -830,7 +758,7 @@ impl<'a, 'b> Selector<'a, 'b> { fn all_from_current(&mut self) { if let Some(current) = self.current.take() { let mut tmp = Vec::new(); - walk_all(¤t, &mut tmp); + ValueWalker::all(¤t, &mut tmp); self.current = Some(tmp); } debug!("all_from_current: {:?}", self.current); @@ -839,7 +767,7 @@ impl<'a, 'b> Selector<'a, 'b> { fn all_from_current_with_str(&mut self, key: &str) { if let Some(current) = self.current.take() { let mut tmp = Vec::new(); - walk_all_with_str(¤t, &mut tmp, key, false); + ValueWalker::all_with_str(¤t, &mut tmp, key, false); self.current = Some(tmp); } debug!("all_from_current_with_str: {}, {:?}", key, self.current); @@ -848,8 +776,7 @@ impl<'a, 'b> Selector<'a, 'b> { fn all_from_current_with_num(&mut self, index: f64) { if let Some(current) = self.current.take() { let mut tmp = Vec::new(); - - walk_all_with_num(¤t, &mut tmp, index); + ValueWalker::all_with_num(¤t, &mut tmp, index); self.current = Some(tmp); } debug!("all_from_current_with_num: {}, {:?}", index, self.current); diff --git a/src/select/value_walker.rs b/src/select/value_walker.rs new file mode 100644 index 0000000..34779b6 --- /dev/null +++ b/src/select/value_walker.rs @@ -0,0 +1,80 @@ +use serde_json::Value; + +pub(super) struct ValueWalker; + +impl<'a> ValueWalker { + pub fn all_with_num(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, index: f64) { + Self::walk(vec, tmp, &|v| if v.is_array() { + if let Some(item) = v.get(index as usize) { + Some(vec![item]) + } else { + None + } + } else { + None + }); + } + + pub fn all_with_str(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) { + if is_filter { + Self::walk(vec, tmp, &|v| match v { + Value::Object(map) if map.contains_key(key) => Some(vec![v]), + _ => None, + }); + } else { + Self::walk(vec, tmp, &|v| match v { + Value::Object(map) => match map.get(key) { + Some(v) => Some(vec![v]), + _ => None, + }, + _ => None, + }); + } + } + + pub fn all(vec: &[&'a Value], tmp: &mut Vec<&'a Value>) { + Self::walk(vec, tmp, &|v| match v { + Value::Array(vec) => Some(vec.iter().collect()), + Value::Object(map) => { + let mut tmp = Vec::new(); + for (_, v) in map { + tmp.push(v); + } + Some(tmp) + } + _ => None, + }); + } + + fn walk(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F) + where + F: Fn(&Value) -> Option>, + { + for v in vec { + Self::_walk(v, tmp, fun); + } + } + + fn _walk(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) + where + F: Fn(&Value) -> Option>, + { + if let Some(mut ret) = fun(v) { + tmp.append(&mut ret); + } + + match v { + Value::Array(vec) => { + for v in vec { + Self::_walk(v, tmp, fun); + } + } + Value::Object(map) => { + for (_, v) in map { + Self::_walk(&v, tmp, fun); + } + } + _ => {} + } + } +}