mirror of
https://github.com/fluencelabs/jsonpath
synced 2025-05-04 21:52:13 +00:00
Fix bug: eq, hash. Bump up 0.1.6
This commit is contained in:
parent
b24a8c18a9
commit
8e1a0f84e1
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jsonpath_lib"
|
name = "jsonpath_lib"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
authors = ["Changseok Han <freestrings@gmail.com>"]
|
authors = ["Changseok Han <freestrings@gmail.com>"]
|
||||||
|
|
||||||
description = "JsonPath in Rust and Webassembly - Webassembly Demo: https://freestrings.github.io/jsonpath"
|
description = "JsonPath in Rust and Webassembly - Webassembly Demo: https://freestrings.github.io/jsonpath"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jsonpath-rs"
|
name = "jsonpath-rs"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
authors = ["Changseok Han <freestrings@gmail.com>"]
|
authors = ["Changseok Han <freestrings@gmail.com>"]
|
||||||
description = "JsonPath engine for NodeJs with Rust native implementation."
|
description = "JsonPath engine for NodeJs with Rust native implementation."
|
||||||
keywords = ["library", "jsonpath", "json"]
|
keywords = ["library", "jsonpath", "json"]
|
||||||
|
@ -14,9 +14,11 @@ impl TermContext {
|
|||||||
TermContext::Constants(et) => {
|
TermContext::Constants(et) => {
|
||||||
match other {
|
match other {
|
||||||
TermContext::Constants(oet) => {
|
TermContext::Constants(oet) => {
|
||||||
|
trace!("const-const");
|
||||||
TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, default)))
|
TermContext::Constants(ExprTerm::Bool(et.cmp(oet, cmp_fn, default)))
|
||||||
}
|
}
|
||||||
TermContext::Json(key, v) => {
|
TermContext::Json(key, v) => {
|
||||||
|
trace!("const-json");
|
||||||
TermContext::Json(None, v.take_with(key, et, cmp_fn, true))
|
TermContext::Json(None, v.take_with(key, et, cmp_fn, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,6 +26,7 @@ impl TermContext {
|
|||||||
TermContext::Json(key, v) => {
|
TermContext::Json(key, v) => {
|
||||||
match other {
|
match other {
|
||||||
TermContext::Json(key_other, ov) => {
|
TermContext::Json(key_other, ov) => {
|
||||||
|
trace!("json-json");
|
||||||
|
|
||||||
fn is_json(t: &TermContext) -> bool {
|
fn is_json(t: &TermContext) -> bool {
|
||||||
match t {
|
match t {
|
||||||
@ -32,18 +35,16 @@ impl TermContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut v = v.filter(key);
|
|
||||||
let mut ov = ov.filter(key_other);
|
|
||||||
let mut c = v.into_term(key);
|
let mut c = v.into_term(key);
|
||||||
let mut oc = ov.into_term(key_other);
|
let mut oc = ov.into_term(key_other);
|
||||||
|
|
||||||
if is_json(&c) && is_json(&oc) {
|
if is_json(&c) && is_json(&oc) {
|
||||||
v.cmp(&mut ov, cmp_fn.into_type())
|
v.cmp(&ov, cmp_fn.into_type())
|
||||||
} else {
|
} else {
|
||||||
c.cmp(&mut oc, cmp_fn, default)
|
c.cmp(&mut oc, cmp_fn, default)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermContext::Constants(et) => {
|
TermContext::Constants(et) => {
|
||||||
|
trace!("json-const");
|
||||||
TermContext::Json(None, v.take_with(key, et, cmp_fn, false))
|
TermContext::Json(None, v.take_with(key, et, cmp_fn, false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,26 +88,32 @@ impl TermContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn eq(&self, other: &TermContext) -> TermContext {
|
pub fn eq(&self, other: &TermContext) -> TermContext {
|
||||||
|
trace!("eq");
|
||||||
self.cmp(other, CmpEq, false)
|
self.cmp(other, CmpEq, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ne(&self, other: &TermContext) -> TermContext {
|
pub fn ne(&self, other: &TermContext) -> TermContext {
|
||||||
|
trace!("ne");
|
||||||
self.cmp(other, CmpNe, true)
|
self.cmp(other, CmpNe, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gt(&self, other: &TermContext) -> TermContext {
|
pub fn gt(&self, other: &TermContext) -> TermContext {
|
||||||
|
trace!("gt");
|
||||||
self.cmp(other, CmpGt, false)
|
self.cmp(other, CmpGt, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ge(&self, other: &TermContext) -> TermContext {
|
pub fn ge(&self, other: &TermContext) -> TermContext {
|
||||||
|
trace!("ge");
|
||||||
self.cmp(other, CmpGe, false)
|
self.cmp(other, CmpGe, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lt(&self, other: &TermContext) -> TermContext {
|
pub fn lt(&self, other: &TermContext) -> TermContext {
|
||||||
|
trace!("lt");
|
||||||
self.cmp(other, CmpLt, false)
|
self.cmp(other, CmpLt, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn le(&self, other: &TermContext) -> TermContext {
|
pub fn le(&self, other: &TermContext) -> TermContext {
|
||||||
|
trace!("le");
|
||||||
self.cmp(other, CmpLe, false)
|
self.cmp(other, CmpLe, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::result::Result;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::result::Result;
|
||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
@ -324,6 +324,8 @@ impl JsonValueFilter {
|
|||||||
vf.vw.set_leaves(is_leaves);
|
vf.vw.set_leaves(is_leaves);
|
||||||
if v.is_null() {
|
if v.is_null() {
|
||||||
vf.vw.replace(v);
|
vf.vw.replace(v);
|
||||||
|
} else if v.is_array() && v.as_array().unwrap().is_empty() {
|
||||||
|
vf.vw.replace(RefValue::Null.into());
|
||||||
} else if vf.vw.is_array() {
|
} else if vf.vw.is_array() {
|
||||||
vf.vw.replace(v);
|
vf.vw.replace(v);
|
||||||
}
|
}
|
||||||
@ -480,6 +482,9 @@ impl JsonValueFilter {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(TermContext::Constants(ExprTerm::Bool(false))) => {
|
||||||
|
self.replace_filter_stack(RefValue::Null.into(), false);
|
||||||
|
}
|
||||||
Some(TermContext::Json(_, vw)) => {
|
Some(TermContext::Json(_, vw)) => {
|
||||||
self.replace_filter_stack(vw.get_val().clone(), vw.is_leaves());
|
self.replace_filter_stack(vw.get_val().clone(), vw.is_leaves());
|
||||||
}
|
}
|
||||||
|
@ -155,6 +155,7 @@ impl ValueWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn into_hashset(&self) -> IndexSet<RefValueWrapper> {
|
fn into_hashset(&self) -> IndexSet<RefValueWrapper> {
|
||||||
|
trace!("into_hashset");
|
||||||
let mut hashset = IndexSet::new();
|
let mut hashset = IndexSet::new();
|
||||||
match self.val.deref() {
|
match self.val.deref() {
|
||||||
RefValue::Array(ref v1) => {
|
RefValue::Array(ref v1) => {
|
||||||
@ -170,9 +171,10 @@ impl ValueWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn except(&self, other: &Self) -> Self {
|
pub fn except(&self, other: &Self) -> Self {
|
||||||
|
trace!("except");
|
||||||
let hashset = self.into_hashset();
|
let hashset = self.into_hashset();
|
||||||
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
|
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
|
||||||
match &(*other.val) {
|
match other.val.deref() {
|
||||||
RefValue::Array(ref v1) => {
|
RefValue::Array(ref v1) => {
|
||||||
for v in v1 {
|
for v in v1 {
|
||||||
if !hashset.contains(v) {
|
if !hashset.contains(v) {
|
||||||
@ -192,6 +194,7 @@ impl ValueWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn intersect(&self, other: &Self) -> Self {
|
pub fn intersect(&self, other: &Self) -> Self {
|
||||||
|
trace!("intersect");
|
||||||
let hashset = self.into_hashset();
|
let hashset = self.into_hashset();
|
||||||
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
|
let mut ret: IndexSet<RefValueWrapper> = IndexSet::new();
|
||||||
match other.val.deref() {
|
match other.val.deref() {
|
||||||
@ -214,6 +217,7 @@ impl ValueWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn union(&self, other: &Self) -> Self {
|
pub fn union(&self, other: &Self) -> Self {
|
||||||
|
trace!("union");
|
||||||
let mut hashset = self.into_hashset();
|
let mut hashset = self.into_hashset();
|
||||||
match other.val.deref() {
|
match other.val.deref() {
|
||||||
RefValue::Array(ref v1) => {
|
RefValue::Array(ref v1) => {
|
||||||
@ -249,6 +253,7 @@ impl ValueWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter(&self, key: &Option<ValueFilterKey>) -> Self {
|
pub fn filter(&self, key: &Option<ValueFilterKey>) -> Self {
|
||||||
|
trace!("filter");
|
||||||
let v = match self.val.deref() {
|
let v = match self.val.deref() {
|
||||||
RefValue::Array(ref vec) => {
|
RefValue::Array(ref vec) => {
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
|
@ -14,106 +14,118 @@ impl<'de> Deserialize<'de> for RefValue {
|
|||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct RefValueVisitor {}
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for RefValueVisitor {
|
||||||
|
type Value = RefValue;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
formatter.write_str("any valid JSON value")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: Error, {
|
||||||
|
Ok(RefValue::Bool(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
Ok(RefValue::Number(v.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
Ok(RefValue::Number(v.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
let n: Value = v.into();
|
||||||
|
if let Value::Number(n) = n {
|
||||||
|
Ok(RefValue::Number(n))
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
self.visit_string(String::from(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
Ok(RefValue::String(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
Ok(RefValue::Null)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> where
|
||||||
|
D: Deserializer<'de>, {
|
||||||
|
Deserialize::deserialize(deserializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error, {
|
||||||
|
Ok(RefValue::Null)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_seq<A>(self, mut visitor: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>, {
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
while let Some(elem) = visitor.next_element()? {
|
||||||
|
let e: RefValue = elem;
|
||||||
|
let v: RefValueWrapper = e.into();
|
||||||
|
vec.push(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RefValue::Array(vec))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn visit_map<A>(self, mut visitor: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: MapAccess<'de>, {
|
||||||
|
let mut values = IndexMap::new();
|
||||||
|
match visitor.next_key() {
|
||||||
|
Ok(Some(first_key)) => {
|
||||||
|
let next: RefValue = visitor.next_value()?;
|
||||||
|
values.insert(first_key, next.into());
|
||||||
|
while let Some((k, v)) = visitor.next_entry()? {
|
||||||
|
let value: RefValue = v;
|
||||||
|
values.insert(k, value.into());
|
||||||
|
}
|
||||||
|
Ok(RefValue::Object(values))
|
||||||
|
}
|
||||||
|
_ => Ok(RefValue::Object(IndexMap::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deserializer.deserialize_any(RefValueVisitor {})
|
deserializer.deserialize_any(RefValueVisitor {})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct RefValueVisitor {}
|
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for RefValueVisitor {
|
|
||||||
type Value = RefValue;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
formatter.write_str("any valid JSON value")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: Error, {
|
|
||||||
Ok(RefValue::Bool(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
Ok(RefValue::Number(v.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
Ok(RefValue::Number(v.into()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
let n: Value = v.into();
|
|
||||||
if let Value::Number(n) = n {
|
|
||||||
Ok(RefValue::Number(n))
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
self.visit_string(String::from(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
Ok(RefValue::String(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
Ok(RefValue::Null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error> where
|
|
||||||
D: Deserializer<'de>, {
|
|
||||||
Deserialize::deserialize(deserializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: serde::de::Error, {
|
|
||||||
Ok(RefValue::Null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_seq<A>(self, mut visitor: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: SeqAccess<'de>, {
|
|
||||||
let mut vec = Vec::new();
|
|
||||||
|
|
||||||
while let Some(elem) = visitor.next_element()? {
|
|
||||||
let e: RefValue = elem;
|
|
||||||
let v: RefValueWrapper = e.into();
|
|
||||||
vec.push(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(RefValue::Array(vec))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<A>(self, mut visitor: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: MapAccess<'de>, {
|
|
||||||
let mut values = IndexMap::new();
|
|
||||||
match visitor.next_key() {
|
|
||||||
Ok(Some(first_key)) => {
|
|
||||||
let next: RefValue = visitor.next_value()?;
|
|
||||||
values.insert(first_key, next.into());
|
|
||||||
while let Some((k, v)) = visitor.next_entry()? {
|
|
||||||
let value: RefValue = v;
|
|
||||||
values.insert(k, value.into());
|
|
||||||
}
|
|
||||||
Ok(RefValue::Object(values))
|
|
||||||
}
|
|
||||||
_ => Ok(RefValue::Object(IndexMap::new())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -124,11 +124,17 @@ pub enum RefValue {
|
|||||||
Object(IndexMap<String, RefValueWrapper>),
|
Object(IndexMap<String, RefValueWrapper>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static REF_VALUE_NULL: &'static str = "$jsonpath::ref_value::model::RefValue::Null";
|
||||||
|
|
||||||
impl Hash for RefValue {
|
impl Hash for RefValue {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
match self {
|
match self {
|
||||||
RefValue::Null => RefValue::Null.hash(state),
|
RefValue::Null => {
|
||||||
RefValue::Bool(b) => b.hash(state),
|
REF_VALUE_NULL.hash(state)
|
||||||
|
},
|
||||||
|
RefValue::Bool(b) => {
|
||||||
|
b.hash(state)
|
||||||
|
},
|
||||||
RefValue::Number(n) => {
|
RefValue::Number(n) => {
|
||||||
if n.is_f64() {
|
if n.is_f64() {
|
||||||
n.as_f64().unwrap().to_string().hash(state)
|
n.as_f64().unwrap().to_string().hash(state)
|
||||||
@ -138,7 +144,9 @@ impl Hash for RefValue {
|
|||||||
n.as_u64().unwrap().hash(state);
|
n.as_u64().unwrap().hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RefValue::String(s) => s.hash(state),
|
RefValue::String(s) => {
|
||||||
|
s.hash(state)
|
||||||
|
},
|
||||||
RefValue::Object(map) => {
|
RefValue::Object(map) => {
|
||||||
for (_, v) in map {
|
for (_, v) in map {
|
||||||
v.hash(state);
|
v.hash(state);
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
// Copyright 2017 Serde Developers
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
const TAG_CONT: u8 = 0b1000_0000;
|
|
||||||
const TAG_TWO_B: u8 = 0b1100_0000;
|
|
||||||
const TAG_THREE_B: u8 = 0b1110_0000;
|
|
||||||
const TAG_FOUR_B: u8 = 0b1111_0000;
|
|
||||||
const MAX_ONE_B: u32 = 0x80;
|
|
||||||
const MAX_TWO_B: u32 = 0x800;
|
|
||||||
const MAX_THREE_B: u32 = 0x10000;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn encode(c: char) -> Encode {
|
|
||||||
let code = c as u32;
|
|
||||||
let mut buf = [0; 4];
|
|
||||||
let pos = if code < MAX_ONE_B {
|
|
||||||
buf[3] = code as u8;
|
|
||||||
3
|
|
||||||
} else if code < MAX_TWO_B {
|
|
||||||
buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
|
|
||||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
|
||||||
2
|
|
||||||
} else if code < MAX_THREE_B {
|
|
||||||
buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
|
|
||||||
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
|
||||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
|
|
||||||
buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
|
|
||||||
buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
|
|
||||||
buf[3] = (code & 0x3F) as u8 | TAG_CONT;
|
|
||||||
0
|
|
||||||
};
|
|
||||||
Encode { buf: buf, pos: pos }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Encode {
|
|
||||||
buf: [u8; 4],
|
|
||||||
pos: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Encode {
|
|
||||||
pub fn as_str(&self) -> &str {
|
|
||||||
std::str::from_utf8(&self.buf[self.pos..]).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
@ -154,17 +154,17 @@ fn return_type() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn op() {
|
fn op_default() {
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
let jf = do_filter("$.school[?(@.friends == @.friends)]", "./benches/data_obj.json");
|
let jf = do_filter("$.school[?(@.friends == @.friends)]", "./benches/data_obj.json");
|
||||||
let friends = json!({
|
let friends = json!({
|
||||||
"friends": [
|
"friends": [
|
||||||
{"id": 0, "name": "Millicent Norman"},
|
{"id": 0, "name": "Millicent Norman"},
|
||||||
{"id": 1, "name": "Vincent Cannon" },
|
{"id": 1, "name": "Vincent Cannon" },
|
||||||
{"id": 2, "name": "Gray Berry"}
|
{"id": 2, "name": "Gray Berry"}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
assert_eq!(friends, jf.into_value());
|
assert_eq!(friends, jf.into_value());
|
||||||
|
|
||||||
let jf = do_filter("$.friends[?(@.name)]", "./benches/data_obj.json");
|
let jf = do_filter("$.friends[?(@.name)]", "./benches/data_obj.json");
|
||||||
@ -203,6 +203,81 @@ fn op() {
|
|||||||
assert_eq!(friends, jf.into_value());
|
assert_eq!(friends, jf.into_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn op_number() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let json = json!({ "a": 1 });
|
||||||
|
let ret = jsonpath::select(&json, "$.[?(@.a == 1)]").unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
let ret = jsonpath::select(&json, "$.[?(@.a != 2)]").unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
let ret = jsonpath::select(&json, "$.[?(@.a < 2)]").unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
let ret = jsonpath::select(&json, "$.[?(@.a <= 1)]").unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
let ret = jsonpath::select(&json, "$.[?(@.a > 0)]").unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
let ret = jsonpath::select(&json, "$.[?(@.a >= 0)]").unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn op_string() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let json = json!({ "a": "b" });
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a == "b")]"#).unwrap();
|
||||||
|
assert_eq!(json!({ "a": "b" }), ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a != "c")]"#).unwrap();
|
||||||
|
assert_eq!(json!({ "a": "b" }), ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a < "b")]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a <= "b")]"#).unwrap();
|
||||||
|
assert_eq!(json!({ "a": "b" }), ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a > "b")]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a >= "b")]"#).unwrap();
|
||||||
|
assert_eq!(json!({ "a": "b" }), ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn op_object() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let json = json!({
|
||||||
|
"a": { "1": 1 },
|
||||||
|
"b": { "2": 2 },
|
||||||
|
"c": { "1": 1 },
|
||||||
|
});
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a == @.c)]"#).unwrap();
|
||||||
|
assert_eq!(json, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a != @.c)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a < @.c)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a <= @.c)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a > @.c)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a >= @.c)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn op_complex() {
|
||||||
|
setup();
|
||||||
|
|
||||||
|
let json = json!({ "a": { "b": 1 } });
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(1 == @.a)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?("1" != @.a)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a <= 1)]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
let ret = jsonpath::select(&json, r#"$.[?(@.a > "1")]"#).unwrap();
|
||||||
|
assert_eq!(Value::Null, ret);
|
||||||
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn example() {
|
fn example() {
|
||||||
setup();
|
setup();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "jsonpath-wasm"
|
name = "jsonpath-wasm"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
authors = ["Changseok Han <freestrings@gmail.com>"]
|
authors = ["Changseok Han <freestrings@gmail.com>"]
|
||||||
description = "JsonPath Webassembly version compiled by Rust - Demo: https://freestrings.github.io/jsonpath"
|
description = "JsonPath Webassembly version compiled by Rust - Demo: https://freestrings.github.io/jsonpath"
|
||||||
keywords = ["library", "jsonpath", "json", "webassembly"]
|
keywords = ["library", "jsonpath", "json", "webassembly"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user