Javascript Selector 유닛테스트 완료

This commit is contained in:
freestrings 2019-04-09 18:43:56 +09:00
parent d263e30c91
commit 1c3656460e
17 changed files with 552 additions and 303 deletions

604
README.md
View File

@ -16,21 +16,9 @@ It is an implementation for [JsonPath](https://goessner.net/articles/JsonPath/)
To enjoy Rust!
## API
## Rust API
[With Javascript](#with-javascript)
- [jsonpath-wasm library](#jsonpath-wasm-library)
- [jsonpath-rs library](#jsonpath-rs-library-only-nodejs)
- [Javascript - jsonpath.select(json: string|object, jsonpath: string)](#javascript---jsonpathselectjson-stringobject-jsonpath-string)
- [Javascript - jsonpath.compile(jsonpath: string)](#javascript---jsonpathcompilejsonpath-string)
- [Javascript - jsonpath.selector(json: string|object)](#javascript---jsonpathselectorjson-stringobject)
- [Javascript - alloc_json, dealloc_json](#javascript---alloc_json-dealloc_json)
- [Javascript-wasm - examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples)
[With Rust](#with-rust)
- [jsonpath_lib library](#jsonpath_lib-library)
- [jsonpath_lib crate](#jsonpath_lib-crate)
- [Rust - jsonpath::Selector struct](#rust---jsonpathselector-struct)
- [Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)](#rust---jsonpathselectjson-serde_jsonvaluevalue-jsonpath-str)
- [Rust - jsonpath::select_as_str(json_str: &str, jsonpath: &str)](#rust---jsonpathselect_as_strjson-str-jsonpath-str)
@ -40,15 +28,262 @@ To enjoy Rust!
- [Rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value)](#rust---jsonpathselector_ast-serdededeserializeownedjson-serde_jsonvaluevalue)
- [Rust - examples](https://github.com/freestrings/jsonpath/wiki/rust-examples)
[Simple time check - webassembly](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck---jsonpath-wasm)
## Javascript API
[Simple time check - native addon for NodeJs](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck-jsonpath-native)
- [npm package](#npm-package)
- [Javascript - jsonpath.Selector class](#javascript---selector-class)
- [Javascript - jsonpath.select(json: string|object, jsonpath: string)](#javascript---jsonpathselectjson-stringobject-jsonpath-string)
- [Javascript - jsonpath.compile(jsonpath: string)](#javascript---jsonpathcompilejsonpath-string)
- [Javascript - jsonpath.selector(json: string|object)](#javascript---jsonpathselectorjson-stringobject)
- [Javascript - allocJson, deallocJson (Webassembly Only)](#javascript---allocjson-deallocjson-webassembly-only)
- [Javascript - examples](https://github.com/freestrings/jsonpath/wiki/Javascript-examples)
## With Javascript
## Simple time check
- [jsonpath-wasm](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck---jsonpath-wasm)
- [jsonpath-rs](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck-jsonpath-native)
### jsonpath-wasm library
---
### Rust API
#### jsonpath_lib crate
[Go to creates.io](https://crates.io/crates/jsonpath_lib)
```rust
extern crate jsonpath_lib as jsonpath;
#[macro_use]
extern crate serde_json;
```
#### Rust - jsonpath::Selector struct
```rust
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Friend {
name: String,
age: Option<u8>,
}
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector = Selector::new();
let result = selector
.path("$..[?(@.age >= 30)]").unwrap()
// .value_from_str(&serde_json::to_string(&json_obj).unwrap() /*&str*/).unwrap()
// .value_from(&json_obj /*&impl serde::ser::Serialize*/).unwrap()
.value((&json_obj /*serde_json::value::Value*/ ).into()).unwrap()
.select_to_value().unwrap();
assert_eq!(json!([{"name": "친구3", "age": 30}]), result);
let result = selector.select_to_str().unwrap();
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
let result = selector.select_to::<Vec<Friend>>().unwrap();
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
```
#### Rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
```
#### Rust - jsonpath::select_as_str(json: &str, jsonpath: &str)
```rust
let ret = jsonpath::select_as_str(r#"
{
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
}
"#, "$..friends[0]").unwrap();
assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
```
#### Rust - jsonpath::select_as\<T: `serde::de::DeserializeOwned`\>(json: &str, jsonpath: &str)
```rust
#[derive(Deserialize, PartialEq, Debug)]
struct Person {
name: String,
age: u8,
phones: Vec<String>,
}
let ret: Person = jsonpath::select_as(r#"
{
"person":
{
"name": "Doe John",
"age": 44,
"phones": [
"+44 1234567",
"+44 2345678"
]
}
}
"#, "$.person").unwrap();
let person = Person {
name: "Doe John".to_string(),
age: 44,
phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
};
assert_eq!(person, ret);
```
#### Rust - jsonpath::compile(jsonpath: &str)
```rust
let mut template = jsonpath::compile("$..friends[0]");
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let json = template(&json_obj).unwrap();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
```
#### Rust - jsonpath::selector(json: &serde_json::value::Value)
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector = jsonpath::selector(&json_obj);
let json = selector("$..friends[0]").unwrap();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
let json = selector("$..friends[1]").unwrap();
let ret = json!([
{"name": "친구4"},
{"name": "친구2", "age": 20}
]);
assert_eq!(json, ret);
```
#### Rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value)
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Friend {
name: String,
age: Option<u8>,
}
let mut selector = jsonpath::selector_as::<Vec<Friend>>(&json_obj);
let json = selector("$..friends[0]").unwrap();
let ret = vec!(
Friend { name: "친구3".to_string(), age: Some(30) },
Friend { name: "친구1".to_string(), age: Some(20) }
);
assert_eq!(json, ret);
let json = selector("$..friends[1]").unwrap();
let ret = vec!(
Friend { name: "친구4".to_string(), age: None },
Friend { name: "친구2".to_string(), age: Some(20) }
);
assert_eq!(json, ret);
```
---
### Javascript API
#### npm package
##### jsonpath-wasm (Not yet published)
*(not yet published `jsonpath-wasm`)*
```javascript
// browser
import * as jsonpath from "jsonpath-wasm";
@ -56,15 +291,92 @@ import * as jsonpath from "jsonpath-wasm";
const jsonpath = require('jsonpath-wasm');
```
### jsonpath-rs library (Only NodeJS)
##### jsonpath-rs (NodeJS only)
`jsonpath-rs` is native addon for NodeJs
[Goto npmjs.org](https://www.npmjs.com/package/jsonpath-rs)
```javascript
const jsonpath = require('jsonpath-rs');
```
### Javascript - jsonpath.select(json: string|object, jsonpath: string)
#### javascript - Selector class
##### jsonpath-wasm
`wasm-bindgen` 리턴타입 제약 때문에 빌더 패턴은 지원하지 않는다.
It does not support `builder-pattern` due to the `return type` restriction of `wasm-bindgen`.
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let selector = new jsonpath.Selector();
selector.path('$..friends[0]');
selector.value(jsonObj);
let selectToObj = selector.selectTo();
let selectToString = selector.selectToStr();
console.log(
JSON.stringify(ret) == JSON.stringify(selectToObj),
JSON.stringify(ret) == selectToString
);
// => true, true
```
##### jsonpath-rs
```javascript
let jsonObj = {
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
};
let ret = [
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
];
let selector = new jsonpath.Selector()
.path('$..friends[0]')
.value(jsonObj);
let selectToObj = selector.selectTo();
let selectToString = selector.selectToStr();
console.log(
JSON.stringify(ret) == JSON.stringify(selectToObj),
JSON.stringify(ret) == selectToString
);
// => true, true
```
#### Javascript - jsonpath.select(json: string|object, jsonpath: string)
```javascript
let jsonObj = {
@ -97,7 +409,7 @@ console.log(
// => true, true
```
### Javascript - jsonpath.compile(jsonpath: string)
#### Javascript - jsonpath.compile(jsonpath: string)
```javascript
let template = jsonpath.compile('$..friends[0]');
@ -156,7 +468,7 @@ console.log(
// => true, true
```
### Javascript - jsonpath.selector(json: string|object)
#### Javascript - jsonpath.selector(json: string|object)
```javascript
let jsonObj = {
@ -197,13 +509,10 @@ console.log(
// => true, true
```
### Javascript - alloc_json, dealloc_json
#### Javascript - allocJson, deallocJson (Webassembly Only)
wasm-bindgen은 Javascript와 Webassembly간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체는 Webassembly 영역에 생성해 두면 성능에 도움이 된다.
*(not supported in `jsonpath-rs`)*
wasm-bindgen은 Javascript와 Webassembly 간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체를 Webassembly 영역에 생성해 두면 성능에 도움이 된다.
Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, it is helpful to create repeated Json objects in Webassembly area.
Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, creating frequently used JSON objects in the WebAssembly area helps performance.
```javascript
const jsonpath = require('@nodejs/jsonpath-wasm');
@ -222,7 +531,7 @@ let jsonObj = {
};
// allocate jsonObj in webassembly
let ptr = jsonpath.alloc_json(jsonObj);
let ptr = jsonpath.allocJson(jsonObj);
// `0` is invalid pointer
if(ptr == 0) {
@ -253,236 +562,5 @@ console.log(
// => true true true true true
jsonpath.dealloc_json(ptr);
jsonpath.deallocJson(ptr);
```
## With Rust
### jsonpath_lib library
```rust
extern crate jsonpath_lib as jsonpath;
#[macro_use]
extern crate serde_json;
```
### Rust - jsonpath::Selector struct
```rust
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Friend {
name: String,
age: Option<u8>,
}
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector = Selector::new();
let result = selector
.path("$..[?(@.age >= 30)]").unwrap()
// .value_from_str(&serde_json::to_string(&json_obj).unwrap() /*&str*/).unwrap()
// .value_from(&json_obj /*&impl serde::ser::Serialize*/).unwrap()
.value((&json_obj /*serde_json::value::Value*/ ).into()).unwrap()
.select_to_value().unwrap();
assert_eq!(json!([{"name": "친구3", "age": 30}]), result);
let result = selector.select_to_str().unwrap();
assert_eq!(r#"[{"name":"친구3","age":30}]"#, result);
let result = selector.select_to::<Vec<Friend>>().unwrap();
assert_eq!(vec![Friend { name: "친구3".to_string(), age: Some(30) }], result);
```
### rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let json = jsonpath::select(&json_obj, "$..friends[0]").unwrap();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
```
### Rust - jsonpath::select_as_str(json: &str, jsonpath: &str)
```rust
let ret = jsonpath::select_as_str(r#"
{
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]
}
"#, "$..friends[0]").unwrap();
assert_eq!(ret, r#"[{"name":"친구3","age":30},{"name":"친구1","age":20}]"#);
```
### Rust - jsonpath::select_as\<T: `serde::de::DeserializeOwned`\>(json: &str, jsonpath: &str)
```rust
#[derive(Deserialize, PartialEq, Debug)]
struct Person {
name: String,
age: u8,
phones: Vec<String>,
}
let ret: Person = jsonpath::select_as(r#"
{
"person":
{
"name": "Doe John",
"age": 44,
"phones": [
"+44 1234567",
"+44 2345678"
]
}
}
"#, "$.person").unwrap();
let person = Person {
name: "Doe John".to_string(),
age: 44,
phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()],
};
assert_eq!(person, ret);
```
### Rust - jsonpath::compile(jsonpath: &str)
```rust
let mut template = jsonpath::compile("$..friends[0]");
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let json = template(&json_obj).unwrap();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
```
### Rust - jsonpath::selector(json: &serde_json::value::Value)
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
let mut selector = jsonpath::selector(&json_obj);
let json = selector("$..friends[0]").unwrap();
let ret = json!([
{"name": "친구3", "age": 30},
{"name": "친구1", "age": 20}
]);
assert_eq!(json, ret);
let json = selector("$..friends[1]").unwrap();
let ret = json!([
{"name": "친구4"},
{"name": "친구2", "age": 20}
]);
assert_eq!(json, ret);
```
### Rust - jsonpath::selector_as\<T: `serde::de::DeserializeOwned`\>(json: &serde_json::value::Value)
```rust
let json_obj = json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]});
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Friend {
name: String,
age: Option<u8>,
}
let mut selector = jsonpath::selector_as::<Vec<Friend>>(&json_obj);
let json = selector("$..friends[0]").unwrap();
let ret = vec!(
Friend { name: "친구3".to_string(), age: Some(30) },
Friend { name: "친구1".to_string(), age: Some(20) }
);
assert_eq!(json, ret);
let json = selector("$..friends[1]").unwrap();
let ret = vec!(
Friend { name: "친구4".to_string(), age: None },
Friend { name: "친구2".to_string(), age: Some(20) }
);
assert_eq!(json, ret);
```

View File

@ -37,6 +37,8 @@ __extra () {
printf "\n"
sleep 1
cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - compile-alloc: " && time ./bench.sh wasmCompileAlloc ${ITER}
sleep 1
cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm - Selector: " && time ./bench.sh wasmSelectorClass ${ITER}
}
if [ "$1" = "extra" ]; then

View File

@ -86,7 +86,7 @@ function wasmCompile() {
}
function wasmCompileAlloc() {
let ptr = jpw.alloc_json(getJson());
let ptr = jpw.allocJson(getJson());
if (ptr == 0) {
console.error('Invalid pointer');
return;
@ -98,7 +98,7 @@ function wasmCompileAlloc() {
let _ = template(ptr);
}
} finally {
jpw.dealloc_json(ptr);
jpw.deallocJson(ptr);
}
}
@ -109,7 +109,7 @@ function wasmSelect() {
}
function wasmSelectAlloc() {
let ptr = jpw.alloc_json(getJson());
let ptr = jpw.allocJson(getJson());
if (ptr == 0) {
console.error('Invalid pointer');
return;
@ -120,7 +120,16 @@ function wasmSelectAlloc() {
let _ = jpw.select(ptr, path);
}
} finally {
jpw.dealloc_json(ptr);
jpw.deallocJson(ptr);
}
}
function wasmSelectorClass() {
let selector = new jpw.Selector();
for (var i = 0; i < iter; i++) {
selector.path(path);
selector.value(jsonStr);
let _ = selector.selectToStr();
}
}

View File

@ -54,11 +54,11 @@ echo
echo
__msg "wasm-pack"
cd "${WASM}" && \
wasm-pack build --target=nodejs --scope nodejs --out-dir nodejs_pkg && \
wasm-pack build --release --target=nodejs --scope nodejs --out-dir nodejs_pkg && \
cd "${WASM_NODEJS_PKG}" && npm link
cd "${WASM}" && \
wasm-pack build --target=browser --scope browser --out-dir browser_pkg && \
wasm-pack build --release --target=browser --scope browser --out-dir browser_pkg && \
cd "${WASM_BROWSER_PKG}" && npm link
echo

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -88,11 +88,14 @@
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
/******/ },
/******/ "__wbindgen_closure_wrapper77": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper77"](p0i32,p1i32,p2i32);
/******/ "__wbindgen_rethrow": function(p0i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32);
/******/ },
/******/ "__wbindgen_closure_wrapper79": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper79"](p0i32,p1i32,p2i32);
/******/ "__wbindgen_closure_wrapper103": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper103"](p0i32,p1i32,p2i32);
/******/ },
/******/ "__wbindgen_closure_wrapper105": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper105"](p0i32,p1i32,p2i32);
/******/ }
/******/ }
/******/ };
@ -192,7 +195,7 @@
/******/ promises.push(installedWasmModuleData);
/******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId]();
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"215c5418dd8b4be64f60"}[wasmModuleId] + ".module.wasm");
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"68fa958468b8cdcb12e4"}[wasmModuleId] + ".module.wasm");
/******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {

13
docs/bootstrap.js vendored
View File

@ -88,11 +88,14 @@
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
/******/ },
/******/ "__wbindgen_closure_wrapper77": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper77"](p0i32,p1i32,p2i32);
/******/ "__wbindgen_rethrow": function(p0i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32);
/******/ },
/******/ "__wbindgen_closure_wrapper79": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper79"](p0i32,p1i32,p2i32);
/******/ "__wbindgen_closure_wrapper103": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper103"](p0i32,p1i32,p2i32);
/******/ },
/******/ "__wbindgen_closure_wrapper105": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper105"](p0i32,p1i32,p2i32);
/******/ }
/******/ }
/******/ };
@ -192,7 +195,7 @@
/******/ promises.push(installedWasmModuleData);
/******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId]();
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"215c5418dd8b4be64f60"}[wasmModuleId] + ".module.wasm");
/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"68fa958468b8cdcb12e4"}[wasmModuleId] + ".module.wasm");
/******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {

View File

@ -1,6 +1,6 @@
{
"name": "jsonpath-rs",
"version": "0.1.6",
"version": "0.1.7",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,5 +1,5 @@
[package]
name = "jsonpath-wasm"
name = "jsonpath_wasm"
version = "0.1.7"
authors = ["Changseok Han <freestrings@gmail.com>"]
description = "JsonPath Webassembly version compiled by Rust - Demo: https://freestrings.github.io/jsonpath"
@ -26,6 +26,9 @@ web-sys = { version = "0.3", features = ['console'] }
[dev-dependencies]
wasm-bindgen-test = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
js-sys = "0.3"
[profile.release]
opt-level = "s"

View File

@ -7,17 +7,19 @@ extern crate wasm_bindgen;
extern crate web_sys;
use std::collections::HashMap;
use std::ops::Deref;
use std::result::Result;
use std::sync::Mutex;
use std::ops::Deref;
use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;
use web_sys::console;
use jsonpath::filter::value_filter::JsonValueFilter;
use jsonpath::parser::parser::{Node, NodeVisitor, Parser};
use jsonpath::ref_value::model::{RefValue, RefValueWrapper};
use jsonpath::Selector as _Selector;
use wasm_bindgen::prelude::*;
use web_sys::console;
use std::result;
cfg_if! {
if #[cfg(feature = "wee_alloc")] {
@ -85,8 +87,8 @@ lazy_static! {
static ref CACHE_JSON_IDX: Mutex<usize> = Mutex::new(0);
}
#[wasm_bindgen]
pub fn alloc_json(js_value: JsValue) -> usize {
#[wasm_bindgen(js_name = allocJson)]
pub extern fn alloc_json(js_value: JsValue) -> usize {
match into_serde_json(&js_value) {
Ok(json) => {
let mut map = CACHE_JSON.lock().unwrap();
@ -106,8 +108,8 @@ pub fn alloc_json(js_value: JsValue) -> usize {
}
}
#[wasm_bindgen]
pub fn dealloc_json(ptr: usize) -> bool {
#[wasm_bindgen(js_name = deallocJson)]
pub extern fn dealloc_json(ptr: usize) -> bool {
let mut map = CACHE_JSON.lock().unwrap();
map.remove(&ptr).is_some()
}
@ -167,5 +169,49 @@ pub fn select(js_value: JsValue, path: &str) -> JsValue {
}
}
///
/// `wasm_bindgen` 제약으로 builder-pattern을 구사 할 수 없다.
///
#[wasm_bindgen]
pub struct Selector {
selector: _Selector
}
#[wasm_bindgen]
impl Selector {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Selector { selector: _Selector::new() }
}
#[wasm_bindgen(catch)]
pub fn path(&mut self, path: &str) -> result::Result<(), JsValue> {
let _ = self.selector.path(path)?;
Ok(())
}
#[wasm_bindgen(catch)]
pub fn value(&mut self, value: JsValue) -> result::Result<(), JsValue> {
let ref_value = into_serde_json(&value)?;
let _ = self.selector.value(ref_value)?;
Ok(())
}
#[wasm_bindgen(catch, js_name = selectToStr)]
pub fn select_to_str(&mut self) -> result::Result<JsValue, JsValue> {
let json_str = self.selector.select_to_str()?;
Ok(JsValue::from_str(&json_str))
}
#[wasm_bindgen(catch, js_name = selectTo)]
pub fn select_to(&mut self) -> result::Result<JsValue, JsValue> {
let ref_value = self.selector.select_to::<RefValue>()
.map_err(|e| JsValue::from_str(&e))?;
Ok(JsValue::from_serde(&ref_value)
.map_err(|e| JsValue::from_str(&format!("{:?}", e)))?)
}
}
#[wasm_bindgen]
pub fn testa() {}

View File

@ -1,13 +1,118 @@
//! Test suite for the Web and headless browsers.
#![cfg(target_arch = "wasm32")]
extern crate core;
extern crate js_sys;
extern crate jsonpath_wasm as jsonpath;
#[macro_use]
extern crate serde_json;
extern crate wasm_bindgen;
extern crate wasm_bindgen_test;
use serde_json::Value;
use wasm_bindgen::*;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn pass() {
assert_eq!(1 + 1, 2);
fn json_str() -> &'static str {
r#"
{
"store": {
"book": [
{
"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
},
{
"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
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
},
"expensive": 10
}
"#
}
fn target_json() -> Value {
json!([{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
}])
}
#[wasm_bindgen_test]
fn select() {
let json: Value = jsonpath::select(JsValue::from_str(json_str()), "$..book[2]").into_serde().unwrap();
assert_eq!(json, target_json());
}
#[wasm_bindgen_test]
fn compile() {
let js_value = jsonpath::compile("$..book[2]");
assert_eq!(js_value.is_function(), true);
let cb: &js_sys::Function = JsCast::unchecked_ref(js_value.as_ref());
let cb_result: JsValue = cb.call1(&js_value, &JsValue::from_str(json_str())).unwrap();
let json: Value = cb_result.into_serde().unwrap();
assert_eq!(json, target_json());
}
#[wasm_bindgen_test]
fn selector() {
let js_value = jsonpath::selector(JsValue::from_str(json_str()));
assert_eq!(js_value.is_function(), true);
let cb: &js_sys::Function = JsCast::unchecked_ref(js_value.as_ref());
let cb_result: JsValue = cb.call1(&js_value, &JsValue::from_str("$..book[2]")).unwrap();
let json: Value = cb_result.into_serde().unwrap();
assert_eq!(json, target_json());
}
#[wasm_bindgen_test]
fn alloc_dealloc_json() {
let ptr = jsonpath::alloc_json(JsValue::from_str(json_str()));
assert_eq!(ptr > 0, true);
let json: Value = jsonpath::select(JsValue::from_f64(ptr as f64), "$..book[2]").into_serde().unwrap();
assert_eq!(json, target_json());
assert_eq!(jsonpath::dealloc_json(ptr), true);
let err = jsonpath::select(JsValue::from_f64(ptr as f64), "$..book[2]").as_string().unwrap();
assert_eq!(err, "Invalid pointer".to_string());
}
#[wasm_bindgen_test]
fn selector_struct() {
let mut selector = jsonpath::Selector::new();
selector.path("$..book[2]").unwrap();
selector.value(JsValue::from_str(json_str())).unwrap();
let json: Value = selector.select_to().unwrap().into_serde().unwrap();
assert_eq!(json, target_json());
}

View File

@ -61,7 +61,7 @@ let path = '$..book[?(@.price<30 && @.category=="fiction")]';
let template = jpw.compile(path);
let selector = jpw.selector(json);
let ptr = jpw.alloc_json(json);
let ptr = jpw.allocJson(json);
if(ptr == 0) console.error('invalid ptr');
let iterCount = 2000;
@ -83,7 +83,7 @@ run('jsonpath', iterCount, function() { jp.query(json, path) })
return run('jsonpath-wasm- select-alloc', iterCount, function() { jpw.select(ptr, path) });
})
.finally(function() {
if(!jpw.dealloc_json(ptr)) {
if(!jpw.deallocJson(ptr)) {
console.error('fail to dealloc');
}
});