serde_json::Value clone 제거

This commit is contained in:
freestrings
2019-03-11 17:35:15 +09:00
parent ba57ae0ea5
commit 1a3104c5db
30 changed files with 1333 additions and 672 deletions

View File

@ -23,7 +23,7 @@ mod tests {
fn new_value_filter(file: &str) -> ValueFilter {
let string = read_json(file);
let json: Value = serde_json::from_str(string.as_str()).unwrap();
ValueFilter::new(json, false, false)
ValueFilter::new(json.into(), false, false)
}
fn do_filter(path: &str, file: &str) -> JsonValueFilter {
@ -71,7 +71,7 @@ mod tests {
"Vincent Cannon",
"Gray Berry"
]);
assert_eq!(&friends, current.get_val());
assert_eq!(friends, current.get_val().into_value());
}
let mut jf = new_value_filter("./benches/data_obj.json");
{
@ -84,7 +84,7 @@ mod tests {
"Vincent Cannon",
"Gray Berry"
]);
assert_eq!(&names, current.get_val());
assert_eq!(names, current.get_val().into_value());
}
}
@ -98,32 +98,32 @@ mod tests {
]);
let jf = do_filter("$.school.friends[1, 2]", "./benches/data_obj.json");
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.school.friends[1:]", "./benches/data_obj.json");
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.school.friends[:-2]", "./benches/data_obj.json");
let friends = json!([
{"id": 0, "name": "Millicent Norman"}
]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$..friends[2].name", "./benches/data_obj.json");
let friends = json!(["Gray Berry", "Gray Berry"]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$..friends[*].name", "./benches/data_obj.json");
let friends = json!(["Vincent Cannon","Gray Berry","Millicent Norman","Vincent Cannon","Gray Berry"]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$['school']['friends'][*].['name']", "./benches/data_obj.json");
let friends = json!(["Millicent Norman","Vincent Cannon","Gray Berry"]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$['school']['friends'][0].['name']", "./benches/data_obj.json");
let friends = json!("Millicent Norman");
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
}
#[test]
@ -139,16 +139,16 @@ mod tests {
});
let jf = do_filter("$.school", "./benches/data_obj.json");
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.school[?(@.friends[0])]", "./benches/data_obj.json");
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.school[?(@.friends[10])]", "./benches/data_obj.json");
assert_eq!(&Value::Null, jf.current_value());
assert_eq!(Value::Null, jf.current_value().into_value());
let jf = do_filter("$.school[?(1==1)]", "./benches/data_obj.json");
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.school.friends[?(1==1)]", "./benches/data_obj.json");
let friends = json!([
@ -156,7 +156,7 @@ mod tests {
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
}
#[test]
@ -171,42 +171,42 @@ mod tests {
{"id": 2, "name": "Gray Berry"}
]
});
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.friends[?(@.name)]", "./benches/data_obj.json");
let friends = json!([
{ "id" : 1, "name" : "Vincent Cannon" },
{ "id" : 2, "name" : "Gray Berry" }
]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.friends[?(@.id >= 2)]", "./benches/data_obj.json");
let friends = json!([
{ "id" : 2, "name" : "Gray Berry" }
]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.friends[?(@.id >= 2 || @.id == 1)]", "./benches/data_obj.json");
let friends = json!([
{ "id" : 2, "name" : "Gray Berry" },
{ "id" : 1, "name" : "Vincent Cannon" }
]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json");
assert_eq!(&Value::Null, jf.current_value());
assert_eq!(Value::Null, jf.current_value().into_value());
let jf = do_filter("$..friends[?(@.id == $.index)].id", "./benches/data_obj.json");
let friends = json!([0, 0]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$..book[?($.store.bicycle.price < @.price)].price", "./benches/example.json");
let friends = json!([22.99]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
let jf = do_filter("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", "./benches/example.json");
let friends = json!([12.99]);
assert_eq!(&friends, jf.current_value());
assert_eq!(friends, jf.current_value().into_value());
}
#[test]
@ -215,10 +215,10 @@ mod tests {
let jf = do_filter("$.store.book[*].author", "./benches/example.json");
let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..author", "./benches/example.json");
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$.store.*", "./benches/example.json");
let ret = json!([
@ -230,11 +230,11 @@ mod tests {
],
{"color" : "red","price" : 19.95},
]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$.store..price", "./benches/example.json");
let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..book[2]", "./benches/example.json");
let ret = json!([{
@ -244,7 +244,7 @@ mod tests {
"isbn" : "0-553-21311-3",
"price" : 8.99
}]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..book[-2]", "./benches/example.json");
let ret = json!([{
@ -254,7 +254,7 @@ mod tests {
"isbn" : "0-553-21311-3",
"price" : 8.99
}]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..book[0,1]", "./benches/example.json");
let ret = json!([
@ -271,7 +271,7 @@ mod tests {
"price" : 12.99
}
]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..book[:2]", "./benches/example.json");
let ret = json!([
@ -288,7 +288,7 @@ mod tests {
"price" : 12.99
}
]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..book[2:]", "./benches/example.json");
let ret = json!([
@ -307,7 +307,7 @@ mod tests {
"price" : 22.99
}
]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..book[?(@.isbn)]", "./benches/example.json");
let ret = json!([
@ -326,7 +326,7 @@ mod tests {
"price" : 22.99
}
]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$.store.book[?(@.price < 10)]", "./benches/example.json");
let ret = json!([
@ -344,10 +344,10 @@ mod tests {
"price" : 8.99
}
]);
assert_eq!(&ret, jf.current_value());
assert_eq!(ret, jf.current_value().into_value());
let jf = do_filter("$..*", "./benches/example.json");
let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap();
assert_eq!(&json, jf.current_value());
assert_eq!(json, jf.current_value().into_value());
}
}

View File

@ -9,7 +9,7 @@ pub enum TermContext {
}
impl TermContext {
fn cmp<F: PrivCmp + IntoType>(&mut self, other: &mut TermContext, cmp_fn: F, default: bool) -> TermContext {
fn cmp<F: PrivCmp + IntoType>(&self, other: &TermContext, cmp_fn: F, default: bool) -> TermContext {
match self {
TermContext::Constants(et) => {
match other {
@ -51,7 +51,7 @@ impl TermContext {
}
}
fn cmp_cond(&mut self, other: &mut TermContext, cmp_cond_type: CmpCondType) -> TermContext {
fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType) -> TermContext {
match self {
TermContext::Constants(et) => {
match other {
@ -86,35 +86,35 @@ impl TermContext {
}
}
pub fn eq(&mut self, other: &mut TermContext) -> TermContext {
pub fn eq(&self, other: &TermContext) -> TermContext {
self.cmp(other, CmpEq, false)
}
pub fn ne(&mut self, other: &mut TermContext) -> TermContext {
pub fn ne(&self, other: &TermContext) -> TermContext {
self.cmp(other, CmpNe, true)
}
pub fn gt(&mut self, other: &mut TermContext) -> TermContext {
pub fn gt(&self, other: &TermContext) -> TermContext {
self.cmp(other, CmpGt, false)
}
pub fn ge(&mut self, other: &mut TermContext) -> TermContext {
pub fn ge(&self, other: &TermContext) -> TermContext {
self.cmp(other, CmpGe, false)
}
pub fn lt(&mut self, other: &mut TermContext) -> TermContext {
pub fn lt(&self, other: &TermContext) -> TermContext {
self.cmp(other, CmpLt, false)
}
pub fn le(&mut self, other: &mut TermContext) -> TermContext {
pub fn le(&self, other: &TermContext) -> TermContext {
self.cmp(other, CmpLe, false)
}
pub fn and(&mut self, other: &mut TermContext) -> TermContext {
pub fn and(&self, other: &TermContext) -> TermContext {
self.cmp_cond(other, CmpCondType::And)
}
pub fn or(&mut self, other: &mut TermContext) -> TermContext {
pub fn or(&self, other: &TermContext) -> TermContext {
self.cmp_cond(other, CmpCondType::Or)
}
}

View File

@ -1,29 +1,28 @@
use core::borrow::Borrow;
use std::error::Error;
use std::rc::Rc;
use std::result;
use ref_value::*;
use serde_json::Value;
use super::parser::*;
use super::term::*;
use super::value_wrapper::*;
trait ArrayIndex {
fn index(&self, v: &Value) -> usize;
fn index(&self, v: &RefValueWrapper) -> usize;
fn take_value(&self, v: &mut Value) -> Value {
fn take_value(&self, v: &RefValueWrapper) -> RefValueWrapper {
let idx = self.index(v);
match v.get_mut(idx) {
Some(v) => v.take(),
_ => Value::Null
match v.get(idx) {
Some(v) => v,
_ => RefValue::Null.into()
}
}
}
impl ArrayIndex for f64 {
fn index(&self, v: &Value) -> usize {
fn index(&self, v: &RefValueWrapper) -> usize {
if v.is_array() && self < &0_f64 {
(v.as_array().unwrap().len() as f64 + self) as usize
} else {
@ -33,7 +32,7 @@ impl ArrayIndex for f64 {
}
impl ArrayIndex for isize {
fn index(&self, v: &Value) -> usize {
fn index(&self, v: &RefValueWrapper) -> usize {
if v.is_array() && self < &0_isize {
(v.as_array().unwrap().len() as isize + self) as usize
} else {
@ -43,7 +42,7 @@ impl ArrayIndex for isize {
}
impl ArrayIndex for usize {
fn index(&self, _: &Value) -> usize {
fn index(&self, _: &RefValueWrapper) -> usize {
*self as usize
}
}
@ -63,54 +62,55 @@ pub struct ValueFilter {
}
impl ValueFilter {
pub fn new(v: Value, is_leaves: bool, filter_mode: bool) -> Self {
pub fn new(v: RefValueWrapper, is_leaves: bool, filter_mode: bool) -> Self {
ValueFilter { vw: ValueWrapper::new(v, is_leaves), last_key: None, filter_mode }
}
fn iter_to_value_vec<'a, I: Iterator<Item=&'a mut Value>>(iter: I) -> Vec<Value> {
iter.map(|v| v.take())
fn iter_to_value_vec<'a, I: Iterator<Item=&'a TypeRefValue>>(iter: I) -> Vec<TypeRefValue> {
iter
.map(|v| v.clone())
.filter(|v| !v.is_null())
.collect()
}
fn get_nested_array<F: ArrayIndex>(v: &mut Value, key: F, filter_mode: bool) -> Value {
fn get_nested_array<F: ArrayIndex>(v: &RefValueWrapper, key: F, filter_mode: bool) -> RefValueWrapper {
if v.is_array() && v.as_array().unwrap().get(key.index(v)).is_some() {
if filter_mode {
v.take()
v.clone()
} else {
let idx = key.index(v);
v.get_mut(idx).unwrap().take()
v.get(idx).unwrap().clone()
}
} else {
key.take_value(v)
}
}
fn get_nested_object(v: &mut Value, key: &String, filter_mode: bool) -> Value {
fn get_nested_object(v: &RefValueWrapper, key: &String, filter_mode: bool) -> RefValueWrapper {
if v.is_object() && v.as_object().unwrap().contains_key(key) {
if filter_mode {
v.take()
v.clone()
} else {
v.get_mut(key).unwrap().take()
v.get(key.clone()).unwrap().clone()
}
} else {
Value::Null
RefValue::Null.into()
}
}
fn collect_all(key: Option<&String>, v: &Value, buf: &mut Vec<Value>) {
match v {
Value::Array(vec) => {
fn collect_all(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec<TypeRefValue>) {
match v.get_data_ref() {
RefValue::Array(vec) => {
if key.is_none() {
for v in vec {
buf.push(v.clone());
}
}
for i in vec {
Self::collect_all(key, &i, buf);
Self::collect_all(key, &i.into(), buf);
}
}
Value::Object(v) => {
RefValue::Object(v) => {
for (k, v) in v.into_iter() {
if match key {
Some(map_key) => map_key == k,
@ -120,7 +120,7 @@ impl ValueFilter {
}
}
for (_, v) in v.into_iter() {
Self::collect_all(key, &v, buf);
Self::collect_all(key, &v.into(), buf);
}
}
_ => {}
@ -133,7 +133,7 @@ impl ValueFilter {
Self::collect_all(None, &self.vw.get_val(), &mut buf);
trace!("step_leaves_all - {:?}", buf);
self.last_key = Some(ValueFilterKey::All);
self.vw = ValueWrapper::new(Value::Array(buf), true);
self.vw = ValueWrapper::new(RefValue::Array(buf).into(), true);
&self.vw
}
@ -143,53 +143,63 @@ impl ValueFilter {
pub fn step_leaves_string(&mut self, key: &String) -> &ValueWrapper {
debug!("step_leaves_string");
let mut buf: Vec<Value> = Vec::new();
let mut buf = Vec::new();
Self::collect_all(Some(key), &self.vw.get_val(), &mut buf);
trace!("step_leaves_string - {:?}", buf);
self.last_key = Some(ValueFilterKey::String(key.clone()));
self.vw = ValueWrapper::new(Value::Array(buf), true);
self.vw = ValueWrapper::new(RefValue::Array(buf).into(), true);
&self.vw
}
pub fn step_in_all(&mut self) -> &ValueWrapper {
debug!("step_in_all");
let vec = match &mut self.vw.get_val_mut() {
Value::Object(map) => Self::iter_to_value_vec(map.values_mut()),
Value::Array(list) => Self::iter_to_value_vec(list.iter_mut()),
Value::Null => Vec::new(),
other => vec![other.take()]
let vec = match self.vw.get_val().get_data_ref() {
RefValue::Object(ref map) => {
Self::iter_to_value_vec(map.values())
}
RefValue::Array(ref list) => {
Self::iter_to_value_vec(list.iter())
}
RefValue::Null => Vec::new(),
_ => vec![self.vw.get_val().clone_data()]
};
self.last_key = Some(ValueFilterKey::All);
self.vw.replace(Value::Array(vec));
trace!("step_in_all - {:?}", self.vw.get_val());
self.vw.replace(RefValue::Array(vec).into());
trace!("step_in_all - {:?}", self.vw.get_val().get_data_ref());
&self.vw
}
pub fn step_in_num(&mut self, key: &f64) -> &ValueWrapper {
debug!("step_in_num");
trace!("step_in_num - before: leaves {}, filterMode {} - {:?}", self.vw.is_leaves(), self.filter_mode, self.vw.get_val());
trace!("step_in_num - before: leaves {}, filterMode {} - {:?}"
, self.vw.is_leaves()
, self.filter_mode
, self.vw.get_val().get_data_ref());
let v = if self.vw.is_leaves() {
let filter_mode = self.filter_mode;
match &mut self.vw.get_val_mut() {
Value::Array(v) => {
let vec: Vec<Value> = v.iter_mut()
.map(|v| Self::get_nested_array(v, *key, filter_mode))
.filter(|v| !v.is_null())
.collect();
Value::Array(vec)
match self.vw.get_val().get_data_ref() {
RefValue::Array(ref vec) => {
let mut ret = Vec::new();
for v in vec {
let wrapper = Self::get_nested_array(&v.into(), *key, filter_mode);
if !wrapper.is_null() {
ret.push(wrapper.clone_data());
}
}
RefValue::Array(ret).into()
}
other => key.take_value(other)
_ => key.take_value(&self.vw.get_val())
}
} else {
key.take_value(self.vw.get_val_mut())
key.take_value(&self.vw.get_val())
};
self.last_key = Some(ValueFilterKey::Num(key.index(&v)));
self.vw.replace(v);
trace!("step_in_num - after: {:?}", self.vw.get_val());
trace!("step_in_num - after: {:?}", self.vw.get_val().get_data_ref());
&self.vw
}
@ -199,55 +209,68 @@ impl ValueFilter {
pub fn step_in_string(&mut self, key: &String) -> &ValueWrapper {
debug!("step_in_string");
trace!("step_in_string - before: {},{},{:?}", self.vw.is_leaves(), self.filter_mode, self.vw.get_val());
trace!("step_in_string - before: {},{},{:?}"
, self.vw.is_leaves()
, self.filter_mode
, self.vw.get_val().get_data_ref());
let filter_mode = self.filter_mode;
let is_leaves = self.vw.is_leaves();
let v = match &mut self.vw.get_val_mut() {
Value::Array(ref mut vec) if is_leaves => {
let val = match self.vw.get_val().get_data_ref() {
RefValue::Array(ref vec) if is_leaves => {
let mut buf = Vec::new();
for mut item in vec {
if let Value::Array(v) = item {
let mut ret: Vec<Value> = v.iter_mut()
.map(|v| Self::get_nested_object(v, key, filter_mode))
.filter(|v| !v.is_null())
.collect();
for mut v in vec {
let wrapper: RefValueWrapper = v.into();
if wrapper.is_array() {
let vec = wrapper.as_array().unwrap();
let mut ret = Vec::new();
for v in vec {
let nested_wrapper = Self::get_nested_object(&v.into(), key, filter_mode);
if !nested_wrapper.is_null() {
ret.push(nested_wrapper.clone_data());
}
}
buf.append(&mut ret);
} else {
match item.get_mut(key) {
Some(v) => buf.push(v.take()),
match wrapper.get(key.clone()) {
Some(v) => buf.push(v.clone_data()),
_ => {}
}
}
}
Value::Array(buf)
RefValue::Array(buf).into()
}
Value::Array(v) if !is_leaves => {
let vec: Vec<Value> = v.iter_mut()
.map(|v| Self::get_nested_object(v, key, filter_mode))
.filter(|v| !v.is_null())
.collect();
Value::Array(vec)
RefValue::Array(ref vec) if !is_leaves => {
let mut ret = Vec::new();
for v in vec {
let wrapper = Self::get_nested_object(&v.into(), key, filter_mode);
if !wrapper.is_null() {
ret.push(wrapper.clone_data());
}
}
RefValue::Array(ret).into()
}
other => {
match other.get_mut(key) {
Some(v) => v.take(),
_ => Value::Null
_ => {
match self.vw.get_val().get(key.clone()) {
Some(v) => v.clone(),
_ => RefValue::Null.into()
}
}
};
self.last_key = Some(ValueFilterKey::String(key.clone()));
self.vw.replace(v);
trace!("step_in_string - after: {},{},{:?}", self.vw.is_leaves(), self.filter_mode, self.vw.get_val());
self.vw.replace(val);
trace!("step_in_string - after: {},{},{:?}"
, self.vw.is_leaves()
, self.filter_mode
, self.vw.get_val().get_data_ref());
&self.vw
}
}
pub struct JsonValueFilter {
json: Rc<Box<Value>>,
json: RefValueWrapper,
filter_stack: Vec<ValueFilter>,
token_stack: Vec<ParseToken>,
term_stack: Vec<TermContext>,
@ -257,12 +280,12 @@ impl JsonValueFilter {
pub fn new(json: &str) -> result::Result<Self, String> {
let json: Value = serde_json::from_str(json)
.map_err(|e| e.description().to_string())?;
Ok(JsonValueFilter::new_from_value(Rc::new(Box::new(json))))
Ok(JsonValueFilter::new_from_value(json.into()))
}
pub fn new_from_value(json: Rc<Box<Value>>) -> Self {
pub fn new_from_value(json: RefValueWrapper) -> Self {
JsonValueFilter {
json: json,
json,
filter_stack: Vec::new(),
token_stack: Vec::new(),
term_stack: Vec::new(),
@ -287,14 +310,13 @@ impl JsonValueFilter {
Some(self.filter_stack.push(vf))
});
} else {
let v: &Value = self.json.as_ref().borrow();
self.filter_stack.push({
ValueFilter::new(v.clone(), false, from_current)
ValueFilter::new(self.json.clone(), false, from_current)
});
}
}
fn replace_filter_stack(&mut self, v: Value, is_leaves: bool) {
fn replace_filter_stack(&mut self, v: RefValueWrapper, is_leaves: bool) {
if self.filter_stack.is_empty() {
self.filter_stack.push(ValueFilter::new(v, is_leaves, false));
} else {
@ -312,17 +334,17 @@ impl JsonValueFilter {
}
}
pub fn current_value(&self) -> &Value {
pub fn current_value(&self) -> RefValueWrapper {
match self.filter_stack.last() {
Some(v) => &v.vw.get_val(),
_ => &Value::Null
Some(v) => v.vw.get_val().clone(),
_ => RefValue::Null.into()
}
}
pub fn take_value(&mut self) -> Value {
pub fn take_value(&mut self) -> RefValueWrapper {
match self.filter_stack.last_mut() {
Some(v) => v.vw.get_val_mut().take(),
_ => Value::Null
Some(v) => v.vw.get_val().clone(),
_ => RefValue::Null.into()
}
}
@ -331,25 +353,28 @@ impl JsonValueFilter {
match self.filter_stack.last_mut() {
Some(ref mut vf) if vf.vw.is_array() && vf.vw.is_leaves() => {
if let Value::Array(mut val) = vf.vw.get_val_mut().take() {
let mut ret = Vec::new();
for mut v in &mut val {
let mut ret = Vec::new();
if let RefValue::Array(val) = vf.vw.get_val().get_data_ref() {
for mut v in val {
for i in &indices {
let v = i.take_value(v);
let v = i.take_value(&v.into());
if !v.is_null() {
ret.push(v);
ret.push(v.clone_data());
}
}
}
vf.vw.replace(Value::Array(ret));
}
vf.vw.replace(RefValue::Array(ret).into());
}
Some(ref mut vf) if vf.vw.is_array() && !vf.vw.is_leaves() => {
let ret = indices.into_iter()
.map(|i| i.take_value(vf.vw.get_val_mut()))
.filter(|v| !v.is_null())
.collect();
vf.vw.replace(Value::Array(ret));
let mut ret = Vec::new();
for i in indices {
let wrapper = i.take_value(&vf.vw.get_val());
if !wrapper.is_null() {
ret.push(wrapper.clone_data());
}
}
vf.vw.replace(RefValue::Array(ret).into());
}
_ => {}
}
@ -358,43 +383,51 @@ impl JsonValueFilter {
fn token_range(&mut self, from: Option<isize>, to: Option<isize>) {
self.token_stack.pop();
fn _from_to<F: ArrayIndex>(from: Option<F>, to: Option<F>, val: &Value) -> (usize, usize) {
fn _from_to<F: ArrayIndex>(from: Option<F>, to: Option<F>, val: &RefValueWrapper) -> (usize, usize) {
let from = match from {
Some(v) => v.index(val),
_ => 0
};
let to = match to {
Some(v) => v.index(val),
_ => if let Value::Array(v) = val { v.len() } else { 0 }
_ => {
if let RefValue::Array(v) = val.get_data_ref() {
v.len()
} else {
0
}
}
};
(from, to)
}
fn _range(from: usize, to: usize, v: &mut Value) -> Vec<Value> {
fn _range(from: usize, to: usize, v: &RefValueWrapper) -> Vec<TypeRefValue> {
trace!("range - {}:{}", from, to);
(from..to).into_iter()
.map(|i| i.take_value(v))
.filter(|v| !v.is_null())
.map(|v| v.clone_data())
.collect()
}
match self.filter_stack.last_mut() {
Some(ref mut vf) if vf.vw.is_array() && vf.vw.is_leaves() => {
if let Value::Array(mut vec) = vf.vw.get_val_mut().take() {
let mut buf = Vec::new();
for mut item in &mut vec {
let (from, to) = _from_to(from, to, item);
let mut v: Vec<Value> = _range(from, to, item);
let mut buf = Vec::new();
if let RefValue::Array(vec) = vf.vw.get_val().get_data_ref() {
for mut v in vec {
let wrapper = v.into();
let (from, to) = _from_to(from, to, &wrapper);
let mut v: Vec<TypeRefValue> = _range(from, to, &wrapper);
buf.append(&mut v);
}
vf.vw.replace(Value::Array(buf));
}
vf.vw.replace(RefValue::Array(buf).into());
}
Some(ref mut vf) if vf.vw.is_array() && !vf.vw.is_leaves() => {
let (from, to) = _from_to(from, to, vf.vw.get_val());
let v: Vec<Value> = _range(from, to, vf.vw.get_val_mut());
vf.vw.replace(Value::Array(v));
let (from, to) = _from_to(from, to, &vf.vw.get_val());
let vec: Vec<TypeRefValue> = _range(from, to, vf.vw.get_val());
vf.vw.replace(RefValue::Array(vec).into());
}
_ => {}
}
@ -449,19 +482,19 @@ impl JsonValueFilter {
_ => {}
}
}
Some(TermContext::Json(_, mut vw)) => {
self.replace_filter_stack(vw.get_val_mut().take(), vw.is_leaves());
Some(TermContext::Json(_, vw)) => {
self.replace_filter_stack(vw.get_val().clone(), vw.is_leaves());
}
_ => {
match self.filter_stack.pop() {
Some(mut vf) => {
let is_leaves = vf.vw.is_leaves();
match vf.vw.get_val_mut() {
Value::Null | Value::Bool(false) => {
self.replace_filter_stack(Value::Null, is_leaves);
match vf.vw.get_val().get_data_ref() {
RefValue::Null | RefValue::Bool(false) => {
self.replace_filter_stack(RefValue::Null.into(), is_leaves);
}
other => {
self.replace_filter_stack(other.take(), is_leaves);
_ => {
self.replace_filter_stack(vf.vw.get_val().clone(), is_leaves);
}
}
}
@ -479,18 +512,18 @@ impl JsonValueFilter {
trace!("right {:?}", right);
if left.is_some() && right.is_some() {
let mut left = left.unwrap();
let mut right = right.unwrap();
let left = left.unwrap();
let right = right.unwrap();
let tc = match ft {
FilterToken::Equal => left.eq(&mut right),
FilterToken::NotEqual => left.ne(&mut right),
FilterToken::Greater => left.gt(&mut right),
FilterToken::GreaterOrEqual => left.ge(&mut right),
FilterToken::Little => left.lt(&mut right),
FilterToken::LittleOrEqual => left.le(&mut right),
FilterToken::And => left.and(&mut right),
FilterToken::Or => left.or(&mut right),
FilterToken::Equal => left.eq(&right),
FilterToken::NotEqual => left.ne(&right),
FilterToken::Greater => left.gt(&right),
FilterToken::GreaterOrEqual => left.ge(&right),
FilterToken::Little => left.lt(&right),
FilterToken::LittleOrEqual => left.le(&right),
FilterToken::And => left.and(&right),
FilterToken::Or => left.or(&right),
};
self.term_stack.push(tc);
}

View File

@ -1,6 +1,5 @@
use indexmap::map::IndexMap;
use serde_json::Value;
use ref_value::*;
use super::cmp::*;
use super::term::*;
@ -8,12 +7,12 @@ use super::value_filter::*;
#[derive(Debug)]
pub struct ValueWrapper {
val: Value,
val: RefValueWrapper,
is_leaves: bool,
}
impl ValueWrapper {
pub fn new(val: Value, leaves: bool) -> Self {
pub fn new(val: RefValueWrapper, leaves: bool) -> Self {
ValueWrapper { val, is_leaves: leaves }
}
@ -25,7 +24,7 @@ impl ValueWrapper {
self.is_leaves = is_leaves;
}
pub fn cmp(&mut self, other: &mut ValueWrapper, cmp_type: CmpType) -> TermContext {
pub fn cmp(&self, other: &ValueWrapper, cmp_type: CmpType) -> TermContext {
match cmp_type {
CmpType::Eq => {
TermContext::Json(None, self.intersect(other))
@ -39,24 +38,19 @@ impl ValueWrapper {
}
}
fn cmp_with_term<F: PrivCmp>(val: &Value, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool {
match val {
Value::Bool(ref v1) => {
fn cmp_with_term<F: PrivCmp>(val: &RefValueWrapper, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool {
match val.get_data_ref() {
RefValue::Bool(ref v1) => {
match et {
ExprTerm::Bool(v2) => if reverse { cmp_fn.cmp_bool(v2, v1) } else { cmp_fn.cmp_bool(v1, v2) },
_ => default
}
}
Value::Number(ref v1) => match v1.as_f64() {
Some(ref v1) => {
match et {
ExprTerm::Number(v2) => if reverse { cmp_fn.cmp_f64(v2, v1) } else { cmp_fn.cmp_f64(v1, v2) },
_ => default
}
}
RefValue::Number(ref v1) => match et {
ExprTerm::Number(v2) => if reverse { cmp_fn.cmp_f64(v2, &v1.as_f64().unwrap()) } else { cmp_fn.cmp_f64(&v1.as_f64().unwrap(), v2) },
_ => default
},
Value::String(ref v1) => {
RefValue::String(ref v1) => {
match et {
ExprTerm::String(v2) => if reverse { cmp_fn.cmp_string(v2, v1) } else { cmp_fn.cmp_string(v1, v2) },
_ => default
@ -66,12 +60,12 @@ impl ValueWrapper {
}
}
fn take_object_in_array<F: PrivCmp>(&mut self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option<Self> {
fn _filter_with_object<F: Fn(&Value) -> bool>(v: &&mut Value, key: &String, fun: F) -> bool {
match &v {
Value::Object(map) => {
fn take_object_in_array<F: PrivCmp>(&self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option<Self> {
fn _filter_with_object<F: Fn(&RefValueWrapper) -> bool>(v: &RefValueWrapper, key: &String, fun: F) -> bool {
match v.get_data_ref() {
RefValue::Object(map) => {
match map.get(key) {
Some(vv) => fun(vv),
Some(val) => fun(&val.into()),
_ => false
}
}
@ -79,21 +73,24 @@ impl ValueWrapper {
}
}
match self.val.take() {
Value::Array(mut vec) => {
let mut ret: Vec<Value> = vec.iter_mut()
.filter(|v| {
_filter_with_object(v, key, |vv| Self::cmp_with_term(vv, et, cmp, false, reverse))
})
.map(|v| v.take())
.collect();
Some(ValueWrapper::new(Value::Array(ret), false))
match self.val.get_data_ref() {
RefValue::Array(vec) => {
let mut ret = Vec::new();
for v in vec {
if _filter_with_object(&v.into(), key, |vv| {
Self::cmp_with_term(vv, et, cmp, false, reverse)
}) {
ret.push(v.clone());
}
}
Some(ValueWrapper::new(RefValue::Array(ret).into(), false))
}
_ => None
}
}
fn take_with_key_type<F: PrivCmp>(&mut self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: &F, reverse: bool) -> Option<Self> {
fn take_with_key_type<F: PrivCmp>(&self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: &F, reverse: bool) -> Option<Self> {
match key {
Some(ValueFilterKey::String(key)) => {
self.take_object_in_array(key, et, cmp, reverse)
@ -102,23 +99,25 @@ impl ValueWrapper {
}
}
pub fn take_with<F: PrivCmp>(&mut self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: F, reverse: bool) -> Self {
pub fn take_with<F: PrivCmp>(&self, key: &Option<ValueFilterKey>, et: &ExprTerm, cmp: F, reverse: bool) -> Self {
match self.take_with_key_type(key, et, &cmp, reverse) {
Some(vw) => vw,
_ => {
match self.val.take() {
Value::Array(mut vec) => {
let mut ret = vec.iter_mut()
.filter(|v| Self::cmp_with_term(&v, et, &cmp, false, reverse))
.map(|v| v.take())
.collect();
ValueWrapper::new(Value::Array(ret), false)
match self.val.get_data_ref() {
RefValue::Array(vec) => {
let mut ret = Vec::new();
for v in vec {
if Self::cmp_with_term(&v.into(), et, &cmp, false, reverse) {
ret.push(v.clone());
}
}
ValueWrapper::new(RefValue::Array(ret).into(), false)
}
other => {
if Self::cmp_with_term(&other, et, &cmp, false, reverse) {
ValueWrapper::new(other, false)
_ => {
if Self::cmp_with_term(&self.val, et, &cmp, false, reverse) {
ValueWrapper::new(self.val.clone(), false)
} else {
ValueWrapper::new(Value::Null, false)
ValueWrapper::new(RefValue::Null.into(), false)
}
}
}
@ -126,24 +125,25 @@ impl ValueWrapper {
}
}
pub fn replace(&mut self, val: Value) {
let is_null = match &val {
Value::Array(v) => if v.is_empty() { true } else { false },
Value::Object(m) => if m.is_empty() { true } else { false },
pub fn replace(&mut self, val: RefValueWrapper) {
let is_null = match val.get_data_ref() {
RefValue::Array(v) => if v.is_empty() { true } else { false },
RefValue::Object(m) => if m.is_empty() { true } else { false },
_ => val.is_null()
};
self.val = if is_null { Value::Null } else { val };
self.val = if is_null {
let v = RefValueWrapper::wrap(RefValue::Null);
RefValueWrapper::new(v)
} else {
val
};
}
pub fn get_val(&self) -> &Value {
pub fn get_val(&self) -> &RefValueWrapper {
&self.val
}
pub fn get_val_mut(&mut self) -> &mut Value {
&mut self.val
}
pub fn clone_val(&self) -> Value {
pub fn clone_val(&self) -> RefValueWrapper {
self.val.clone()
}
@ -151,150 +151,161 @@ impl ValueWrapper {
self.val.is_array()
}
fn uuid(v: &Value) -> String {
fn _fn(v: &Value) -> String {
match v {
Value::Null => "null".to_string(),
Value::String(v) => v.to_string(),
Value::Bool(v) => v.to_string(),
Value::Number(v) => v.to_string(),
Value::Array(v) => {
v.iter().enumerate()
.map(|(i, v)| { format!("{}{}", i, _fn(v)) })
.collect()
fn uuid(v: &RefValueWrapper) -> String {
fn _fn(v: &RefValueWrapper, acc: &mut String) {
match v.get_data_ref() {
RefValue::Null => acc.push_str("null"),
RefValue::String(v) => acc.push_str(v),
RefValue::Bool(v) => acc.push_str(if *v { "true" } else { "false" }),
RefValue::Number(v) => acc.push_str(&*v.to_string()),
RefValue::Array(v) => {
for (i, v) in v.iter().enumerate() {
acc.push_str(&*i.to_string());
_fn(&v.into(), acc);
}
}
Value::Object(v) => {
v.into_iter().map(|(k, v)| { format!("{}{}", k, _fn(v)) }).collect()
RefValue::Object(ref v) => {
for (k, v) in v.into_iter() {
acc.push_str(&*k.to_string());
_fn(&v.into(), acc);
}
}
}
}
_fn(v)
let mut acc = String::new();
_fn(v, &mut acc);
acc
}
fn into_map(&mut self) -> IndexMap<String, Value> {
fn into_map(&self) -> IndexMap<String, RefValueWrapper> {
let mut map = IndexMap::new();
match &mut self.val {
Value::Array(v1) => {
match self.val.get_data_ref() {
RefValue::Array(ref v1) => {
for v in v1 {
map.insert(Self::uuid(v), v.take());
let wrapper = v.into();
let key = Self::uuid(&wrapper);
map.insert(key, wrapper);
}
}
other => {
map.insert(Self::uuid(other), other.take());
_ => {
map.insert(Self::uuid(&self.val), self.val.clone());
}
}
map
}
pub fn except(&mut self, other: &mut Self) -> Self {
pub fn except(&self, other: &Self) -> Self {
let map = self.into_map();
let mut ret: IndexMap<String, Value> = IndexMap::new();
match &mut other.val {
Value::Array(v1) => {
let mut ret: IndexMap<String, RefValueWrapper> = IndexMap::new();
match other.val.get_data_ref() {
RefValue::Array(ref v1) => {
for v in v1 {
let key = Self::uuid(v);
let wrapper = v.into();
let key = Self::uuid(&wrapper);
if !map.contains_key(&key) {
ret.insert(key, v.take());
ret.insert(key, wrapper);
}
}
}
other => {
let key = Self::uuid(other);
_ => {
let key = Self::uuid(&other.val);
if !map.contains_key(&key) {
ret.insert(key, other.take());
ret.insert(key, other.val.clone());
}
}
}
let v = ret.values_mut().into_iter().map(|v| v.take()).collect();
ValueWrapper::new(v, false)
let vec = ret.values().into_iter().map(|v| v.clone_data()).collect();
ValueWrapper::new(RefValue::Array(vec).into(), false)
}
pub fn intersect(&mut self, other: &mut Self) -> Self {
pub fn intersect(&self, other: &Self) -> Self {
let map = self.into_map();
let mut ret: IndexMap<String, Value> = IndexMap::new();
match &mut other.val {
Value::Array(v1) => {
let mut ret: IndexMap<String, RefValueWrapper> = IndexMap::new();
match other.val.get_data_ref() {
RefValue::Array(ref v1) => {
for v in v1 {
let key = Self::uuid(v);
let wrapper = v.into();
let key = Self::uuid(&wrapper);
if map.contains_key(&key) {
ret.insert(key, v.take());
ret.insert(key, wrapper);
}
}
}
other => {
let key = Self::uuid(other);
_ => {
let key = Self::uuid(&other.val);
if map.contains_key(&key) {
ret.insert(key, other.take());
ret.insert(key, other.val.clone());
}
}
}
let v = ret.values_mut().into_iter().map(|v| v.take()).collect();
ValueWrapper::new(v, false)
let vec = ret.values().into_iter().map(|v| v.clone_data()).collect();
ValueWrapper::new(RefValue::Array(vec).into(), false)
}
pub fn union(&mut self, other: &mut Self) -> Self {
pub fn union(&self, other: &Self) -> Self {
let mut map = self.into_map();
match &mut other.val {
Value::Array(v1) => {
match other.val.get_data_ref() {
RefValue::Array(ref v1) => {
for v in v1 {
let key = Self::uuid(v);
let wrapper = v.into();
let key = Self::uuid(&wrapper);
if !map.contains_key(&key) {
map.insert(key, v.take());
map.insert(key, wrapper);
}
}
}
other => {
let key = Self::uuid(other);
_ => {
let key = Self::uuid(&other.val);
if !map.contains_key(&key) {
map.insert(key, other.take());
map.insert(key, other.val.clone());
}
}
}
let mut vw = ValueWrapper::new(Value::Null, false);
let list: Vec<Value> = map.values_mut().into_iter().map(|val| val.take()).collect();
vw.replace(Value::Array(list));
let mut vw = ValueWrapper::new(RefValue::Null.into(), false);
let list = map.values().into_iter().map(|val| val.clone_data()).collect();
vw.replace(RefValue::Array(list).into());
vw
}
pub fn into_term(&mut self, key: &mut Option<ValueFilterKey>) -> TermContext {
match self.val.take() {
Value::String(s) => TermContext::Constants(ExprTerm::String(s)),
Value::Number(n) => TermContext::Constants(ExprTerm::Number(n.as_f64().unwrap())),
Value::Bool(b) => TermContext::Constants(ExprTerm::Bool(b)),
other => TermContext::Json(match key {
pub fn into_term(&self, key: &Option<ValueFilterKey>) -> TermContext {
match self.val.get_data_ref() {
RefValue::String(ref s) => TermContext::Constants(ExprTerm::String(s.clone())),
RefValue::Number(ref n) => TermContext::Constants(ExprTerm::Number(n.as_f64().unwrap())),
RefValue::Bool(b) => TermContext::Constants(ExprTerm::Bool(*b)),
_ => TermContext::Json(match key {
Some(vk) => Some(vk.clone()),
_ => None
}, ValueWrapper::new(other, false))
}, ValueWrapper::new(self.val.clone(), false))
}
}
pub fn filter(&mut self, key: &mut Option<ValueFilterKey>) -> Self {
let v = match &mut self.val {
Value::Array(vec) => {
let ret = vec.iter_mut()
.filter(|v| match key {
Some(ValueFilterKey::String(val_key)) => {
v.get(val_key.as_str()).is_some()
pub fn filter(&self, key: &Option<ValueFilterKey>) -> Self {
let v = match self.val.get_data_ref() {
RefValue::Array(ref vec) => {
let mut ret = Vec::new();
for v in vec {
if let Some(ValueFilterKey::String(k)) = key {
let wrapper: RefValueWrapper = v.into();
if wrapper.get(k.clone()).is_some() {
ret.push(v.clone());
}
_ => false
})
.map(|v| v.take())
.collect();
Value::Array(ret)
}
}
RefValue::Array(ret).into()
}
Value::Object(map) => {
RefValue::Object(ref map) => {
match key {
Some(ValueFilterKey::String(val_key)) => match map.get_mut(val_key) {
Some(v) => v.take(),
_ => Value::Null
Some(ValueFilterKey::String(k)) => match map.get(k) {
Some(v) => v.into(),
_ => RefValue::Null.into()
},
_ => Value::Null
_ => RefValue::Null.into()
}
}
other => other.take()
_ => self.val.clone()
};
ValueWrapper::new(v, false)

View File

@ -43,26 +43,26 @@
//! "expensive": 10
//! });
//!
//! let mut reader = jsonpath::reader(json_obj);
//! let mut selector = jsonpath::selector(json_obj);
//!
//! //
//! // $.store.book[*].author
//! //
//! let json = reader("$.store.book[*].author").unwrap();
//! let json = selector("$.store.book[*].author").unwrap();
//! let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]);
//! assert_eq!(json, ret);
//!
//! //
//! // $..author
//! //
//! let json = reader("$..author").unwrap();
//! let json = selector("$..author").unwrap();
//! let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]);
//! assert_eq!(json, ret);
//!
//! //
//! // $.store.*
//! //
//! let json = reader("$.store.*").unwrap();
//! let json = selector("$.store.*").unwrap();
//! let ret = json!([
//! [
//! {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95},
@ -77,14 +77,14 @@
//! //
//! // $.store..price
//! //
//! let json = reader("$.store..price").unwrap();
//! let json = selector("$.store..price").unwrap();
//! let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]);
//! assert_eq!(ret, json);
//!
//! //
//! // $..book[2]
//! //
//! let json = reader("$..book[2]").unwrap();
//! let json = selector("$..book[2]").unwrap();
//! let ret = json!([{
//! "category" : "fiction",
//! "author" : "Herman Melville",
@ -97,7 +97,7 @@
//! //
//! // $..book[-2]
//! //
//! let json = reader("$..book[-2]").unwrap();
//! let json = selector("$..book[-2]").unwrap();
//! let ret = json!([{
//! "category" : "fiction",
//! "author" : "Herman Melville",
@ -110,7 +110,7 @@
//! //
//! // $..book[0,1]
//! //
//! let json = reader("$..book[0,1]").unwrap();
//! let json = selector("$..book[0,1]").unwrap();
//! let ret = json!([
//! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95},
//! {"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}
@ -120,7 +120,7 @@
//! //
//! // $..book[:2]
//! //
//! let json = reader("$..book[:2]").unwrap();
//! let json = selector("$..book[:2]").unwrap();
//! let ret = json!([
//! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95},
//! {"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99}
@ -130,7 +130,7 @@
//! //
//! // $..book[2:]
//! //
//! let json = reader("$..book[2:]").unwrap();
//! let json = selector("$..book[2:]").unwrap();
//! let ret = json!([
//! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99},
//! {"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99}
@ -140,7 +140,7 @@
//! //
//! // $..book[?(@.isbn)]
//! //
//! let json = reader("$..book[?(@.isbn)]").unwrap();
//! let json = selector("$..book[?(@.isbn)]").unwrap();
//! let ret = json!([
//! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99},
//! {"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99}
@ -150,7 +150,7 @@
//! //
//! // $.store.book[?(@.price < 10)]
//! //
//! let json = reader("$.store.book[?(@.price < 10)]").unwrap();
//! let json = selector("$.store.book[?(@.price < 10)]").unwrap();
//! let ret = json!([
//! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95},
//! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}
@ -175,14 +175,17 @@ extern crate indexmap;
pub mod parser;
#[doc(hidden)]
pub mod filter;
#[doc(hidden)]
pub mod ref_value;
use parser::parser::*;
use filter::value_filter::*;
use std::result;
use std::rc::Rc;
use serde_json::Value;
use ref_value::*;
type Result = result::Result<Value, String>;
/// # Read multiple Json multiple times with the same JsonPath
@ -223,9 +226,9 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(Value) -> Result + 'a {
move |json| {
match &node {
Ok(n) => {
let mut jf = JsonValueFilter::new_from_value(Rc::new(Box::new(json)));
let mut jf = JsonValueFilter::new_from_value(json.into());
jf.visit(n.clone());
Ok(jf.take_value())
Ok(jf.take_value().into_value())
}
Err(e) => Err(e.clone())
}
@ -246,26 +249,31 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(Value) -> Result + 'a {
/// "friends": [{"id": 0},{"id": 1}]
/// });
///
/// let mut reader = jsonpath::reader(json_obj);
/// let mut selector = jsonpath::selector(json_obj);
///
/// let json = reader("$..friends[0]").unwrap();
/// let json = selector("$..friends[0]").unwrap();
/// let ret = json!([ {"id": 0}, {"id": 0} ]);
/// assert_eq!(json, ret);
///
/// let json = reader("$..friends[1]").unwrap();
/// let json = selector("$..friends[1]").unwrap();
/// let ret = json!([ {"id": 1}, {"id": 1} ]);
/// assert_eq!(json, ret);
/// ```
pub fn reader(json: Value) -> impl FnMut(&str) -> Result {
let n = Rc::new(Box::new(json));
pub fn selector(json: Value) -> impl FnMut(&str) -> Result {
let wrapper: RefValueWrapper = json.into();
move |path: &str| {
let mut jf = JsonValueFilter::new_from_value(n.clone());
let mut jf = JsonValueFilter::new_from_value(wrapper.clone());
let mut parser = Parser::new(path);
parser.parse(&mut jf)?;
Ok(jf.take_value())
Ok(jf.take_value().into_value())
}
}
/// # Read the same Json multiple times using different JsonPath - Deprecated. use selector
pub fn reader(json: Value) -> impl FnMut(&str) -> Result {
selector(json)
}
/// # Read Json using JsonPath
///
/// ```rust
@ -278,15 +286,20 @@ pub fn reader(json: Value) -> impl FnMut(&str) -> Result {
/// },
/// "friends": [{"id": 0}, {"id": 1}]
/// });
/// let json = jsonpath::read(json_obj, "$..friends[0]").unwrap();
/// let json = jsonpath::select(json_obj, "$..friends[0]").unwrap();
/// let ret = json!([ {"id": 0}, {"id": 0} ]);
/// assert_eq!(json, ret);
/// ```
pub fn read(json: Value, path: &str) -> Result {
let mut jf = JsonValueFilter::new_from_value(Rc::new(Box::new(json)));
pub fn select(json: Value, path: &str) -> Result {
let mut jf = JsonValueFilter::new_from_value(json.into());
let mut parser = Parser::new(path);
parser.parse(&mut jf)?;
Ok(jf.take_value())
Ok(jf.take_value().into_value())
}
/// # Read Json using JsonPath - Deprecated. use select
pub fn read(json: Value, path: &str) -> Result {
select(json, path)
}
#[cfg(test)]
@ -323,9 +336,9 @@ mod tests {
}
#[test]
fn reader() {
fn selector() {
let json_obj = read_json("./benches/data_obj.json");
let mut reader = super::reader(json_obj);
let mut reader = super::selector(json_obj);
let json = reader("$..friends[2]").unwrap();
let ret = json!([
{"id": 2,"name": "Gray Berry"},
@ -342,9 +355,9 @@ mod tests {
}
#[test]
fn read() {
fn select() {
let json_obj = read_json("./benches/example.json");
let json = super::read(json_obj, "$..book[2]").unwrap();
let json = super::select(json_obj, "$..book[2]").unwrap();
let ret = json!([{
"category" : "fiction",
"author" : "Herman Melville",

View File

@ -13,25 +13,21 @@ type Result<T> = result::Result<T, String>;
mod utils {
use std::result;
pub fn vec_to_int<F>(vec: &Vec<char>, msg_handler: F) -> result::Result<isize, String>
pub fn string_to_isize<F>(string: &String, msg_handler: F) -> result::Result<isize, String>
where F: Fn() -> String {
match vec.iter().map(|c| *c).collect::<String>().as_str().parse::<isize>() {
match string.as_str().parse::<isize>() {
Ok(n) => Ok(n),
_ => Err(msg_handler())
}
}
pub fn vec_to_float<F>(vec: &Vec<char>, msg_handler: F) -> result::Result<f64, String>
pub fn string_to_f64<F>(string: &String, msg_handler: F) -> result::Result<f64, String>
where F: Fn() -> String {
match vec.iter().map(|c| *c).collect::<String>().as_str().parse::<f64>() {
match string.as_str().parse::<f64>() {
Ok(n) => Ok(n),
_ => Err(msg_handler())
}
}
pub fn vec_to_string(vec: &Vec<char>) -> String {
vec.iter().map(|c| *c).collect::<String>()
}
}
#[derive(Debug, PartialEq, Clone)]
@ -236,7 +232,7 @@ impl<'a> Parser<'a> {
debug!("#key");
match self.tokenizer.next_token() {
Ok(Token::Key(_, v)) => {
Ok(self.node(ParseToken::Key(utils::vec_to_string(&v))))
Ok(self.node(ParseToken::Key(v)))
}
_ => {
Err(self.tokenizer.err_msg())
@ -247,9 +243,9 @@ impl<'a> Parser<'a> {
fn array_quota_value(&mut self) -> Result<Node> {
debug!("#array_quota_value");
match self.tokenizer.next_token() {
Ok(Token::SingleQuoted(_, ref vec))
| Ok(Token::DoubleQuoted(_, ref vec)) => {
Ok(self.node(ParseToken::Key(utils::vec_to_string(vec))))
Ok(Token::SingleQuoted(_, val))
| Ok(Token::DoubleQuoted(_, val)) => {
Ok(self.node(ParseToken::Key(val)))
}
Err(TokenError::Eof) => {
Ok(self.node(ParseToken::Eof))
@ -299,9 +295,8 @@ impl<'a> Parser<'a> {
fn array_value_key(&mut self) -> Result<Node> {
debug!("#array_value_key");
match self.tokenizer.next_token() {
Ok(Token::Key(pos, ref vec)) => {
let digit = utils::vec_to_int(vec,
|| self.tokenizer.err_msg_with_pos(pos))?;
Ok(Token::Key(pos, ref val)) => {
let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?;
self.eat_whitespace();
match self.tokenizer.peek_token() {
@ -357,9 +352,8 @@ impl<'a> Parser<'a> {
self.eat_token();
self.eat_whitespace();
match self.tokenizer.next_token() {
Ok(Token::Key(pos, ref vec)) => {
let digit = utils::vec_to_int(vec,
|| self.tokenizer.err_msg_with_pos(pos))?;
Ok(Token::Key(pos, ref val)) => {
let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?;
values.push(digit);
}
_ => {
@ -387,9 +381,8 @@ impl<'a> Parser<'a> {
fn range_to(&mut self) -> Result<Node> {
debug!("#range_to");
match self.tokenizer.next_token() {
Ok(Token::Key(pos, ref vec)) => {
let digit = utils::vec_to_int(vec,
|| self.tokenizer.err_msg_with_pos(pos))?;
Ok(Token::Key(pos, ref val)) => {
let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?;
Ok(self.node(ParseToken::Range(None, Some(digit))))
}
_ => {
@ -401,9 +394,8 @@ impl<'a> Parser<'a> {
fn range(&mut self, num: isize) -> Result<Node> {
debug!("#range");
match self.tokenizer.next_token() {
Ok(Token::Key(pos, ref vec)) => {
let digit = utils::vec_to_int(vec,
|| self.tokenizer.err_msg_with_pos(pos))?;
Ok(Token::Key(pos, ref val)) => {
let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?;
Ok(self.node(ParseToken::Range(Some(num), Some(digit))))
}
_ => {
@ -505,14 +497,13 @@ impl<'a> Parser<'a> {
fn term_num(&mut self) -> Result<Node> {
debug!("#term_num");
match self.tokenizer.next_token() {
Ok(Token::Key(pos, mut vec)) => {
Ok(Token::Key(pos, val)) => {
match self.tokenizer.peek_token() {
Ok(Token::Dot(_)) => {
self.term_num_float(&mut vec)
self.term_num_float(val.as_str())
}
_ => {
let number = utils::vec_to_float(&vec,
|| self.tokenizer.err_msg_with_pos(pos))?;
let number = utils::string_to_f64(&val, || self.tokenizer.err_msg_with_pos(pos))?;
Ok(self.node(ParseToken::Number(number)))
}
}
@ -526,17 +517,16 @@ impl<'a> Parser<'a> {
}
}
fn term_num_float(&mut self, mut num: &mut Vec<char>) -> Result<Node> {
fn term_num_float(&mut self, mut num: &str) -> Result<Node> {
debug!("#term_num_float");
self.eat_token();
match self.tokenizer.next_token() {
Ok(Token::Key(pos, mut frac)) => {
let mut f = vec![];
f.append(&mut num);
Ok(Token::Key(pos, frac)) => {
let mut f = String::new();
f.push_str(&mut num);
f.push('.');
f.append(&mut frac);
let number = utils::vec_to_float(&f,
|| self.tokenizer.err_msg_with_pos(pos))?;
f.push_str(frac.as_str());
let number = utils::string_to_f64(&f, || self.tokenizer.err_msg_with_pos(pos))?;
Ok(self.node(ParseToken::Number(number)))
}
_ => {

View File

@ -23,19 +23,23 @@ impl<'a> PathReader<'a> {
Ok((self.pos + ch.len_utf8(), ch))
}
pub fn take_while<F>(&mut self, fun: F) -> result::Result<(usize, Vec<char>), ReaderError>
pub fn take_while<F>(&mut self, fun: F) -> result::Result<(usize, String), ReaderError>
where
F: Fn(&char) -> bool
{
let vec: Vec<char> = self.input.chars()
.by_ref()
.take_while(fun)
.collect();
let mut char_len: usize = 0;
let mut ret = String::new();
for c in self.input.chars().by_ref() {
if !fun(&c) {
break;
}
char_len += c.len_utf8();
ret.push(c);
}
let char_len: usize = vec.iter().by_ref().map(|c| c.len_utf8()).sum();
self.pos += char_len;
self.input = &self.input[char_len..];
Ok((self.pos, vec))
Ok((self.pos, ret))
}
pub fn next_char(&mut self) -> result::Result<(usize, char), ReaderError> {

View File

@ -75,9 +75,9 @@ pub enum Token {
Split(usize),
OpenParenthesis(usize),
CloseParenthesis(usize),
Key(usize, Vec<char>),
DoubleQuoted(usize, Vec<char>),
SingleQuoted(usize, Vec<char>),
Key(usize, String),
DoubleQuoted(usize, String),
SingleQuoted(usize, String),
Equal(usize),
GreaterOrEqual(usize),
Greater(usize),
@ -153,15 +153,15 @@ impl<'a> Tokenizer<'a> {
}
fn single_quota(&mut self, pos: usize, ch: char) -> result::Result<Token, TokenError> {
let (_, vec) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?;
let (_, val) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?;
self.input.next_char().map_err(to_token_error)?;
Ok(Token::SingleQuoted(pos, vec))
Ok(Token::SingleQuoted(pos, val))
}
fn double_quota(&mut self, pos: usize, ch: char) -> result::Result<Token, TokenError> {
let (_, vec) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?;
let (_, val) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?;
self.input.next_char().map_err(to_token_error)?;
Ok(Token::DoubleQuoted(pos, vec))
Ok(Token::DoubleQuoted(pos, val))
}
fn equal(&mut self, pos: usize, _: char) -> result::Result<Token, TokenError> {
@ -414,9 +414,9 @@ mod tests {
vec![
Token::Absolute(0),
Token::Dot(1),
Token::Key(2, vec!['0', '1']),
Token::Key(2, "01".to_string()),
Token::Dot(4),
Token::Key(5, vec!['a'])
Token::Key(5, "a".to_string())
]
, Some(TokenError::Eof)
));
@ -449,7 +449,7 @@ mod tests {
Token::Absolute(0),
Token::Dot(1),
Token::Dot(2),
Token::Key(3, vec!['a', 'b'])
Token::Key(3, "ab".to_string())
]
, Some(TokenError::Eof)
));
@ -460,7 +460,7 @@ mod tests {
Token::Absolute(0),
Token::Dot(1),
Token::Dot(2),
Token::Key(3, vec!['가']),
Token::Key(3, "".to_string()),
Token::Whitespace(6, 0),
Token::OpenArray(7),
]
@ -471,10 +471,10 @@ mod tests {
(
vec![
Token::OpenArray(0),
Token::Key(1, vec!['-', '1']),
Token::Key(1, "-1".to_string()),
Token::Comma(3),
Token::Whitespace(4, 0),
Token::Key(5, vec!['2']),
Token::Key(5, "2".to_string()),
Token::Whitespace(6, 0),
Token::CloseArray(7),
]
@ -486,19 +486,19 @@ mod tests {
vec![
Token::OpenArray(0),
Token::Whitespace(1, 0),
Token::Key(2, vec!['1']),
Token::Key(2, "1".to_string()),
Token::Whitespace(3, 0),
Token::Key(4, vec!['2']),
Token::Key(4, "2".to_string()),
Token::Whitespace(5, 0),
Token::Comma(6),
Token::Whitespace(7, 0),
Token::Key(8, vec!['3']),
Token::Key(8, "3".to_string()),
Token::Whitespace(9, 0),
Token::DoubleQuoted(10, vec!['a', 'b', 'c']),
Token::DoubleQuoted(10, "abc".to_string()),
Token::Whitespace(15, 0),
Token::Split(16),
Token::Whitespace(17, 0),
Token::Key(18, vec!['-', '1', '0']),
Token::Key(18, "-10".to_string()),
Token::Whitespace(21, 0),
Token::CloseArray(22),
]
@ -512,12 +512,12 @@ mod tests {
Token::OpenParenthesis(1),
Token::At(2),
Token::Dot(3),
Token::Key(4, vec!['a', '가']),
Token::Key(4, "a가".to_string()),
Token::Whitespace(8, 0),
Token::Little(9),
Token::Key(10, vec!['4', '1']),
Token::Key(10, "41".to_string()),
Token::Dot(12),
Token::Key(13, vec!['0', '1']),
Token::Key(13, "01".to_string()),
Token::CloseParenthesis(15),
]
, Some(TokenError::Eof)
@ -530,12 +530,12 @@ mod tests {
Token::OpenParenthesis(1),
Token::At(2),
Token::Dot(3),
Token::Key(4, vec!['a']),
Token::Key(4, "a".to_string()),
Token::Whitespace(5, 0),
Token::Little(6),
Token::Key(7, vec!['4', 'a']),
Token::Key(7, "4a".to_string()),
Token::Dot(9),
Token::Key(10, vec!['0', '1']),
Token::Key(10, "01".to_string()),
Token::CloseParenthesis(12),
]
, Some(TokenError::Eof)
@ -547,11 +547,11 @@ mod tests {
Token::OpenParenthesis(1),
Token::Absolute(2),
Token::Dot(3),
Token::Key(4, vec!['c']),
Token::Key(4, "c".to_string()),
Token::Greater(5),
Token::At(6),
Token::Dot(7),
Token::Key(8, vec!['d']),
Token::Key(8, "d".to_string()),
Token::CloseParenthesis(9)
]
, Some(TokenError::Eof)

384
src/ref_value/mod.rs Normal file
View File

@ -0,0 +1,384 @@
extern crate indexmap;
extern crate serde_json;
use std::sync::Arc;
use std::convert::Into;
use indexmap::map::IndexMap;
use serde_json::Number;
use serde_json::Value;
pub type TypeRefValue = Arc<Box<RefValue>>;
impl Into<RefValueWrapper> for TypeRefValue {
fn into(self) -> RefValueWrapper {
RefValueWrapper::new(self.clone())
}
}
impl Into<RefValueWrapper> for &TypeRefValue {
fn into(self) -> RefValueWrapper {
RefValueWrapper::new(self.clone())
}
}
///
/// serde_json::Value 참고
///
pub trait RefIndex {
fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue>;
fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue>;
fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue;
}
impl RefIndex for usize {
fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue> {
match *v {
RefValue::Array(ref vec) => vec.get(*self),
_ => None,
}
}
fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue> {
match *v {
RefValue::Array(ref mut vec) => vec.get_mut(*self),
_ => None,
}
}
fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue {
match *v {
RefValue::Array(ref mut vec) => {
let len = vec.len();
vec.get_mut(*self).unwrap_or_else(|| {
panic!(
"cannot access index {} of JSON array of length {}",
self, len
)
})
}
_ => panic!("cannot access index {} of JSON {:?}", self, v),
}
}
}
impl RefIndex for str {
fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue> {
match *v {
RefValue::Object(ref map) => map.get(self),
_ => None,
}
}
fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue> {
match *v {
RefValue::Object(ref mut map) => map.get_mut(self),
_ => None,
}
}
fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue {
if let RefValue::Null = *v {
*v = RefValue::Object(IndexMap::new());
}
match *v {
RefValue::Object(ref mut map) => {
map.entry(self.to_owned()).or_insert(RefValueWrapper::wrap(RefValue::Null))
},
_ => panic!("cannot access key {:?} in JSON {:?}", self, v),
}
}
}
impl RefIndex for String {
fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue> {
self[..].index_into(v)
}
fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue> {
self[..].index_into_mut(v)
}
fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue {
self[..].index_or_insert(v)
}
}
#[derive(Debug)]
pub struct RefValueWrapper {
data: TypeRefValue
}
impl RefValueWrapper {
pub fn new(ref_value: TypeRefValue) -> Self {
RefValueWrapper { data: ref_value }
}
pub fn wrap(ref_val: RefValue) -> TypeRefValue {
Arc::new(Box::new(ref_val))
}
pub fn into_value(&self) -> Value {
ValueConverter::new(&self.data)
}
pub fn clone(&self) -> Self {
RefValueWrapper { data: self.data.clone() }
}
pub fn clone_data(&self) -> TypeRefValue {
self.data.clone()
}
pub fn get<I: RefIndex>(&self, index: I) -> Option<RefValueWrapper> {
index.index_into(&**self.data).map(|v| Self::new(v.clone()))
}
pub fn is_object(&self) -> bool {
(**self.data).is_object()
}
pub fn as_object(&self) -> Option<&IndexMap<String, TypeRefValue>> {
(**self.data).as_object()
}
pub fn is_array(&self) -> bool {
(**self.data).is_array()
}
pub fn as_array(&self) -> Option<&Vec<TypeRefValue>> {
(**self.data).as_array()
}
pub fn is_string(&self) -> bool {
(**self.data).is_string()
}
pub fn as_str(&self) -> Option<&str> {
(**self.data).as_str()
}
pub fn is_number(&self) -> bool {
(**self.data).is_number()
}
pub fn as_number(&self) -> Option<Number> {
(**self.data).as_number()
}
pub fn is_boolean(&self) -> bool {
(**self.data).is_boolean()
}
pub fn as_bool(&self) -> Option<bool> {
(**self.data).as_bool()
}
pub fn is_null(&self) -> bool {
(**self.data).is_null()
}
pub fn as_null(&self) -> Option<()> {
(**self.data).as_null()
}
pub fn get_data_ref(&self) -> &RefValue {
&(**self.data)
}
}
impl Into<RefValueWrapper> for Value {
fn into(self) -> RefValueWrapper {
let ref_val = RefValueConverter::new(self);
RefValueWrapper::new(ref_val)
}
}
#[derive(Debug)]
pub enum RefValue {
Null,
Bool(bool),
Number(Number),
String(String),
Array(Vec<TypeRefValue>),
Object(IndexMap<String, TypeRefValue>),
}
impl RefValue {
pub fn get<I: RefIndex>(&self, index: I) -> Option<&TypeRefValue> {
index.index_into(self)
}
pub fn is_object(&self) -> bool {
self.as_object().is_some()
}
pub fn as_object(&self) -> Option<&IndexMap<String, TypeRefValue>> {
match *self {
RefValue::Object(ref map) => Some(map),
_ => None,
}
}
pub fn is_array(&self) -> bool {
self.as_array().is_some()
}
pub fn as_array(&self) -> Option<&Vec<TypeRefValue>> {
match *self {
RefValue::Array(ref array) => Some(&*array),
_ => None,
}
}
pub fn is_string(&self) -> bool {
self.as_str().is_some()
}
pub fn as_str(&self) -> Option<&str> {
match *self {
RefValue::String(ref s) => Some(s),
_ => None,
}
}
pub fn is_number(&self) -> bool {
match *self {
RefValue::Number(_) => true,
_ => false,
}
}
pub fn as_number(&self) -> Option<Number> {
match *self {
RefValue::Number(ref n) => Some(n.clone()),
_ => None,
}
}
pub fn is_boolean(&self) -> bool {
self.as_bool().is_some()
}
pub fn as_bool(&self) -> Option<bool> {
match *self {
RefValue::Bool(b) => Some(b),
_ => None,
}
}
pub fn is_null(&self) -> bool {
self.as_null().is_some()
}
pub fn as_null(&self) -> Option<()> {
match *self {
RefValue::Null => Some(()),
_ => None,
}
}
}
impl Into<RefValueWrapper> for RefValue {
fn into(self) -> RefValueWrapper {
let wrap = RefValueWrapper::wrap(self);
RefValueWrapper::new(wrap)
}
}
struct RefValueConverter;
impl RefValueConverter {
fn new(value: Value) -> TypeRefValue {
RefValueConverter {}.visit_value(value)
}
fn visit_value(&self, value: Value) -> TypeRefValue {
match value {
Value::Null => self.visit_null(),
Value::Bool(v) => self.visit_bool(v),
Value::Number(v) => self.visit_number(v),
Value::String(v) => self.visit_string(v),
Value::Array(v) => self.visit_array(v),
Value::Object(v) => self.visit_object(v),
}
}
fn visit_null(&self) -> TypeRefValue {
RefValueWrapper::wrap(RefValue::Null)
}
fn visit_bool(&self, value: bool) -> TypeRefValue {
RefValueWrapper::wrap(RefValue::Bool(value))
}
fn visit_number(&self, value: serde_json::Number) -> TypeRefValue {
RefValueWrapper::wrap(RefValue::Number(value))
}
fn visit_string(&self, value: String) -> TypeRefValue {
RefValueWrapper::wrap(RefValue::String(value.to_string()))
}
fn visit_array(&self, value: Vec<Value>) -> TypeRefValue {
let mut values = Vec::new();
for v in value {
values.push(self.visit_value(v));
}
RefValueWrapper::wrap(RefValue::Array(values))
}
fn visit_object(&self, mut value: serde_json::Map<String, Value>) -> TypeRefValue {
let mut map = IndexMap::new();
let keys: Vec<String> = value.keys().into_iter().map(|k| k.to_string()).collect();
for k in keys {
let value = self.visit_value(match value.get_mut(&k) {
Some(v) => v.take(),
_ => Value::Null
});
map.insert(k, value);
}
RefValueWrapper::wrap(RefValue::Object(map))
}
}
struct ValueConverter;
impl ValueConverter {
fn new(value: &TypeRefValue) -> Value {
ValueConverter {}.visit_value(value)
}
fn visit_value(&self, value: &TypeRefValue) -> Value {
match &***value {
RefValue::Null => self.visit_null(),
RefValue::Bool(v) => self.visit_bool(v),
RefValue::Number(v) => self.visit_number(v),
RefValue::String(v) => self.visit_string(v),
RefValue::Array(v) => self.visit_array(v),
RefValue::Object(v) => self.visit_object(v),
}
}
fn visit_null(&self) -> Value {
Value::Null
}
fn visit_bool(&self, value: &bool) -> Value {
Value::Bool(*value)
}
fn visit_number(&self, value: &serde_json::Number) -> Value {
Value::Number(value.clone())
}
fn visit_string(&self, value: &String) -> Value {
Value::String(value.clone())
}
fn visit_array(&self, value: &Vec<TypeRefValue>) -> Value {
let mut values = Vec::new();
for v in value {
values.push(self.visit_value(v));
}
Value::Array(values)
}
fn visit_object(&self, map: &IndexMap<String, TypeRefValue>) -> Value {
let mut ret = serde_json::Map::new();
let keys: Vec<String> = map.keys().into_iter().map(|k: &String| k.to_string()).collect();
let tmp_null = &RefValueWrapper::wrap(RefValue::Null);
for k in keys {
let value = self.visit_value(match map.get(&k) {
Some(e) => e,
_ => tmp_null
});
ret.insert(k, value);
}
Value::Object(ret)
}
}