mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-06-22 20:31:37 +00:00
Stable 버전에서 컴파일 에러 수정
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate bencher;
|
||||
extern crate jsonpath_lib as jsonpath;
|
||||
extern crate serde;
|
||||
|
@ -76,7 +76,6 @@ pub struct Node {
|
||||
pub struct Parser;
|
||||
|
||||
impl Parser {
|
||||
|
||||
pub fn compile(input: &str) -> ParseResult<Node> {
|
||||
let mut tokenizer = TokenReader::new(input);
|
||||
Ok(Self::json_path(&mut tokenizer)?)
|
||||
@ -531,14 +530,22 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
|
||||
fn peek_key(tokenizer: &mut TokenReader) -> Option<String> {
|
||||
if let Ok(Token::Key(_, k)) = tokenizer.peek_token() {
|
||||
Some(k.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn term(tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||
debug!("#term");
|
||||
match tokenizer.peek_token() {
|
||||
Ok(Token::At(_)) => {
|
||||
|
||||
if tokenizer.peek_is(AT) {
|
||||
Self::eat_token(tokenizer);
|
||||
let node = Self::node(ParseToken::Relative);
|
||||
|
||||
match tokenizer.peek_token() {
|
||||
return match tokenizer.peek_token() {
|
||||
Ok(Token::Whitespace(_, _)) => {
|
||||
Self::eat_whitespace(tokenizer);
|
||||
Ok(node)
|
||||
@ -546,28 +553,31 @@ impl Parser {
|
||||
_ => {
|
||||
Self::paths(node, tokenizer)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if tokenizer.peek_is(ABSOLUTE) {
|
||||
return Self::json_path(tokenizer);
|
||||
}
|
||||
Ok(Token::Absolute(_)) => {
|
||||
Self::json_path(tokenizer)
|
||||
|
||||
if tokenizer.peek_is(DOUBLE_QUOTA) || tokenizer.peek_is(SINGLE_QUOTA) {
|
||||
return Self::array_quota_value(tokenizer);
|
||||
}
|
||||
Ok(Token::DoubleQuoted(_, _))
|
||||
| Ok(Token::SingleQuoted(_, _)) => {
|
||||
Self::array_quota_value(tokenizer)
|
||||
}
|
||||
Ok(Token::Key(_, k)) => {
|
||||
match k.chars().next() {
|
||||
|
||||
if tokenizer.peek_is(KEY) {
|
||||
return match Self::peek_key(tokenizer) {
|
||||
Some(key) => match key.chars().next() {
|
||||
Some(ch) => match ch {
|
||||
'-' | '0'...'9' => Self::term_num(tokenizer),
|
||||
_ => Self::boolean(tokenizer)
|
||||
}
|
||||
_ => Err(tokenizer.err_msg())
|
||||
},
|
||||
_ => Err(tokenizer.err_msg())
|
||||
};
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Err(tokenizer.err_msg())
|
||||
}
|
||||
}
|
||||
|
||||
return Err(tokenizer.err_msg());
|
||||
}
|
||||
|
||||
fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||
|
@ -3,29 +3,29 @@ use std::result::Result;
|
||||
|
||||
use super::path_reader::{PathReader, ReaderError};
|
||||
|
||||
const ABSOLUTE: &'static str = "$";
|
||||
const DOT: &'static str = ".";
|
||||
const AT: &'static str = "@";
|
||||
const OPEN_ARRAY: &'static str = "[";
|
||||
const CLOSE_ARRAY: &'static str = "]";
|
||||
const ASTERISK: &'static str = "*";
|
||||
const QUESTION: &'static str = "?";
|
||||
const COMMA: &'static str = ",";
|
||||
const SPLIT: &'static str = ":";
|
||||
const OPEN_PARENTHESIS: &'static str = "(";
|
||||
const CLOSE_PARENTHESIS: &'static str = ")";
|
||||
const KEY: &'static str = "Key";
|
||||
const DOUBLE_QUOTA: &'static str = "\"";
|
||||
const SINGLE_QUOTA: &'static str = "'";
|
||||
const EQUAL: &'static str = "==";
|
||||
const GREATER_OR_EQUAL: &'static str = ">=";
|
||||
const GREATER: &'static str = ">";
|
||||
const LITTLE: &'static str = "<";
|
||||
const LITTLE_OR_EQUAL: &'static str = "<=";
|
||||
const NOT_EQUAL: &'static str = "!=";
|
||||
const AND: &'static str = "&&";
|
||||
const OR: &'static str = "||";
|
||||
const WHITESPACE: &'static str = " ";
|
||||
pub const ABSOLUTE: &'static str = "$";
|
||||
pub const DOT: &'static str = ".";
|
||||
pub const AT: &'static str = "@";
|
||||
pub const OPEN_ARRAY: &'static str = "[";
|
||||
pub const CLOSE_ARRAY: &'static str = "]";
|
||||
pub const ASTERISK: &'static str = "*";
|
||||
pub const QUESTION: &'static str = "?";
|
||||
pub const COMMA: &'static str = ",";
|
||||
pub const SPLIT: &'static str = ":";
|
||||
pub const OPEN_PARENTHESIS: &'static str = "(";
|
||||
pub const CLOSE_PARENTHESIS: &'static str = ")";
|
||||
pub const KEY: &'static str = "Key";
|
||||
pub const DOUBLE_QUOTA: &'static str = "\"";
|
||||
pub const SINGLE_QUOTA: &'static str = "'";
|
||||
pub const EQUAL: &'static str = "==";
|
||||
pub const GREATER_OR_EQUAL: &'static str = ">=";
|
||||
pub const GREATER: &'static str = ">";
|
||||
pub const LITTLE: &'static str = "<";
|
||||
pub const LITTLE_OR_EQUAL: &'static str = "<=";
|
||||
pub const NOT_EQUAL: &'static str = "!=";
|
||||
pub const AND: &'static str = "&&";
|
||||
pub const OR: &'static str = "||";
|
||||
pub const WHITESPACE: &'static str = " ";
|
||||
|
||||
const CH_DOLLA: char = '$';
|
||||
const CH_DOT: char = '.';
|
||||
@ -91,6 +91,10 @@ impl Token {
|
||||
self.to_simple() == other.to_simple()
|
||||
}
|
||||
|
||||
pub fn simple_eq(&self, str_token: &str) -> bool {
|
||||
self.to_simple() == str_token
|
||||
}
|
||||
|
||||
fn to_simple(&self) -> &'static str {
|
||||
match self {
|
||||
Token::Absolute(_) => ABSOLUTE,
|
||||
@ -305,6 +309,13 @@ impl<'a> TokenReader<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek_is(&self, simple_token: &str) -> bool {
|
||||
match self.peek_token() {
|
||||
Ok(t) => t.simple_eq(simple_token),
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn peek_token(&self) -> Result<&Token, TokenError> {
|
||||
match self.tokens.last() {
|
||||
Some((_, t)) => {
|
||||
|
@ -1004,6 +1004,49 @@ pub struct SelectorMut {
|
||||
value: Option<Value>,
|
||||
}
|
||||
|
||||
fn replace_value<F: FnMut(&Value) -> Value>(tokens: Vec<String>, value: &mut Value, fun: &mut F) {
|
||||
let mut target = value;
|
||||
|
||||
for (i, token) in tokens.iter().enumerate() {
|
||||
let target_once = target;
|
||||
let is_last = i == tokens.len() - 1;
|
||||
let target_opt = match *target_once {
|
||||
Value::Object(ref mut map) => {
|
||||
if is_last {
|
||||
let v = if let Some(v) = map.get(token) {
|
||||
fun(v)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
map.insert(token.clone(), v);
|
||||
return;
|
||||
}
|
||||
map.get_mut(token)
|
||||
}
|
||||
Value::Array(ref mut vec) => {
|
||||
if let Ok(x) = token.parse::<usize>() {
|
||||
if is_last {
|
||||
let v = { fun(&vec[x]) };
|
||||
vec[x] = v;
|
||||
return;
|
||||
}
|
||||
vec.get_mut(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(t) = target_opt {
|
||||
target = t;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectorMut {
|
||||
pub fn new() -> Self {
|
||||
SelectorMut { path: None, value: None }
|
||||
@ -1014,11 +1057,6 @@ impl SelectorMut {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn compiled_path(&mut self, node: Node) -> &mut Self {
|
||||
self.path = Some(node);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(&mut self, value: Value) -> &mut Self {
|
||||
self.value = Some(value);
|
||||
self
|
||||
@ -1080,13 +1118,8 @@ impl SelectorMut {
|
||||
self.replace_with(&mut |_| Value::Null)
|
||||
}
|
||||
|
||||
pub fn replace_with<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
|
||||
if self.path.is_none() {
|
||||
return Err(JsonPathError::EmptyPath);
|
||||
}
|
||||
|
||||
let node = self.path.take().unwrap();
|
||||
|
||||
fn select(&self) -> Result<Vec<&Value>, JsonPathError> {
|
||||
if let Some(node) = &self.path {
|
||||
let mut selector = Selector::new();
|
||||
selector.compiled_path(&node);
|
||||
|
||||
@ -1094,62 +1127,24 @@ impl SelectorMut {
|
||||
selector.value(value);
|
||||
}
|
||||
|
||||
let result = selector.select();
|
||||
|
||||
self.path = Some(node);
|
||||
|
||||
let paths = self.compute_paths(result?);
|
||||
|
||||
if let Some(mut value) = self.value.take() {
|
||||
for tokens in paths {
|
||||
self.replace_value(tokens, &mut value, fun);
|
||||
Ok(selector.select()?)
|
||||
} else {
|
||||
Err(JsonPathError::EmptyPath)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn replace_with<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
|
||||
let paths = {
|
||||
let result = self.select()?;
|
||||
self.compute_paths(result)
|
||||
};
|
||||
|
||||
if let Some(ref mut value) = &mut self.value {
|
||||
for tokens in paths {
|
||||
replace_value(tokens, value, fun);
|
||||
}
|
||||
self.value = Some(value);
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn replace_value<F: FnMut(&Value) -> Value>(&mut self, tokens: Vec<String>, value: &mut Value, fun: &mut F) {
|
||||
let mut target = value;
|
||||
|
||||
for (i, token) in tokens.iter().enumerate() {
|
||||
let target_once = target;
|
||||
let is_last = i == tokens.len() - 1;
|
||||
let target_opt = match *target_once {
|
||||
Value::Object(ref mut map) => {
|
||||
if is_last {
|
||||
let v = if let Some(v) = map.get(token) {
|
||||
fun(v)
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
map.insert(token.clone(), v);
|
||||
return;
|
||||
}
|
||||
map.get_mut(token)
|
||||
}
|
||||
Value::Array(ref mut vec) => {
|
||||
if let Ok(x) = token.parse::<usize>() {
|
||||
if is_last {
|
||||
let v = &vec[x];
|
||||
vec[x] = fun(v);
|
||||
return;
|
||||
}
|
||||
vec.get_mut(x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(t) = target_opt {
|
||||
target = t;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -86,15 +86,18 @@ pub fn compile(path: &str) -> JsValue {
|
||||
let node = Parser::compile(path);
|
||||
|
||||
let cb = Closure::wrap(Box::new(move |js_value: JsValue| {
|
||||
let mut selector = _Selector::new();
|
||||
match &node {
|
||||
Ok(node) => selector.compiled_path(node),
|
||||
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone())))
|
||||
};
|
||||
let json = match into_serde_json(&js_value) {
|
||||
Ok(json) => json,
|
||||
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e)))
|
||||
};
|
||||
|
||||
let mut selector = _Selector::new();
|
||||
|
||||
match &node {
|
||||
Ok(node) => selector.compiled_path(node),
|
||||
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Path(e.clone())))
|
||||
};
|
||||
|
||||
match selector.value(&json).select() {
|
||||
Ok(ret) => match JsValue::from_serde(&ret) {
|
||||
Ok(ret) => ret,
|
||||
|
Reference in New Issue
Block a user