mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-06-23 04:41:38 +00:00
Stable 버전에서 컴파일 에러 수정
This commit is contained in:
@ -1,5 +1,4 @@
|
|||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
|
|
||||||
extern crate bencher;
|
extern crate bencher;
|
||||||
extern crate jsonpath_lib as jsonpath;
|
extern crate jsonpath_lib as jsonpath;
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
@ -76,7 +76,6 @@ pub struct Node {
|
|||||||
pub struct Parser;
|
pub struct Parser;
|
||||||
|
|
||||||
impl Parser {
|
impl Parser {
|
||||||
|
|
||||||
pub fn compile(input: &str) -> ParseResult<Node> {
|
pub fn compile(input: &str) -> ParseResult<Node> {
|
||||||
let mut tokenizer = TokenReader::new(input);
|
let mut tokenizer = TokenReader::new(input);
|
||||||
Ok(Self::json_path(&mut tokenizer)?)
|
Ok(Self::json_path(&mut tokenizer)?)
|
||||||
@ -531,43 +530,54 @@ 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> {
|
fn term(tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||||
debug!("#term");
|
debug!("#term");
|
||||||
match tokenizer.peek_token() {
|
|
||||||
Ok(Token::At(_)) => {
|
|
||||||
Self::eat_token(tokenizer);
|
|
||||||
let node = Self::node(ParseToken::Relative);
|
|
||||||
|
|
||||||
match tokenizer.peek_token() {
|
if tokenizer.peek_is(AT) {
|
||||||
Ok(Token::Whitespace(_, _)) => {
|
Self::eat_token(tokenizer);
|
||||||
Self::eat_whitespace(tokenizer);
|
let node = Self::node(ParseToken::Relative);
|
||||||
Ok(node)
|
|
||||||
}
|
return match tokenizer.peek_token() {
|
||||||
_ => {
|
Ok(Token::Whitespace(_, _)) => {
|
||||||
Self::paths(node, tokenizer)
|
Self::eat_whitespace(tokenizer);
|
||||||
}
|
Ok(node)
|
||||||
}
|
}
|
||||||
}
|
_ => {
|
||||||
Ok(Token::Absolute(_)) => {
|
Self::paths(node, tokenizer)
|
||||||
Self::json_path(tokenizer)
|
}
|
||||||
}
|
};
|
||||||
Ok(Token::DoubleQuoted(_, _))
|
}
|
||||||
| Ok(Token::SingleQuoted(_, _)) => {
|
|
||||||
Self::array_quota_value(tokenizer)
|
if tokenizer.peek_is(ABSOLUTE) {
|
||||||
}
|
return Self::json_path(tokenizer);
|
||||||
Ok(Token::Key(_, k)) => {
|
}
|
||||||
match k.chars().next() {
|
|
||||||
|
if tokenizer.peek_is(DOUBLE_QUOTA) || tokenizer.peek_is(SINGLE_QUOTA) {
|
||||||
|
return Self::array_quota_value(tokenizer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if tokenizer.peek_is(KEY) {
|
||||||
|
return match Self::peek_key(tokenizer) {
|
||||||
|
Some(key) => match key.chars().next() {
|
||||||
Some(ch) => match ch {
|
Some(ch) => match ch {
|
||||||
'-' | '0'...'9' => Self::term_num(tokenizer),
|
'-' | '0'...'9' => Self::term_num(tokenizer),
|
||||||
_ => Self::boolean(tokenizer)
|
_ => Self::boolean(tokenizer)
|
||||||
}
|
}
|
||||||
_ => Err(tokenizer.err_msg())
|
_ => 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> {
|
fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult<Node> {
|
||||||
|
@ -3,29 +3,29 @@ use std::result::Result;
|
|||||||
|
|
||||||
use super::path_reader::{PathReader, ReaderError};
|
use super::path_reader::{PathReader, ReaderError};
|
||||||
|
|
||||||
const ABSOLUTE: &'static str = "$";
|
pub const ABSOLUTE: &'static str = "$";
|
||||||
const DOT: &'static str = ".";
|
pub const DOT: &'static str = ".";
|
||||||
const AT: &'static str = "@";
|
pub const AT: &'static str = "@";
|
||||||
const OPEN_ARRAY: &'static str = "[";
|
pub const OPEN_ARRAY: &'static str = "[";
|
||||||
const CLOSE_ARRAY: &'static str = "]";
|
pub const CLOSE_ARRAY: &'static str = "]";
|
||||||
const ASTERISK: &'static str = "*";
|
pub const ASTERISK: &'static str = "*";
|
||||||
const QUESTION: &'static str = "?";
|
pub const QUESTION: &'static str = "?";
|
||||||
const COMMA: &'static str = ",";
|
pub const COMMA: &'static str = ",";
|
||||||
const SPLIT: &'static str = ":";
|
pub const SPLIT: &'static str = ":";
|
||||||
const OPEN_PARENTHESIS: &'static str = "(";
|
pub const OPEN_PARENTHESIS: &'static str = "(";
|
||||||
const CLOSE_PARENTHESIS: &'static str = ")";
|
pub const CLOSE_PARENTHESIS: &'static str = ")";
|
||||||
const KEY: &'static str = "Key";
|
pub const KEY: &'static str = "Key";
|
||||||
const DOUBLE_QUOTA: &'static str = "\"";
|
pub const DOUBLE_QUOTA: &'static str = "\"";
|
||||||
const SINGLE_QUOTA: &'static str = "'";
|
pub const SINGLE_QUOTA: &'static str = "'";
|
||||||
const EQUAL: &'static str = "==";
|
pub const EQUAL: &'static str = "==";
|
||||||
const GREATER_OR_EQUAL: &'static str = ">=";
|
pub const GREATER_OR_EQUAL: &'static str = ">=";
|
||||||
const GREATER: &'static str = ">";
|
pub const GREATER: &'static str = ">";
|
||||||
const LITTLE: &'static str = "<";
|
pub const LITTLE: &'static str = "<";
|
||||||
const LITTLE_OR_EQUAL: &'static str = "<=";
|
pub const LITTLE_OR_EQUAL: &'static str = "<=";
|
||||||
const NOT_EQUAL: &'static str = "!=";
|
pub const NOT_EQUAL: &'static str = "!=";
|
||||||
const AND: &'static str = "&&";
|
pub const AND: &'static str = "&&";
|
||||||
const OR: &'static str = "||";
|
pub const OR: &'static str = "||";
|
||||||
const WHITESPACE: &'static str = " ";
|
pub const WHITESPACE: &'static str = " ";
|
||||||
|
|
||||||
const CH_DOLLA: char = '$';
|
const CH_DOLLA: char = '$';
|
||||||
const CH_DOT: char = '.';
|
const CH_DOT: char = '.';
|
||||||
@ -91,6 +91,10 @@ impl Token {
|
|||||||
self.to_simple() == other.to_simple()
|
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 {
|
fn to_simple(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Token::Absolute(_) => ABSOLUTE,
|
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> {
|
pub fn peek_token(&self) -> Result<&Token, TokenError> {
|
||||||
match self.tokens.last() {
|
match self.tokens.last() {
|
||||||
Some((_, t)) => {
|
Some((_, t)) => {
|
||||||
|
@ -1004,6 +1004,49 @@ pub struct SelectorMut {
|
|||||||
value: Option<Value>,
|
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 {
|
impl SelectorMut {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
SelectorMut { path: None, value: None }
|
SelectorMut { path: None, value: None }
|
||||||
@ -1014,11 +1057,6 @@ impl SelectorMut {
|
|||||||
Ok(self)
|
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 {
|
pub fn value(&mut self, value: Value) -> &mut Self {
|
||||||
self.value = Some(value);
|
self.value = Some(value);
|
||||||
self
|
self
|
||||||
@ -1080,76 +1118,33 @@ impl SelectorMut {
|
|||||||
self.replace_with(&mut |_| Value::Null)
|
self.replace_with(&mut |_| Value::Null)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_with<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
|
fn select(&self) -> Result<Vec<&Value>, JsonPathError> {
|
||||||
if self.path.is_none() {
|
if let Some(node) = &self.path {
|
||||||
return Err(JsonPathError::EmptyPath);
|
let mut selector = Selector::new();
|
||||||
}
|
selector.compiled_path(&node);
|
||||||
|
|
||||||
let node = self.path.take().unwrap();
|
if let Some(value) = &self.value {
|
||||||
|
selector.value(value);
|
||||||
let mut selector = Selector::new();
|
}
|
||||||
selector.compiled_path(&node);
|
|
||||||
|
Ok(selector.select()?)
|
||||||
if let Some(value) = &self.value {
|
} else {
|
||||||
selector.value(value);
|
Err(JsonPathError::EmptyPath)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let result = selector.select();
|
|
||||||
|
pub fn replace_with<F: FnMut(&Value) -> Value>(&mut self, fun: &mut F) -> Result<&mut Self, JsonPathError> {
|
||||||
self.path = Some(node);
|
let paths = {
|
||||||
|
let result = self.select()?;
|
||||||
let paths = self.compute_paths(result?);
|
self.compute_paths(result)
|
||||||
|
};
|
||||||
if let Some(mut value) = self.value.take() {
|
|
||||||
for tokens in paths {
|
if let Some(ref mut value) = &mut self.value {
|
||||||
self.replace_value(tokens, &mut value, fun);
|
for tokens in paths {
|
||||||
|
replace_value(tokens, value, fun);
|
||||||
}
|
}
|
||||||
self.value = Some(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(self)
|
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 node = Parser::compile(path);
|
||||||
|
|
||||||
let cb = Closure::wrap(Box::new(move |js_value: JsValue| {
|
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) {
|
let json = match into_serde_json(&js_value) {
|
||||||
Ok(json) => json,
|
Ok(json) => json,
|
||||||
Err(e) => return JsValue::from_str(&format!("{:?}", JsonPathError::Serde(e)))
|
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() {
|
match selector.value(&json).select() {
|
||||||
Ok(ret) => match JsValue::from_serde(&ret) {
|
Ok(ret) => match JsValue::from_serde(&ret) {
|
||||||
Ok(ret) => ret,
|
Ok(ret) => ret,
|
||||||
|
Reference in New Issue
Block a user