diff --git a/.idea/runConfigurations/serde.xml b/.idea/runConfigurations/serde.xml
new file mode 100644
index 0000000..83f09b6
--- /dev/null
+++ b/.idea/runConfigurations/serde.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 8e4bf32..93f89e7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "jsonpath_lib"
-version = "0.1.4"
+version = "0.1.5"
authors = ["Changseok Han "]
description = "JsonPath in Rust and Webassembly - Webassembly Demo: https://freestrings.github.io/jsonpath"
diff --git a/README.md b/README.md
index 18ecf61..2364b1a 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@ To enjoy Rust!
- [jsonpath_lib library](#jsonpath_lib-library)
- [rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)](#rust---jsonpathselectjson-serde_jsonvaluevalue-jsonpath-str)
+- [rust - jsonpath::select_str(json_str: &str, jsonpath: &str)](#rust---jsonpathselect_strjson-str-jsonpath-str)
- [rust - jsonpath::compile(jsonpath: &str)](#rust---jsonpathcompilejsonpath-str)
- [rust - jsonpath::selector(json: &serde_json::value::Value)](#rust---jsonpathselectorjson-serde_jsonvaluevalue)
- [rust - examples](https://github.com/freestrings/jsonpath/wiki/rust-examples)
@@ -36,6 +37,7 @@ To enjoy Rust!
[With AWS API Gateway](#)
[Simple time check - webassembly](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck---jsonpath-wasm)
+
[Simple time check - native addon for NodeJs](https://github.com/freestrings/jsonpath/wiki/Simple-timecheck-jsonpath-native)
## With Javascript
@@ -192,7 +194,7 @@ extern crate jsonpath_lib as jsonpath;
extern crate serde_json;
```
-### rust - jsonpath::select(&json: serde_json::value::Value, jsonpath: &str)
+### rust - jsonpath::select(json: &serde_json::value::Value, jsonpath: &str)
```rust
let json_obj = json!({
@@ -206,6 +208,21 @@ let ret = json!([ {"id": 0}, {"id": 0} ]);
assert_eq!(json, ret)
```
+### rust - jsonpath::select_str(json: &str, jsonpath: &str)
+
+```rust
+let json_obj = json!({
+ "school": {
+ "friends": [{"id": 0}, {"id": 1}]
+ },
+ "friends": [{"id": 0}, {"id": 1}]
+});
+let json_str = jsonpath::select_str(&serde_json::to_string(&json_obj).unwrap(), "$..friends[0]").unwrap();
+let json: Value = serde_json::from_str(&json_str).unwrap();
+let ret = json!([ {"id": 0}, {"id": 0} ]);
+assert_eq!(json, ret)
+```
+
### rust - jsonpath::compile(jsonpath: &str)
```rust
diff --git a/benches/bench.rs b/benches/bench.rs
index be51d33..0dc42ff 100644
--- a/benches/bench.rs
+++ b/benches/bench.rs
@@ -14,40 +14,57 @@ fn read_json(path: &str) -> String {
contents
}
+fn get_string() -> String {
+ read_json("./benches/example.json")
+}
+
+fn get_json() -> Value {
+ let string = get_string();
+ serde_json::from_str(string.as_str()).unwrap()
+}
+
+fn get_path() -> &'static str {
+ r#"$..book[?(@.price<30 && @.category=="fiction")]"#
+}
+
#[bench]
fn bench_selector(b: &mut Bencher) {
- let string = read_json("./benches/example.json");
- let path = r#"$..book[?(@.price<30 && @.category=="fiction")]"#;
- let json: Value = serde_json::from_str(string.as_str()).unwrap();
+ let json = get_json();
let mut selector = jsonpath::selector(&json);
b.iter(move || {
- for _ in 1..1000 {
- let _ = selector(path).unwrap();
+ for _ in 1..100 {
+ let _ = selector(get_path()).unwrap();
}
});
}
#[bench]
-fn bench_select(b: &mut Bencher) {
- let string = read_json("./benches/example.json");
- let path = r#"$..book[?(@.price<30 && @.category=="fiction")]"#;
- let json: Value = serde_json::from_str(string.as_str()).unwrap();
+fn bench_select_val(b: &mut Bencher) {
+ let json = get_json();
b.iter(move || {
- for _ in 1..1000 {
- let _ = jsonpath::select(&json, path).unwrap();
+ for _ in 1..100 {
+ let _ = jsonpath::select(&json, get_path()).unwrap();
+ }
+ });
+}
+
+#[bench]
+fn bench_select_str(b: &mut Bencher) {
+ let json = get_string();
+ b.iter(move || {
+ for _ in 1..100 {
+ let _ = jsonpath::select_str(&json, get_path()).unwrap();
}
});
}
#[bench]
fn bench_compile(b: &mut Bencher) {
- let string = read_json("./benches/example.json");
- let path = r#"$..book[?(@.price<30 && @.category=="fiction")]"#;
- let json: Value = serde_json::from_str(string.as_str()).unwrap();
- let mut template = jsonpath::compile(path);
+ let json = get_json();
+ let mut template = jsonpath::compile(get_path());
b.iter(move || {
- for _ in 1..1000 {
+ for _ in 1..100 {
let _ = template(&json).unwrap();
}
});
-}
\ No newline at end of file
+}
diff --git a/benches/package-lock.json b/benches/package-lock.json
new file mode 100644
index 0000000..48e341a
--- /dev/null
+++ b/benches/package-lock.json
@@ -0,0 +1,3 @@
+{
+ "lockfileVersion": 1
+}
diff --git a/docs/0.bootstrap.js b/docs/0.bootstrap.js
index d8c210e..3404cfb 100644
--- a/docs/0.bootstrap.js
+++ b/docs/0.bootstrap.js
@@ -4,11 +4,11 @@
/*!***************************************!*\
!*** ../browser_pkg/jsonpath_wasm.js ***!
\***************************************/
-/*! exports provided: alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __widl_f_log_1_, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_string_new, __wbindgen_number_get, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper99, __wbindgen_closure_wrapper101, __wbindgen_throw */
+/*! exports provided: alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __widl_f_log_1_, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_string_new, __wbindgen_number_get, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper100, __wbindgen_closure_wrapper102, __wbindgen_throw */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"alloc_json\", function() { return alloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dealloc_json\", function() { return dealloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"compile\", function() { return compile; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"reader\", function() { return reader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"selector\", function() { return selector; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"select\", function() { return select; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"read\", function() { return read; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"testa\", function() { return testa; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__widl_f_log_1_\", function() { return __widl_f_log_1_; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_clone_ref\", function() { return __wbindgen_object_clone_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_drop_ref\", function() { return __wbindgen_object_drop_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_new\", function() { return __wbindgen_string_new; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_number_get\", function() { return __wbindgen_number_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_is_string\", function() { return __wbindgen_is_string; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_get\", function() { return __wbindgen_string_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_cb_forget\", function() { return __wbindgen_cb_forget; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_parse\", function() { return __wbindgen_json_parse; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_serialize\", function() { return __wbindgen_json_serialize; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper99\", function() { return __wbindgen_closure_wrapper99; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper101\", function() { return __wbindgen_closure_wrapper101; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return __wbindgen_throw; });\n/* harmony import */ var _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./jsonpath_wasm_bg */ \"../browser_pkg/jsonpath_wasm_bg.wasm\");\n/* tslint:disable */\n\n\nconst heap = new Array(32);\n\nheap.fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n/**\n* @param {any} arg0\n* @returns {number}\n*/\nfunction alloc_json(arg0) {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"alloc_json\"](addHeapObject(arg0));\n}\n\n/**\n* @param {number} arg0\n* @returns {boolean}\n*/\nfunction dealloc_json(arg0) {\n return (_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"dealloc_json\"](arg0)) !== 0;\n}\n\nlet cachedTextEncoder = new TextEncoder('utf-8');\n\nlet cachegetUint8Memory = null;\nfunction getUint8Memory() {\n if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint8Memory = new Uint8Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint8Memory;\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nfunction passStringToWasm(arg) {\n\n const buf = cachedTextEncoder.encode(arg);\n const ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_malloc\"](buf.length);\n getUint8Memory().set(buf, ptr);\n WASM_VECTOR_LEN = buf.length;\n return ptr;\n}\n\nfunction getObject(idx) { return heap[idx]; }\n\nfunction dropObject(idx) {\n if (idx < 36) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n/**\n* @param {string} arg0\n* @returns {any}\n*/\nfunction compile(arg0) {\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"compile\"](ptr0, len0));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr0, len0 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use selector\n*\n* @param {any} arg0\n* @returns {any}\n*/\nfunction reader(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"reader\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @returns {any}\n*/\nfunction selector(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"selector\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction select(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"select\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use select\n*\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction read(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"read\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n* @returns {void}\n*/\nfunction testa() {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"testa\"]();\n}\n\nfunction __widl_f_log_1_(arg0) {\n console.log(getObject(arg0));\n}\n\nfunction __wbindgen_object_clone_ref(idx) {\n return addHeapObject(getObject(idx));\n}\n\nfunction __wbindgen_object_drop_ref(i) { dropObject(i); }\n\nlet cachedTextDecoder = new TextDecoder('utf-8');\n\nfunction getStringFromWasm(ptr, len) {\n return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));\n}\n\nfunction __wbindgen_string_new(p, l) {\n return addHeapObject(getStringFromWasm(p, l));\n}\n\nfunction __wbindgen_number_get(n, invalid) {\n let obj = getObject(n);\n if (typeof(obj) === 'number') return obj;\n getUint8Memory()[invalid] = 1;\n return 0;\n}\n\nfunction __wbindgen_is_string(i) {\n return typeof(getObject(i)) === 'string' ? 1 : 0;\n}\n\nlet cachegetUint32Memory = null;\nfunction getUint32Memory() {\n if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint32Memory = new Uint32Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint32Memory;\n}\n\nfunction __wbindgen_string_get(i, len_ptr) {\n let obj = getObject(i);\n if (typeof(obj) !== 'string') return 0;\n const ptr = passStringToWasm(obj);\n getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;\n return ptr;\n}\n\nconst __wbindgen_cb_forget = dropObject;\n\nfunction __wbindgen_json_parse(ptr, len) {\n return addHeapObject(JSON.parse(getStringFromWasm(ptr, len)));\n}\n\nfunction __wbindgen_json_serialize(idx, ptrptr) {\n const ptr = passStringToWasm(JSON.stringify(getObject(idx)));\n getUint32Memory()[ptrptr / 4] = ptr;\n return WASM_VECTOR_LEN;\n}\n\nfunction __wbindgen_closure_wrapper99(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(14);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(15);\n const cb = function(arg0) {\n this.cnt++;\n try {\n return takeObject(f(this.a, b, addHeapObject(arg0)));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_closure_wrapper101(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(16);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(17);\n const cb = function(arg0) {\n this.cnt++;\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(f(this.a, b, ptr0, len0));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_throw(ptr, len) {\n throw new Error(getStringFromWasm(ptr, len));\n}\n\n\n\n//# sourceURL=webpack:///../browser_pkg/jsonpath_wasm.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"alloc_json\", function() { return alloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dealloc_json\", function() { return dealloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"compile\", function() { return compile; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"reader\", function() { return reader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"selector\", function() { return selector; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"select\", function() { return select; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"read\", function() { return read; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"testa\", function() { return testa; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__widl_f_log_1_\", function() { return __widl_f_log_1_; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_clone_ref\", function() { return __wbindgen_object_clone_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_drop_ref\", function() { return __wbindgen_object_drop_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_new\", function() { return __wbindgen_string_new; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_number_get\", function() { return __wbindgen_number_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_is_string\", function() { return __wbindgen_is_string; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_get\", function() { return __wbindgen_string_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_cb_forget\", function() { return __wbindgen_cb_forget; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_parse\", function() { return __wbindgen_json_parse; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_serialize\", function() { return __wbindgen_json_serialize; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper100\", function() { return __wbindgen_closure_wrapper100; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper102\", function() { return __wbindgen_closure_wrapper102; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return __wbindgen_throw; });\n/* harmony import */ var _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./jsonpath_wasm_bg */ \"../browser_pkg/jsonpath_wasm_bg.wasm\");\n/* tslint:disable */\n\n\nconst heap = new Array(32);\n\nheap.fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n/**\n* @param {any} arg0\n* @returns {number}\n*/\nfunction alloc_json(arg0) {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"alloc_json\"](addHeapObject(arg0));\n}\n\n/**\n* @param {number} arg0\n* @returns {boolean}\n*/\nfunction dealloc_json(arg0) {\n return (_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"dealloc_json\"](arg0)) !== 0;\n}\n\nlet cachedTextEncoder = new TextEncoder('utf-8');\n\nlet cachegetUint8Memory = null;\nfunction getUint8Memory() {\n if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint8Memory = new Uint8Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint8Memory;\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nfunction passStringToWasm(arg) {\n\n const buf = cachedTextEncoder.encode(arg);\n const ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_malloc\"](buf.length);\n getUint8Memory().set(buf, ptr);\n WASM_VECTOR_LEN = buf.length;\n return ptr;\n}\n\nfunction getObject(idx) { return heap[idx]; }\n\nfunction dropObject(idx) {\n if (idx < 36) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n/**\n* @param {string} arg0\n* @returns {any}\n*/\nfunction compile(arg0) {\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"compile\"](ptr0, len0));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr0, len0 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use selector\n*\n* @param {any} arg0\n* @returns {any}\n*/\nfunction reader(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"reader\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @returns {any}\n*/\nfunction selector(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"selector\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction select(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"select\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use select\n*\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction read(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"read\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n* @returns {void}\n*/\nfunction testa() {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"testa\"]();\n}\n\nfunction __widl_f_log_1_(arg0) {\n console.log(getObject(arg0));\n}\n\nfunction __wbindgen_object_clone_ref(idx) {\n return addHeapObject(getObject(idx));\n}\n\nfunction __wbindgen_object_drop_ref(i) { dropObject(i); }\n\nlet cachedTextDecoder = new TextDecoder('utf-8');\n\nfunction getStringFromWasm(ptr, len) {\n return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));\n}\n\nfunction __wbindgen_string_new(p, l) {\n return addHeapObject(getStringFromWasm(p, l));\n}\n\nfunction __wbindgen_number_get(n, invalid) {\n let obj = getObject(n);\n if (typeof(obj) === 'number') return obj;\n getUint8Memory()[invalid] = 1;\n return 0;\n}\n\nfunction __wbindgen_is_string(i) {\n return typeof(getObject(i)) === 'string' ? 1 : 0;\n}\n\nlet cachegetUint32Memory = null;\nfunction getUint32Memory() {\n if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint32Memory = new Uint32Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint32Memory;\n}\n\nfunction __wbindgen_string_get(i, len_ptr) {\n let obj = getObject(i);\n if (typeof(obj) !== 'string') return 0;\n const ptr = passStringToWasm(obj);\n getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;\n return ptr;\n}\n\nconst __wbindgen_cb_forget = dropObject;\n\nfunction __wbindgen_json_parse(ptr, len) {\n return addHeapObject(JSON.parse(getStringFromWasm(ptr, len)));\n}\n\nfunction __wbindgen_json_serialize(idx, ptrptr) {\n const ptr = passStringToWasm(JSON.stringify(getObject(idx)));\n getUint32Memory()[ptrptr / 4] = ptr;\n return WASM_VECTOR_LEN;\n}\n\nfunction __wbindgen_closure_wrapper100(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(16);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(17);\n const cb = function(arg0) {\n this.cnt++;\n try {\n return takeObject(f(this.a, b, addHeapObject(arg0)));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_closure_wrapper102(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(14);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(15);\n const cb = function(arg0) {\n this.cnt++;\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(f(this.a, b, ptr0, len0));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_throw(ptr, len) {\n throw new Error(getStringFromWasm(ptr, len));\n}\n\n\n\n//# sourceURL=webpack:///../browser_pkg/jsonpath_wasm.js?");
/***/ }),
diff --git a/docs/bench/0.bootstrap.js b/docs/bench/0.bootstrap.js
index 30b16e0..c354644 100644
--- a/docs/bench/0.bootstrap.js
+++ b/docs/bench/0.bootstrap.js
@@ -4,11 +4,11 @@
/*!***************************************!*\
!*** ../browser_pkg/jsonpath_wasm.js ***!
\***************************************/
-/*! exports provided: alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __widl_f_log_1_, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_string_new, __wbindgen_number_get, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper99, __wbindgen_closure_wrapper101, __wbindgen_throw */
+/*! exports provided: alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __widl_f_log_1_, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_string_new, __wbindgen_number_get, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper100, __wbindgen_closure_wrapper102, __wbindgen_throw */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"alloc_json\", function() { return alloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dealloc_json\", function() { return dealloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"compile\", function() { return compile; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"reader\", function() { return reader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"selector\", function() { return selector; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"select\", function() { return select; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"read\", function() { return read; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"testa\", function() { return testa; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__widl_f_log_1_\", function() { return __widl_f_log_1_; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_clone_ref\", function() { return __wbindgen_object_clone_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_drop_ref\", function() { return __wbindgen_object_drop_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_new\", function() { return __wbindgen_string_new; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_number_get\", function() { return __wbindgen_number_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_is_string\", function() { return __wbindgen_is_string; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_get\", function() { return __wbindgen_string_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_cb_forget\", function() { return __wbindgen_cb_forget; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_parse\", function() { return __wbindgen_json_parse; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_serialize\", function() { return __wbindgen_json_serialize; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper99\", function() { return __wbindgen_closure_wrapper99; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper101\", function() { return __wbindgen_closure_wrapper101; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return __wbindgen_throw; });\n/* harmony import */ var _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./jsonpath_wasm_bg */ \"../browser_pkg/jsonpath_wasm_bg.wasm\");\n/* tslint:disable */\n\n\nconst heap = new Array(32);\n\nheap.fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n/**\n* @param {any} arg0\n* @returns {number}\n*/\nfunction alloc_json(arg0) {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"alloc_json\"](addHeapObject(arg0));\n}\n\n/**\n* @param {number} arg0\n* @returns {boolean}\n*/\nfunction dealloc_json(arg0) {\n return (_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"dealloc_json\"](arg0)) !== 0;\n}\n\nlet cachedTextEncoder = new TextEncoder('utf-8');\n\nlet cachegetUint8Memory = null;\nfunction getUint8Memory() {\n if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint8Memory = new Uint8Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint8Memory;\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nfunction passStringToWasm(arg) {\n\n const buf = cachedTextEncoder.encode(arg);\n const ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_malloc\"](buf.length);\n getUint8Memory().set(buf, ptr);\n WASM_VECTOR_LEN = buf.length;\n return ptr;\n}\n\nfunction getObject(idx) { return heap[idx]; }\n\nfunction dropObject(idx) {\n if (idx < 36) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n/**\n* @param {string} arg0\n* @returns {any}\n*/\nfunction compile(arg0) {\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"compile\"](ptr0, len0));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr0, len0 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use selector\n*\n* @param {any} arg0\n* @returns {any}\n*/\nfunction reader(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"reader\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @returns {any}\n*/\nfunction selector(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"selector\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction select(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"select\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use select\n*\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction read(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"read\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n* @returns {void}\n*/\nfunction testa() {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"testa\"]();\n}\n\nfunction __widl_f_log_1_(arg0) {\n console.log(getObject(arg0));\n}\n\nfunction __wbindgen_object_clone_ref(idx) {\n return addHeapObject(getObject(idx));\n}\n\nfunction __wbindgen_object_drop_ref(i) { dropObject(i); }\n\nlet cachedTextDecoder = new TextDecoder('utf-8');\n\nfunction getStringFromWasm(ptr, len) {\n return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));\n}\n\nfunction __wbindgen_string_new(p, l) {\n return addHeapObject(getStringFromWasm(p, l));\n}\n\nfunction __wbindgen_number_get(n, invalid) {\n let obj = getObject(n);\n if (typeof(obj) === 'number') return obj;\n getUint8Memory()[invalid] = 1;\n return 0;\n}\n\nfunction __wbindgen_is_string(i) {\n return typeof(getObject(i)) === 'string' ? 1 : 0;\n}\n\nlet cachegetUint32Memory = null;\nfunction getUint32Memory() {\n if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint32Memory = new Uint32Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint32Memory;\n}\n\nfunction __wbindgen_string_get(i, len_ptr) {\n let obj = getObject(i);\n if (typeof(obj) !== 'string') return 0;\n const ptr = passStringToWasm(obj);\n getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;\n return ptr;\n}\n\nconst __wbindgen_cb_forget = dropObject;\n\nfunction __wbindgen_json_parse(ptr, len) {\n return addHeapObject(JSON.parse(getStringFromWasm(ptr, len)));\n}\n\nfunction __wbindgen_json_serialize(idx, ptrptr) {\n const ptr = passStringToWasm(JSON.stringify(getObject(idx)));\n getUint32Memory()[ptrptr / 4] = ptr;\n return WASM_VECTOR_LEN;\n}\n\nfunction __wbindgen_closure_wrapper99(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(14);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(15);\n const cb = function(arg0) {\n this.cnt++;\n try {\n return takeObject(f(this.a, b, addHeapObject(arg0)));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_closure_wrapper101(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(16);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(17);\n const cb = function(arg0) {\n this.cnt++;\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(f(this.a, b, ptr0, len0));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_throw(ptr, len) {\n throw new Error(getStringFromWasm(ptr, len));\n}\n\n\n\n//# sourceURL=webpack:///../browser_pkg/jsonpath_wasm.js?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"alloc_json\", function() { return alloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"dealloc_json\", function() { return dealloc_json; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"compile\", function() { return compile; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"reader\", function() { return reader; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"selector\", function() { return selector; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"select\", function() { return select; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"read\", function() { return read; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"testa\", function() { return testa; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__widl_f_log_1_\", function() { return __widl_f_log_1_; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_clone_ref\", function() { return __wbindgen_object_clone_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_object_drop_ref\", function() { return __wbindgen_object_drop_ref; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_new\", function() { return __wbindgen_string_new; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_number_get\", function() { return __wbindgen_number_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_is_string\", function() { return __wbindgen_is_string; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_string_get\", function() { return __wbindgen_string_get; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_cb_forget\", function() { return __wbindgen_cb_forget; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_parse\", function() { return __wbindgen_json_parse; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_json_serialize\", function() { return __wbindgen_json_serialize; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper100\", function() { return __wbindgen_closure_wrapper100; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper102\", function() { return __wbindgen_closure_wrapper102; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_throw\", function() { return __wbindgen_throw; });\n/* harmony import */ var _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./jsonpath_wasm_bg */ \"../browser_pkg/jsonpath_wasm_bg.wasm\");\n/* tslint:disable */\n\n\nconst heap = new Array(32);\n\nheap.fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nlet heap_next = heap.length;\n\nfunction addHeapObject(obj) {\n if (heap_next === heap.length) heap.push(heap.length + 1);\n const idx = heap_next;\n heap_next = heap[idx];\n\n heap[idx] = obj;\n return idx;\n}\n/**\n* @param {any} arg0\n* @returns {number}\n*/\nfunction alloc_json(arg0) {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"alloc_json\"](addHeapObject(arg0));\n}\n\n/**\n* @param {number} arg0\n* @returns {boolean}\n*/\nfunction dealloc_json(arg0) {\n return (_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"dealloc_json\"](arg0)) !== 0;\n}\n\nlet cachedTextEncoder = new TextEncoder('utf-8');\n\nlet cachegetUint8Memory = null;\nfunction getUint8Memory() {\n if (cachegetUint8Memory === null || cachegetUint8Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint8Memory = new Uint8Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint8Memory;\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nfunction passStringToWasm(arg) {\n\n const buf = cachedTextEncoder.encode(arg);\n const ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_malloc\"](buf.length);\n getUint8Memory().set(buf, ptr);\n WASM_VECTOR_LEN = buf.length;\n return ptr;\n}\n\nfunction getObject(idx) { return heap[idx]; }\n\nfunction dropObject(idx) {\n if (idx < 36) return;\n heap[idx] = heap_next;\n heap_next = idx;\n}\n\nfunction takeObject(idx) {\n const ret = getObject(idx);\n dropObject(idx);\n return ret;\n}\n/**\n* @param {string} arg0\n* @returns {any}\n*/\nfunction compile(arg0) {\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"compile\"](ptr0, len0));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr0, len0 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use selector\n*\n* @param {any} arg0\n* @returns {any}\n*/\nfunction reader(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"reader\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @returns {any}\n*/\nfunction selector(arg0) {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"selector\"](addHeapObject(arg0)));\n}\n\n/**\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction select(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"select\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n*\n* deprecated. use select\n*\n* @param {any} arg0\n* @param {string} arg1\n* @returns {any}\n*/\nfunction read(arg0, arg1) {\n const ptr1 = passStringToWasm(arg1);\n const len1 = WASM_VECTOR_LEN;\n try {\n return takeObject(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"read\"](addHeapObject(arg0), ptr1, len1));\n\n } finally {\n _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_free\"](ptr1, len1 * 1);\n\n }\n\n}\n\n/**\n* @returns {void}\n*/\nfunction testa() {\n return _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"testa\"]();\n}\n\nfunction __widl_f_log_1_(arg0) {\n console.log(getObject(arg0));\n}\n\nfunction __wbindgen_object_clone_ref(idx) {\n return addHeapObject(getObject(idx));\n}\n\nfunction __wbindgen_object_drop_ref(i) { dropObject(i); }\n\nlet cachedTextDecoder = new TextDecoder('utf-8');\n\nfunction getStringFromWasm(ptr, len) {\n return cachedTextDecoder.decode(getUint8Memory().subarray(ptr, ptr + len));\n}\n\nfunction __wbindgen_string_new(p, l) {\n return addHeapObject(getStringFromWasm(p, l));\n}\n\nfunction __wbindgen_number_get(n, invalid) {\n let obj = getObject(n);\n if (typeof(obj) === 'number') return obj;\n getUint8Memory()[invalid] = 1;\n return 0;\n}\n\nfunction __wbindgen_is_string(i) {\n return typeof(getObject(i)) === 'string' ? 1 : 0;\n}\n\nlet cachegetUint32Memory = null;\nfunction getUint32Memory() {\n if (cachegetUint32Memory === null || cachegetUint32Memory.buffer !== _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer) {\n cachegetUint32Memory = new Uint32Array(_jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"memory\"].buffer);\n }\n return cachegetUint32Memory;\n}\n\nfunction __wbindgen_string_get(i, len_ptr) {\n let obj = getObject(i);\n if (typeof(obj) !== 'string') return 0;\n const ptr = passStringToWasm(obj);\n getUint32Memory()[len_ptr / 4] = WASM_VECTOR_LEN;\n return ptr;\n}\n\nconst __wbindgen_cb_forget = dropObject;\n\nfunction __wbindgen_json_parse(ptr, len) {\n return addHeapObject(JSON.parse(getStringFromWasm(ptr, len)));\n}\n\nfunction __wbindgen_json_serialize(idx, ptrptr) {\n const ptr = passStringToWasm(JSON.stringify(getObject(idx)));\n getUint32Memory()[ptrptr / 4] = ptr;\n return WASM_VECTOR_LEN;\n}\n\nfunction __wbindgen_closure_wrapper100(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(16);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(17);\n const cb = function(arg0) {\n this.cnt++;\n try {\n return takeObject(f(this.a, b, addHeapObject(arg0)));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_closure_wrapper102(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(14);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(15);\n const cb = function(arg0) {\n this.cnt++;\n const ptr0 = passStringToWasm(arg0);\n const len0 = WASM_VECTOR_LEN;\n try {\n return takeObject(f(this.a, b, ptr0, len0));\n\n } finally {\n if (this.cnt-- == 1) d(this.a, b);\n\n }\n\n };\n cb.a = a;\n cb.cnt = 1;\n let real = cb.bind(cb);\n real.original = cb;\n return addHeapObject(real);\n}\n\nfunction __wbindgen_throw(ptr, len) {\n throw new Error(getStringFromWasm(ptr, len));\n}\n\n\n\n//# sourceURL=webpack:///../browser_pkg/jsonpath_wasm.js?");
/***/ }),
diff --git a/docs/bench/bootstrap.js b/docs/bench/bootstrap.js
index 7b72122..f8a1b6b 100644
--- a/docs/bench/bootstrap.js
+++ b/docs/bench/bootstrap.js
@@ -88,11 +88,11 @@
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
/******/ },
-/******/ "__wbindgen_closure_wrapper99": function(p0i32,p1i32,p2i32) {
-/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper99"](p0i32,p1i32,p2i32);
+/******/ "__wbindgen_closure_wrapper100": function(p0i32,p1i32,p2i32) {
+/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper100"](p0i32,p1i32,p2i32);
/******/ },
-/******/ "__wbindgen_closure_wrapper101": function(p0i32,p1i32,p2i32) {
-/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper101"](p0i32,p1i32,p2i32);
+/******/ "__wbindgen_closure_wrapper102": function(p0i32,p1i32,p2i32) {
+/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper102"](p0i32,p1i32,p2i32);
/******/ }
/******/ }
/******/ };
@@ -192,7 +192,7 @@
/******/ promises.push(installedWasmModuleData);
/******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId]();
-/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"db8564aae9d99ec41b79"}[wasmModuleId] + ".module.wasm");
+/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"e354e10adee0b37b85d7"}[wasmModuleId] + ".module.wasm");
/******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
diff --git a/docs/bench/db8564aae9d99ec41b79.module.wasm b/docs/bench/db8564aae9d99ec41b79.module.wasm
deleted file mode 100644
index d66938d..0000000
Binary files a/docs/bench/db8564aae9d99ec41b79.module.wasm and /dev/null differ
diff --git a/docs/bench/e354e10adee0b37b85d7.module.wasm b/docs/bench/e354e10adee0b37b85d7.module.wasm
new file mode 100644
index 0000000..83d18f9
Binary files /dev/null and b/docs/bench/e354e10adee0b37b85d7.module.wasm differ
diff --git a/docs/bootstrap.js b/docs/bootstrap.js
index 2200220..117aa80 100644
--- a/docs/bootstrap.js
+++ b/docs/bootstrap.js
@@ -88,11 +88,11 @@
/******/ "__wbindgen_throw": function(p0i32,p1i32) {
/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
/******/ },
-/******/ "__wbindgen_closure_wrapper99": function(p0i32,p1i32,p2i32) {
-/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper99"](p0i32,p1i32,p2i32);
+/******/ "__wbindgen_closure_wrapper100": function(p0i32,p1i32,p2i32) {
+/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper100"](p0i32,p1i32,p2i32);
/******/ },
-/******/ "__wbindgen_closure_wrapper101": function(p0i32,p1i32,p2i32) {
-/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper101"](p0i32,p1i32,p2i32);
+/******/ "__wbindgen_closure_wrapper102": function(p0i32,p1i32,p2i32) {
+/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper102"](p0i32,p1i32,p2i32);
/******/ }
/******/ }
/******/ };
@@ -192,7 +192,7 @@
/******/ promises.push(installedWasmModuleData);
/******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId]();
-/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"db8564aae9d99ec41b79"}[wasmModuleId] + ".module.wasm");
+/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"e354e10adee0b37b85d7"}[wasmModuleId] + ".module.wasm");
/******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
diff --git a/docs/db8564aae9d99ec41b79.module.wasm b/docs/db8564aae9d99ec41b79.module.wasm
deleted file mode 100644
index d66938d..0000000
Binary files a/docs/db8564aae9d99ec41b79.module.wasm and /dev/null differ
diff --git a/docs/e354e10adee0b37b85d7.module.wasm b/docs/e354e10adee0b37b85d7.module.wasm
new file mode 100644
index 0000000..83d18f9
Binary files /dev/null and b/docs/e354e10adee0b37b85d7.module.wasm differ
diff --git a/nodejs/lib/index.js b/nodejs/lib/index.js
index 4dc380a..49b1dca 100644
--- a/nodejs/lib/index.js
+++ b/nodejs/lib/index.js
@@ -6,7 +6,7 @@ function compile(path) {
if(typeof json != 'string') {
json = JSON.stringify(json)
}
- return compile.template(json);
+ return JSON.parse(compile.template(json));
};
}
@@ -16,7 +16,7 @@ function selector(json) {
}
let selector = new Selector(json);
return (path) => {
- return selector.selector(path);
+ return JSON.parse(selector.selector(path));
}
}
@@ -24,7 +24,7 @@ function select(json, path) {
if(typeof json != 'string') {
json = JSON.stringify(json)
}
- return selectStr(json, path);
+ return JSON.parse(selectStr(json, path));
}
module.exports = {
diff --git a/nodejs/native/Cargo.toml b/nodejs/native/Cargo.toml
index 0cf1cc6..6f9ed3f 100644
--- a/nodejs/native/Cargo.toml
+++ b/nodejs/native/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "jsonpath-rs"
-version = "0.1.0"
+version = "0.1.1"
authors = ["Changseok Han "]
description = "JsonPath engine for NodeJs with Rust native implementation."
keywords = ["library", "jsonpath", "json"]
diff --git a/nodejs/native/src/lib.rs b/nodejs/native/src/lib.rs
index cefd707..1b6110c 100644
--- a/nodejs/native/src/lib.rs
+++ b/nodejs/native/src/lib.rs
@@ -24,13 +24,9 @@ fn select(mut ctx: FunctionContext) -> JsResult {
fn select_str(mut ctx: FunctionContext) -> JsResult {
let json_val = ctx.argument::(0)?.value();
- let json: Value = match serde_json::from_str(json_val.as_str()) {
- Ok(json) => json,
- Err(e) => panic!("{:?}", e)
- };
let path = ctx.argument::(1)?.value();
- match jsonpath::select(&json, path.as_str()) {
- Ok(value) => Ok(neon_serde::to_value(&mut ctx, &value)?),
+ match jsonpath::select_str(&json_val, path.as_str()) {
+ Ok(value) => Ok(JsString::new(&mut ctx, &value).upcast()),
Err(e) => panic!("{:?}", e)
}
}
@@ -66,31 +62,30 @@ declare_types! {
this.node.clone()
};
-// let o = ctx.argument::(0)?;
-// let json: Value = neon_serde::from_value(&mut ctx, o)?;
let json_str = ctx.argument::(0)?.value();
- let json: Value = match serde_json::from_str(&json_str) {
- Ok(json) => json,
+ let ref_value: RefValue = match serde_json::from_str(&json_str) {
+ Ok(ref_value) => ref_value,
Err(e) => panic!("{:?}", e)
};
- let mut jf = JsonValueFilter::new_from_value((&json).into());
+
+ let mut jf = JsonValueFilter::new_from_value(ref_value.into());
jf.visit(node);
- let v = jf.take_value().into_value();
- Ok(neon_serde::to_value(&mut ctx, &v)?)
+ match serde_json::to_string(&jf.take_value()) {
+ Ok(json_str) => Ok(JsString::new(&mut ctx, &json_str).upcast()),
+ Err(e) => panic!("{:?}", e)
+ }
}
}
pub class JsSelector for Selector {
init(mut ctx) {
-// let o = ctx.argument::(0)?;
-// let json: Value = neon_serde::from_value(&mut ctx, o)?;
let json_str = ctx.argument::(0)?.value();
- let json: Value = match serde_json::from_str(&json_str) {
- Ok(json) => json,
+ let ref_value: RefValue = match serde_json::from_str(&json_str) {
+ Ok(ref_value) => ref_value,
Err(e) => panic!("{:?}", e)
};
- Ok(Selector { json: (&json).into() })
+ Ok(Selector { json: ref_value.into() })
}
method selector(mut ctx) {
@@ -112,8 +107,10 @@ declare_types! {
let mut jf = JsonValueFilter::new_from_value(json);
jf.visit(node);
- let v = jf.take_value().into_value();
- Ok(neon_serde::to_value(&mut ctx, &v)?)
+ match serde_json::to_string(&jf.take_value()) {
+ Ok(json_str) => Ok(JsString::new(&mut ctx, &json_str).upcast()),
+ Err(e) => panic!("{:?}", e)
+ }
}
}
}
diff --git a/nodejs/test/index.spec.js b/nodejs/test/index.spec.js
index 751d3d0..dc3cbad 100644
--- a/nodejs/test/index.spec.js
+++ b/nodejs/test/index.spec.js
@@ -4,7 +4,7 @@ describe('compile test', () => {
it('basic', (done) => {
let template = jsonpath.compile('$.a');
let result = template({'a': 1});
- if (result == 1) {
+ if (result === 1) {
done();
}
});
@@ -14,7 +14,7 @@ describe('selector test', () => {
it('basic', (done) => {
let selector = jsonpath.selector({'a': 1});
let result = selector('$.a');
- if (result == 1) {
+ if (result === 1) {
done();
}
});
@@ -23,7 +23,7 @@ describe('selector test', () => {
describe('select test', () => {
it('basic', (done) => {
let result = jsonpath.select({'a': 1}, '$.a');
- if (result == 1) {
+ if (result === 1) {
done();
}
});
diff --git a/src/filter/term.rs b/src/filter/term.rs
index 8fb2e6b..4828491 100644
--- a/src/filter/term.rs
+++ b/src/filter/term.rs
@@ -66,7 +66,7 @@ impl TermContext {
}
}
TermContext::Json(_, v) => {
- TermContext::Json(None, ValueWrapper::new(v.clone_val(), false))
+ TermContext::Json(None, ValueWrapper::new(v.get_val().clone(), false))
}
}
}
@@ -79,7 +79,7 @@ impl TermContext {
}
}
_ => {
- TermContext::Json(None, ValueWrapper::new(v.clone_val(), false))
+ TermContext::Json(None, ValueWrapper::new(v.get_val().clone(), false))
}
}
}
diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs
index 8b71639..a3feccd 100644
--- a/src/filter/value_filter.rs
+++ b/src/filter/value_filter.rs
@@ -1,13 +1,13 @@
use std::error::Error;
use std::result::Result;
+use std::ops::Deref;
use serde_json::Value;
-use ref_value::*;
-
-use parser::prelude::*;
use filter::term::*;
use filter::value_wrapper::*;
+use parser::prelude::*;
+use ref_value::model::*;
trait ArrayIndex {
fn index(&self, v: &RefValueWrapper) -> usize;
@@ -15,7 +15,7 @@ trait ArrayIndex {
fn take_value(&self, v: &RefValueWrapper) -> RefValueWrapper {
let idx = self.index(v);
match v.get(idx) {
- Some(v) => v,
+ Some(v) => v.clone(),
_ => RefValue::Null.into()
}
}
@@ -66,7 +66,7 @@ impl ValueFilter {
ValueFilter { vw: ValueWrapper::new(v, is_leaves), last_key: None, filter_mode }
}
- fn iter_to_value_vec<'a, I: Iterator- >(iter: I) -> Vec {
+ fn iter_to_value_vec<'a, I: Iterator
- >(iter: I) -> Vec {
iter
.map(|v| v.clone())
.filter(|v| !v.is_null())
@@ -98,8 +98,8 @@ impl ValueFilter {
}
}
- fn collect_all(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec) {
- match v.get_data_ref() {
+ fn collect_all(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec) {
+ match v.deref() {
RefValue::Array(vec) => {
if key.is_none() {
for v in vec {
@@ -107,7 +107,7 @@ impl ValueFilter {
}
}
for i in vec {
- Self::collect_all(key, &i.into(), buf);
+ Self::collect_all(key, i, buf);
}
}
RefValue::Object(v) => {
@@ -120,7 +120,7 @@ impl ValueFilter {
}
}
for (_, v) in v.into_iter() {
- Self::collect_all(key, &v.into(), buf);
+ Self::collect_all(key, v, buf);
}
}
_ => {}
@@ -154,7 +154,7 @@ impl ValueFilter {
pub fn step_in_all(&mut self) -> &ValueWrapper {
debug!("step_in_all");
- let vec = match self.vw.get_val().get_data_ref() {
+ let vec = match self.vw.get_val().deref() {
RefValue::Object(ref map) => {
Self::iter_to_value_vec(map.values())
}
@@ -162,12 +162,12 @@ impl ValueFilter {
Self::iter_to_value_vec(list.iter())
}
RefValue::Null => Vec::new(),
- _ => vec![self.vw.get_val().clone_data()]
+ _ => vec![self.vw.get_val().clone()]
};
self.last_key = Some(ValueFilterKey::All);
self.vw.replace(RefValue::Array(vec).into());
- trace!("step_in_all - {:?}", self.vw.get_val().get_data_ref());
+ trace!("step_in_all - {:?}", self.vw.get_val());
&self.vw
}
@@ -176,17 +176,17 @@ impl ValueFilter {
trace!("step_in_num - before: leaves {}, filterMode {} - {:?}"
, self.vw.is_leaves()
, self.filter_mode
- , self.vw.get_val().get_data_ref());
+ , self.vw.get_val());
let v = if self.vw.is_leaves() {
let filter_mode = self.filter_mode;
- match self.vw.get_val().get_data_ref() {
+ match self.vw.get_val().deref() {
RefValue::Array(ref vec) => {
let mut ret = Vec::new();
for v in vec {
- let wrapper = Self::get_nested_array(&v.into(), *key, filter_mode);
+ let wrapper = Self::get_nested_array(v, *key, filter_mode);
if !wrapper.is_null() {
- ret.push(wrapper.clone_data());
+ ret.push(wrapper.clone());
}
}
RefValue::Array(ret).into()
@@ -199,7 +199,7 @@ impl ValueFilter {
self.last_key = Some(ValueFilterKey::Num(key.index(&v)));
self.vw.replace(v);
- trace!("step_in_num - after: {:?}", self.vw.get_val().get_data_ref());
+ trace!("step_in_num - after: {:?}", self.vw.get_val());
&self.vw
}
@@ -212,28 +212,27 @@ impl ValueFilter {
trace!("step_in_string - before: {},{},{:?}"
, self.vw.is_leaves()
, self.filter_mode
- , self.vw.get_val().get_data_ref());
+ , self.vw.get_val());
let filter_mode = self.filter_mode;
let is_leaves = self.vw.is_leaves();
- let val = match self.vw.get_val().get_data_ref() {
+ let val = match self.vw.get_val().deref() {
RefValue::Array(ref vec) if is_leaves => {
let mut buf = Vec::new();
for mut v in vec {
- let wrapper: RefValueWrapper = v.into();
- if wrapper.is_array() {
- let vec = wrapper.as_array().unwrap();
+ if v.is_array() {
+ let vec = v.as_array().unwrap();
let mut ret = Vec::new();
for v in vec {
- let nested_wrapper = Self::get_nested_object(&v.into(), key, filter_mode);
+ let nested_wrapper = Self::get_nested_object(v, key, filter_mode);
if !nested_wrapper.is_null() {
- ret.push(nested_wrapper.clone_data());
+ ret.push(nested_wrapper.clone());
}
}
buf.append(&mut ret);
} else {
- match wrapper.get(key.clone()) {
- Some(v) => buf.push(v.clone_data()),
+ match v.get(key.clone()) {
+ Some(v) => buf.push(v.clone()),
_ => {}
}
}
@@ -244,9 +243,9 @@ impl ValueFilter {
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);
+ let wrapper = Self::get_nested_object(v, key, filter_mode);
if !wrapper.is_null() {
- ret.push(wrapper.clone_data());
+ ret.push(wrapper.clone());
}
}
RefValue::Array(ret).into()
@@ -264,7 +263,7 @@ impl ValueFilter {
trace!("step_in_string - after: {},{},{:?}"
, self.vw.is_leaves()
, self.filter_mode
- , self.vw.get_val().get_data_ref());
+ , self.vw.get_val());
&self.vw
}
}
@@ -304,7 +303,7 @@ impl JsonValueFilter {
if from_current {
self.filter_stack.last()
.map(|vf| {
- ValueFilter::new(vf.vw.clone_val(), vf.vw.is_leaves(), from_current)
+ ValueFilter::new(vf.vw.get_val().clone(), vf.vw.is_leaves(), from_current)
})
.and_then(|vf| {
Some(self.filter_stack.push(vf))
@@ -334,10 +333,10 @@ impl JsonValueFilter {
}
}
- pub fn current_value(&self) -> RefValueWrapper {
+ pub fn into_value(&self) -> Value {
match self.filter_stack.last() {
- Some(v) => v.vw.get_val().clone(),
- _ => RefValue::Null.into()
+ Some(v) => v.vw.into_value(),
+ _ => Value::Null
}
}
@@ -354,12 +353,12 @@ impl JsonValueFilter {
match self.filter_stack.last_mut() {
Some(ref mut vf) if vf.vw.is_array() && vf.vw.is_leaves() => {
let mut ret = Vec::new();
- if let RefValue::Array(val) = vf.vw.get_val().get_data_ref() {
+ if let RefValue::Array(val) = vf.vw.get_val().deref() {
for mut v in val {
for i in &indices {
- let v = i.take_value(&v.into());
+ let v = i.take_value(v);
if !v.is_null() {
- ret.push(v.clone_data());
+ ret.push(v.clone());
}
}
}
@@ -371,7 +370,7 @@ impl JsonValueFilter {
for i in indices {
let wrapper = i.take_value(&vf.vw.get_val());
if !wrapper.is_null() {
- ret.push(wrapper.clone_data());
+ ret.push(wrapper.clone());
}
}
vf.vw.replace(RefValue::Array(ret).into());
@@ -391,7 +390,7 @@ impl JsonValueFilter {
let to = match to {
Some(v) => v.index(val),
_ => {
- if let RefValue::Array(v) = val.get_data_ref() {
+ if let RefValue::Array(v) = val.deref() {
v.len()
} else {
0
@@ -401,24 +400,23 @@ impl JsonValueFilter {
(from, to)
}
- fn _range(from: usize, to: usize, v: &RefValueWrapper) -> Vec {
+ fn _range(from: usize, to: usize, v: &RefValueWrapper) -> Vec {
trace!("range - {}:{}", from, to);
(from..to).into_iter()
.map(|i| i.take_value(v))
.filter(|v| !v.is_null())
- .map(|v| v.clone_data())
+ .map(|v| v.clone())
.collect()
}
match self.filter_stack.last_mut() {
Some(ref mut vf) if vf.vw.is_array() && vf.vw.is_leaves() => {
let mut buf = Vec::new();
- if let RefValue::Array(vec) = vf.vw.get_val().get_data_ref() {
+ if let RefValue::Array(vec) = vf.vw.get_val().deref() {
for mut v in vec {
- let wrapper = v.into();
- let (from, to) = _from_to(from, to, &wrapper);
- let mut v: Vec = _range(from, to, &wrapper);
+ let (from, to) = _from_to(from, to, v);
+ let mut v: Vec = _range(from, to, v);
buf.append(&mut v);
}
}
@@ -426,7 +424,7 @@ impl JsonValueFilter {
}
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 vec: Vec = _range(from, to, vf.vw.get_val());
+ let vec: Vec = _range(from, to, vf.vw.get_val());
vf.vw.replace(RefValue::Array(vec).into());
}
_ => {}
@@ -489,7 +487,7 @@ impl JsonValueFilter {
match self.filter_stack.pop() {
Some(mut vf) => {
let is_leaves = vf.vw.is_leaves();
- match vf.vw.get_val().get_data_ref() {
+ match vf.vw.get_val().deref() {
RefValue::Null | RefValue::Bool(false) => {
self.replace_filter_stack(RefValue::Null.into(), is_leaves);
}
diff --git a/src/filter/value_wrapper.rs b/src/filter/value_wrapper.rs
index 355f279..314c81d 100644
--- a/src/filter/value_wrapper.rs
+++ b/src/filter/value_wrapper.rs
@@ -1,6 +1,9 @@
-use indexmap::map::IndexMap;
+use std::ops::Deref;
-use ref_value::*;
+use indexmap::IndexSet;
+use serde_json::Value;
+
+use ref_value::model::*;
use super::cmp::*;
use super::term::*;
@@ -40,7 +43,7 @@ impl ValueWrapper {
}
fn cmp_with_term(val: &RefValueWrapper, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool {
- match val.get_data_ref() {
+ match val.deref() {
RefValue::Bool(ref v1) => {
match et {
ExprTerm::Bool(v2) => if reverse { cmp_fn.cmp_bool(v2, v1) } else { cmp_fn.cmp_bool(v1, v2) },
@@ -63,10 +66,10 @@ impl ValueWrapper {
fn take_object_in_array(&self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option {
fn _filter_with_object bool>(v: &RefValueWrapper, key: &String, fun: F) -> bool {
- match v.get_data_ref() {
+ match v.deref() {
RefValue::Object(map) => {
match map.get(key) {
- Some(val) => fun(&val.into()),
+ Some(val) => fun(val),
_ => false
}
}
@@ -74,11 +77,11 @@ impl ValueWrapper {
}
}
- match self.val.get_data_ref() {
+ match self.val.deref() {
RefValue::Array(vec) => {
let mut ret = Vec::new();
for v in vec {
- if _filter_with_object(&v.into(), key, |vv| {
+ if _filter_with_object(v, key, |vv| {
Self::cmp_with_term(vv, et, cmp, false, reverse)
}) {
ret.push(v.clone());
@@ -104,11 +107,11 @@ impl ValueWrapper {
match self.take_with_key_type(key, et, &cmp, reverse) {
Some(vw) => vw,
_ => {
- match self.val.get_data_ref() {
+ match &(*self.val) {
RefValue::Array(vec) => {
let mut ret = Vec::new();
for v in vec {
- if Self::cmp_with_term(&v.into(), et, &cmp, false, reverse) {
+ if Self::cmp_with_term(v, et, &cmp, false, reverse) {
ret.push(v.clone());
}
}
@@ -127,14 +130,13 @@ impl ValueWrapper {
}
pub fn replace(&mut self, val: RefValueWrapper) {
- let is_null = match val.get_data_ref() {
+ let is_null = match val.deref() {
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 {
- let v = RefValueWrapper::wrap(RefValue::Null);
- RefValueWrapper::new(v)
+ RefValue::Null.into()
} else {
val
};
@@ -144,135 +146,98 @@ impl ValueWrapper {
&self.val
}
- pub fn clone_val(&self) -> RefValueWrapper {
- self.val.clone()
+ pub fn into_value(&self) -> Value {
+ self.get_val().into()
}
pub fn is_array(&self) -> bool {
self.val.is_array()
}
- 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);
- }
- }
- RefValue::Object(ref v) => {
- for (k, v) in v.into_iter() {
- acc.push_str(&*k.to_string());
- _fn(&v.into(), acc);
- }
- }
- }
- }
- let mut acc = String::new();
- _fn(v, &mut acc);
- acc
- }
-
- fn into_map(&self) -> IndexMap {
- let mut map = IndexMap::new();
- match self.val.get_data_ref() {
+ fn into_hashset(&self) -> IndexSet {
+ let mut hashset = IndexSet::new();
+ match self.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
- let wrapper = v.into();
- let key = Self::uuid(&wrapper);
- map.insert(key, wrapper);
+ hashset.insert(v.clone());
}
}
_ => {
- map.insert(Self::uuid(&self.val), self.val.clone());
+ hashset.insert(self.val.clone());
}
}
- map
+ hashset
}
pub fn except(&self, other: &Self) -> Self {
- let map = self.into_map();
- let mut ret: IndexMap = IndexMap::new();
- match other.val.get_data_ref() {
+ let hashset = self.into_hashset();
+ let mut ret: IndexSet = IndexSet::new();
+ match &(*other.val) {
RefValue::Array(ref v1) => {
for v in v1 {
- let wrapper = v.into();
- let key = Self::uuid(&wrapper);
- if !map.contains_key(&key) {
- ret.insert(key, wrapper);
+ if !hashset.contains(v) {
+ ret.insert(v.clone());
}
}
}
_ => {
- let key = Self::uuid(&other.val);
- if !map.contains_key(&key) {
- ret.insert(key, other.val.clone());
+ if !hashset.contains(&other.val) {
+ ret.insert(other.val.clone());
}
}
}
- let vec = ret.values().into_iter().map(|v| v.clone_data()).collect();
+ let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueWrapper::new(RefValue::Array(vec).into(), false)
}
pub fn intersect(&self, other: &Self) -> Self {
- let map = self.into_map();
- let mut ret: IndexMap = IndexMap::new();
- match other.val.get_data_ref() {
+ let hashset = self.into_hashset();
+ let mut ret: IndexSet = IndexSet::new();
+ match other.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
- let wrapper = v.into();
- let key = Self::uuid(&wrapper);
- if map.contains_key(&key) {
- ret.insert(key, wrapper);
+ if hashset.contains(v) {
+ ret.insert(v.clone());
}
}
}
_ => {
- let key = Self::uuid(&other.val);
- if map.contains_key(&key) {
- ret.insert(key, other.val.clone());
+ if hashset.contains(&other.val) {
+ ret.insert(other.val.clone());
}
}
}
- let vec = ret.values().into_iter().map(|v| v.clone_data()).collect();
+ let vec = ret.into_iter().map(|v| v.clone()).collect();
ValueWrapper::new(RefValue::Array(vec).into(), false)
}
pub fn union(&self, other: &Self) -> Self {
- let mut map = self.into_map();
- match other.val.get_data_ref() {
+ let mut hashset = self.into_hashset();
+ match other.val.deref() {
RefValue::Array(ref v1) => {
for v in v1 {
- let wrapper = v.into();
- let key = Self::uuid(&wrapper);
- if !map.contains_key(&key) {
- map.insert(key, wrapper);
+ if !hashset.contains(v) {
+ hashset.insert(v.clone());
}
}
}
_ => {
- let key = Self::uuid(&other.val);
- if !map.contains_key(&key) {
- map.insert(key, other.val.clone());
+ if !hashset.contains(&other.val) {
+ hashset.insert(other.val.clone());
}
}
}
let mut vw = ValueWrapper::new(RefValue::Null.into(), false);
- let list = map.values().into_iter().map(|val| val.clone_data()).collect();
+ let list = hashset.into_iter().map(|val| val.clone()).collect();
vw.replace(RefValue::Array(list).into());
vw
}
pub fn into_term(&self, key: &Option) -> TermContext {
- match self.val.get_data_ref() {
+ match self.val.deref() {
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)),
@@ -284,13 +249,12 @@ impl ValueWrapper {
}
pub fn filter(&self, key: &Option) -> Self {
- let v = match self.val.get_data_ref() {
+ let v = match self.val.deref() {
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() {
+ if v.get(k.clone()).is_some() {
ret.push(v.clone());
}
}
@@ -300,7 +264,7 @@ impl ValueWrapper {
RefValue::Object(ref map) => {
match key {
Some(ValueFilterKey::String(k)) => match map.get(k) {
- Some(v) => v.into(),
+ Some(v) => v.clone(),
_ => RefValue::Null.into()
},
_ => RefValue::Null.into()
diff --git a/src/lib.rs b/src/lib.rs
index 8de9510..fd6592b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -158,11 +158,18 @@
//! assert_eq!(ret, json);
//! ```
+extern crate env_logger;
+extern crate indexmap;
#[macro_use]
extern crate log;
-extern crate env_logger;
+extern crate serde;
extern crate serde_json;
-extern crate indexmap;
+
+use std::result;
+
+use serde_json::Value;
+
+use prelude::*;
#[doc(hidden)]
mod parser;
@@ -172,14 +179,6 @@ mod filter;
mod ref_value;
pub mod prelude;
-use parser::prelude::*;
-use filter::prelude::*;
-
-use std::result;
-use serde_json::Value;
-
-use ref_value::*;
-
type Result = result::Result;
/// # Read multiple Json multiple times with the same JsonPath
@@ -222,7 +221,7 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> Result + 'a {
Ok(n) => {
let mut jf = JsonValueFilter::new_from_value(json.into());
jf.visit(n.clone());
- Ok(jf.take_value().into_value())
+ Ok(jf.take_value().into())
}
Err(e) => Err(e.clone())
}
@@ -259,7 +258,7 @@ pub fn selector(json: &Value) -> impl FnMut(&str) -> Result {
let mut jf = JsonValueFilter::new_from_value(wrapper.clone());
let mut parser = Parser::new(path);
parser.parse(&mut jf)?;
- Ok(jf.take_value().into_value())
+ Ok(jf.take_value().into())
}
}
@@ -288,7 +287,7 @@ 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().into_value())
+ Ok(jf.take_value().into())
}
/// # Read Json using JsonPath - Deprecated. use select
@@ -296,3 +295,29 @@ pub fn read(json: &Value, path: &str) -> Result {
select(json, path)
}
+/// # Read Json string using JsonPath
+///
+/// ```rust
+/// extern crate jsonpath_lib as jsonpath;
+/// #[macro_use] extern crate serde_json;
+///
+/// use serde_json::Value;
+///
+/// let json_obj = json!({
+/// "school": {
+/// "friends": [{"id": 0}, {"id": 1}]
+/// },
+/// "friends": [{"id": 0}, {"id": 1}]
+/// });
+/// let json_str = jsonpath::select_str(&serde_json::to_string(&json_obj).unwrap(), "$..friends[0]").unwrap();
+/// let json: Value = serde_json::from_str(&json_str).unwrap();
+/// let ret = json!([ {"id": 0}, {"id": 0} ]);
+/// assert_eq!(json, ret);
+/// ```
+pub fn select_str(json: &str, path: &str) -> result::Result {
+ let ref_value: RefValue = serde_json::from_str(json).map_err(|e| format!("{:?}", e))?;
+ let mut jf = JsonValueFilter::new_from_value(ref_value.into());
+ let mut parser = Parser::new(path);
+ parser.parse(&mut jf)?;
+ serde_json::to_string(&jf.take_value()).map_err(|e| format!("{:?}", e))
+}
\ No newline at end of file
diff --git a/src/prelude.rs b/src/prelude.rs
index 91c3ae2..ddebc84 100644
--- a/src/prelude.rs
+++ b/src/prelude.rs
@@ -1,3 +1,3 @@
pub use parser::prelude::*;
pub use filter::prelude::*;
-pub use ref_value::*;
\ No newline at end of file
+pub use ref_value::model::*;
\ No newline at end of file
diff --git a/src/ref_value/convert.rs b/src/ref_value/convert.rs
new file mode 100644
index 0000000..887c206
--- /dev/null
+++ b/src/ref_value/convert.rs
@@ -0,0 +1,111 @@
+use std::ops::Deref;
+
+use indexmap::IndexMap;
+use serde_json::Value;
+
+use ref_value::model::{RefValue, RefValueWrapper};
+
+pub struct RefValueConverter;
+
+impl RefValueConverter {
+ pub fn new(value: &Value) -> RefValueWrapper {
+ RefValueConverter {}.visit_value(value)
+ }
+
+ fn visit_value(&self, value: &Value) -> RefValueWrapper {
+ 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) -> RefValueWrapper {
+ RefValue::Null.into()
+ }
+
+ fn visit_bool(&self, value: &bool) -> RefValueWrapper {
+ RefValue::Bool(*value).into()
+ }
+
+ fn visit_number(&self, value: &serde_json::Number) -> RefValueWrapper {
+ RefValue::Number(value.clone()).into()
+ }
+
+ fn visit_string(&self, value: &String) -> RefValueWrapper {
+ RefValue::String(value.to_string()).into()
+ }
+
+ fn visit_array(&self, value: &Vec) -> RefValueWrapper {
+ let mut values = Vec::new();
+ for v in value {
+ values.push(self.visit_value(v));
+ }
+ RefValue::Array(values).into()
+ }
+
+ fn visit_object(&self, value: &serde_json::Map) -> RefValueWrapper {
+ let mut map = IndexMap::new();
+ for (key, _) in value {
+ let value = self.visit_value(match value.get(key) {
+ Some(v) => v,
+ _ => &Value::Null
+ });
+ map.insert(key.clone(), value);
+ }
+ RefValue::Object(map).into()
+ }
+}
+
+pub struct ValueConverter;
+
+impl ValueConverter {
+ pub fn new(value: &RefValueWrapper) -> Value {
+ ValueConverter {}.visit_value(value)
+ }
+
+ fn visit_value(&self, value: &RefValueWrapper) -> Value {
+ match value.deref() {
+ 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) -> 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) -> Value {
+ let mut ret = serde_json::Map::new();
+ let tmp_null = &RefValue::Null.into();
+ for (k, _) in map {
+ let value = self.visit_value(match map.get(k) {
+ Some(e) => e,
+ _ => tmp_null
+ });
+ ret.insert(k.to_string(), value);
+ }
+ Value::Object(ret)
+ }
+}
\ No newline at end of file
diff --git a/src/ref_value/de.rs b/src/ref_value/de.rs
new file mode 100644
index 0000000..b5f3311
--- /dev/null
+++ b/src/ref_value/de.rs
@@ -0,0 +1,119 @@
+use std::error::Error;
+use std::fmt;
+use std::result::Result;
+
+use indexmap::IndexMap;
+use serde::{Deserialize, Deserializer};
+use serde::de::{MapAccess, SeqAccess, Visitor};
+use serde_json::Value;
+
+use super::model::*;
+
+impl<'de> Deserialize<'de> for RefValue {
+ fn deserialize(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ 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(self, v: bool) -> Result
+ where
+ E: Error, {
+ Ok(RefValue::Bool(v))
+ }
+
+ fn visit_i64(self, v: i64) -> Result
+ where
+ E: serde::de::Error, {
+ Ok(RefValue::Number(v.into()))
+ }
+
+ fn visit_u64(self, v: u64) -> Result
+ where
+ E: serde::de::Error, {
+ Ok(RefValue::Number(v.into()))
+ }
+
+ fn visit_f64(self, v: f64) -> Result
+ 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(self, v: &str) -> Result
+ where
+ E: serde::de::Error, {
+ self.visit_string(String::from(v))
+ }
+
+ fn visit_string(self, v: String) -> Result
+ where
+ E: serde::de::Error, {
+ Ok(RefValue::String(v))
+ }
+
+ fn visit_none(self) -> Result
+ where
+ E: serde::de::Error, {
+ Ok(RefValue::Null)
+ }
+
+ fn visit_some(self, deserializer: D) -> Result where
+ D: Deserializer<'de>, {
+ Deserialize::deserialize(deserializer)
+ }
+
+ fn visit_unit(self) -> Result
+ where
+ E: serde::de::Error, {
+ Ok(RefValue::Null)
+ }
+
+ fn visit_seq(self, mut visitor: A) -> Result
+ 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(self, mut visitor: A) -> Result
+ 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())),
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ref_value/mod.rs b/src/ref_value/mod.rs
index cb5310b..080642b 100644
--- a/src/ref_value/mod.rs
+++ b/src/ref_value/mod.rs
@@ -1,382 +1,5 @@
-extern crate indexmap;
-extern crate serde_json;
-
-use std::sync::Arc;
-use std::convert::Into;
-
-use indexmap::map::IndexMap;
-use serde_json::{Number, Value};
-
-pub type TypeRefValue = Arc>;
-
-impl Into for TypeRefValue {
- fn into(self) -> RefValueWrapper {
- RefValueWrapper::new(self.clone())
- }
-}
-
-impl Into 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(&self, index: I) -> Option {
- 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> {
- (**self.data).as_object()
- }
-
- pub fn is_array(&self) -> bool {
- (**self.data).is_array()
- }
-
- pub fn as_array(&self) -> Option<&Vec> {
- (**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 {
- (**self.data).as_number()
- }
-
- pub fn is_boolean(&self) -> bool {
- (**self.data).is_boolean()
- }
-
- pub fn as_bool(&self) -> Option {
- (**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 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),
- Object(IndexMap),
-}
-
-impl RefValue {
- pub fn get(&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> {
- 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> {
- 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 {
- 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 {
- 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 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.clone()))
- }
- fn visit_string(&self, value: &String) -> TypeRefValue {
- RefValueWrapper::wrap(RefValue::String(value.to_string()))
- }
- fn visit_array(&self, value: &Vec) -> 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, value: &serde_json::Map) -> TypeRefValue {
- let mut map = IndexMap::new();
- let keys: Vec = value.keys().into_iter().map(|k| k.to_string()).collect();
- for k in keys {
- let value = self.visit_value(match value.get(&k) {
- Some(v) => v,
- _ => &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) -> 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) -> Value {
- let mut ret = serde_json::Map::new();
- let keys: Vec = 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)
- }
-}
\ No newline at end of file
+pub mod model;
+mod convert;
+pub mod de;
+pub mod ser;
+//mod utf8;
\ No newline at end of file
diff --git a/src/ref_value/model.rs b/src/ref_value/model.rs
new file mode 100644
index 0000000..c977b2a
--- /dev/null
+++ b/src/ref_value/model.rs
@@ -0,0 +1,257 @@
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+use std::sync::Arc;
+
+use indexmap::map::IndexMap;
+use serde_json::{Number, Value};
+
+use super::convert::*;
+
+type TypeRefValue = Arc>;
+
+#[derive(Debug, PartialEq)]
+pub struct RefValueWrapper {
+ data: TypeRefValue
+}
+
+impl Eq for RefValueWrapper {}
+
+impl Deref for RefValueWrapper {
+ type Target = RefValue;
+
+ fn deref(&self) -> &Self::Target {
+ &(**self.data)
+ }
+}
+
+impl Hash for RefValueWrapper {
+ fn hash(&self, state: &mut H) {
+ self.deref().hash(state)
+ }
+}
+
+impl Clone for RefValueWrapper {
+ fn clone(&self) -> Self {
+ RefValueWrapper {
+ data: self.data.clone()
+ }
+ }
+}
+
+///
+/// serde_json::Value 참고
+///
+pub trait RefIndex {
+ fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper>;
+ fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper>;
+ fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper;
+}
+
+impl RefIndex for usize {
+ fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper> {
+ match *v {
+ RefValue::Array(ref vec) => vec.get(*self),
+ _ => None,
+ }
+ }
+ fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper> {
+ match *v {
+ RefValue::Array(ref mut vec) => vec.get_mut(*self),
+ _ => None,
+ }
+ }
+ fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper {
+ 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 RefValueWrapper> {
+ match *v {
+ RefValue::Object(ref map) => map.get(self),
+ _ => None,
+ }
+ }
+ fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper> {
+ match *v {
+ RefValue::Object(ref mut map) => map.get_mut(self),
+ _ => None,
+ }
+ }
+ fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper {
+ if let RefValue::Null = *v {
+ *v = RefValue::Object(IndexMap::new());
+ }
+ match *v {
+ RefValue::Object(ref mut map) => {
+ map.entry(self.to_owned()).or_insert(RefValue::Null.into())
+ }
+ _ => panic!("cannot access key {:?} in JSON {:?}", self, v),
+ }
+ }
+}
+
+impl RefIndex for String {
+ fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v RefValueWrapper> {
+ self[..].index_into(v)
+ }
+ fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut RefValueWrapper> {
+ self[..].index_into_mut(v)
+ }
+ fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut RefValueWrapper {
+ self[..].index_or_insert(v)
+ }
+}
+
+#[derive(Debug, PartialEq)]
+pub enum RefValue {
+ Null,
+ Bool(bool),
+ Number(Number),
+ String(String),
+ Array(Vec),
+ Object(IndexMap),
+}
+
+impl Hash for RefValue {
+ fn hash(&self, state: &mut H) {
+ match self {
+ RefValue::Null => RefValue::Null.hash(state),
+ RefValue::Bool(b) => b.hash(state),
+ RefValue::Number(n) => {
+ if n.is_f64() {
+ n.as_f64().unwrap().to_string().hash(state)
+ } else if n.is_i64() {
+ n.as_i64().unwrap().hash(state);
+ } else {
+ n.as_u64().unwrap().hash(state);
+ }
+ }
+ RefValue::String(s) => s.hash(state),
+ RefValue::Object(map) => {
+ for (_, v) in map {
+ v.hash(state);
+ }
+ }
+ RefValue::Array(v) => {
+ for i in v {
+ i.hash(state);
+ }
+ }
+ }
+ }
+}
+
+impl Eq for RefValue {}
+
+impl RefValue {
+ pub fn get(&self, index: I) -> Option<&RefValueWrapper> {
+ index.index_into(self)
+ }
+
+ pub fn is_object(&self) -> bool {
+ self.as_object().is_some()
+ }
+
+ pub fn as_object(&self) -> Option<&IndexMap> {
+ 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> {
+ 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 {
+ 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 {
+ 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 for RefValue {
+ fn into(self) -> RefValueWrapper {
+ RefValueWrapper {
+ data: Arc::new(Box::new(self))
+ }
+ }
+}
+
+impl Into for &Value {
+ fn into(self) -> RefValueWrapper {
+ RefValueConverter::new(&self)
+ }
+}
+
+impl Into for RefValueWrapper {
+ fn into(self) -> Value {
+ ValueConverter::new(&self)
+ }
+}
+
+impl Into for &RefValueWrapper {
+ fn into(self) -> Value {
+ ValueConverter::new(&self)
+ }
+}
\ No newline at end of file
diff --git a/src/ref_value/ser.rs b/src/ref_value/ser.rs
new file mode 100644
index 0000000..a4a214d
--- /dev/null
+++ b/src/ref_value/ser.rs
@@ -0,0 +1,63 @@
+use std::result::Result;
+
+use serde::{self, Serialize};
+
+use ref_value::model::{RefValue, RefValueWrapper};
+
+impl Serialize for RefValue {
+ #[inline]
+ fn serialize
(&self, serializer: S) -> Result where
+ S: serde::Serializer {
+ match *self {
+ RefValue::Null => serializer.serialize_unit(),
+ RefValue::Bool(b) => serializer.serialize_bool(b),
+ RefValue::Number(ref n) => n.serialize(serializer),
+ RefValue::String(ref s) => serializer.serialize_str(s),
+ RefValue::Array(ref v) => {
+ use std::ops::Deref;
+ let v: Vec<&RefValue> = v.iter().map(|v| v.deref()).collect();
+ v.serialize(serializer)
+ },
+ RefValue::Object(ref m) => {
+ use serde::ser::SerializeMap;
+ use std::ops::Deref;
+ let mut map = serializer.serialize_map(Some(m.len()))?;
+ for (k, v) in m {
+ map.serialize_key(k)?;
+ map.serialize_value(v.deref())?;
+ }
+ map.end()
+ }
+ }
+ }
+}
+
+impl Serialize for RefValueWrapper {
+ #[inline]
+ fn serialize(&self, serializer: S) -> Result where
+ S: serde::Serializer {
+ use std::ops::Deref;
+
+ match *self.deref() {
+ RefValue::Null => serializer.serialize_unit(),
+ RefValue::Bool(b) => serializer.serialize_bool(b),
+ RefValue::Number(ref n) => n.serialize(serializer),
+ RefValue::String(ref s) => serializer.serialize_str(s),
+ RefValue::Array(ref v) => {
+ use std::ops::Deref;
+ let v: Vec<&RefValue> = v.iter().map(|v| v.deref()).collect();
+ v.serialize(serializer)
+ },
+ RefValue::Object(ref m) => {
+ use serde::ser::SerializeMap;
+ use std::ops::Deref;
+ let mut map = serializer.serialize_map(Some(m.len()))?;
+ for (k, v) in m {
+ map.serialize_key(k)?;
+ map.serialize_value(v.deref())?;
+ }
+ map.end()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ref_value/utf8.rs b/src/ref_value/utf8.rs
new file mode 100644
index 0000000..d798531
--- /dev/null
+++ b/src/ref_value/utf8.rs
@@ -0,0 +1,52 @@
+// Copyright 2017 Serde Developers
+//
+// Licensed under the Apache License, Version 2.0 or the MIT license
+// , 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()
+ }
+}
diff --git a/tests/filter.rs b/tests/filter.rs
index 7854698..0db5c3b 100644
--- a/tests/filter.rs
+++ b/tests/filter.rs
@@ -64,7 +64,8 @@ fn step_in() {
"Vincent Cannon",
"Gray Berry"
]);
- assert_eq!(friends, current.get_val().into_value());
+
+ assert_eq!(friends, current.into_value());
}
let mut jf = new_value_filter("./benches/data_obj.json");
{
@@ -77,7 +78,7 @@ fn step_in() {
"Vincent Cannon",
"Gray Berry"
]);
- assert_eq!(names, current.get_val().into_value());
+ assert_eq!(names, current.into_value());
}
}
@@ -91,32 +92,32 @@ fn array() {
]);
let jf = do_filter("$.school.friends[1, 2]", "./benches/data_obj.json");
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.into_value());
let jf = do_filter("$.school.friends[1:]", "./benches/data_obj.json");
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.into_value());
}
#[test]
@@ -132,16 +133,16 @@ fn return_type() {
});
let jf = do_filter("$.school", "./benches/data_obj.json");
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.into_value());
let jf = do_filter("$.school[?(@.friends[0])]", "./benches/data_obj.json");
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.into_value());
let jf = do_filter("$.school[?(@.friends[10])]", "./benches/data_obj.json");
- assert_eq!(Value::Null, jf.current_value().into_value());
+ assert_eq!(Value::Null, jf.into_value());
let jf = do_filter("$.school[?(1==1)]", "./benches/data_obj.json");
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.into_value());
let jf = do_filter("$.school.friends[?(1==1)]", "./benches/data_obj.json");
let friends = json!([
@@ -149,7 +150,7 @@ fn return_type() {
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]);
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.into_value());
}
#[test]
@@ -164,42 +165,42 @@ fn op() {
{"id": 2, "name": "Gray Berry"}
]
});
- assert_eq!(friends, jf.current_value().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.into_value());
let jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json");
- assert_eq!(Value::Null, jf.current_value().into_value());
+ assert_eq!(Value::Null, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.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().into_value());
+ assert_eq!(friends, jf.into_value());
}
#[test]
@@ -208,10 +209,10 @@ fn example() {
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().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..author", "./benches/example.json");
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$.store.*", "./benches/example.json");
let ret = json!([
@@ -223,11 +224,11 @@ fn example() {
],
{"color" : "red","price" : 19.95},
]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.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().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..book[2]", "./benches/example.json");
let ret = json!([{
@@ -237,7 +238,7 @@ fn example() {
"isbn" : "0-553-21311-3",
"price" : 8.99
}]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..book[-2]", "./benches/example.json");
let ret = json!([{
@@ -247,7 +248,7 @@ fn example() {
"isbn" : "0-553-21311-3",
"price" : 8.99
}]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..book[0,1]", "./benches/example.json");
let ret = json!([
@@ -264,7 +265,7 @@ fn example() {
"price" : 12.99
}
]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..book[:2]", "./benches/example.json");
let ret = json!([
@@ -281,7 +282,7 @@ fn example() {
"price" : 12.99
}
]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..book[2:]", "./benches/example.json");
let ret = json!([
@@ -300,7 +301,7 @@ fn example() {
"price" : 22.99
}
]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$..book[?(@.isbn)]", "./benches/example.json");
let ret = json!([
@@ -319,7 +320,7 @@ fn example() {
"price" : 22.99
}
]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.into_value());
let jf = do_filter("$.store.book[?(@.price < 10)]", "./benches/example.json");
let ret = json!([
@@ -337,9 +338,9 @@ fn example() {
"price" : 8.99
}
]);
- assert_eq!(ret, jf.current_value().into_value());
+ assert_eq!(ret, jf.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().into_value());
+ assert_eq!(json, jf.into_value());
}
\ No newline at end of file
diff --git a/tests/lib.rs b/tests/lib.rs
index d19a9e1..45f8469 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -15,6 +15,13 @@ fn read_json(path: &str) -> Value {
serde_json::from_str(contents.as_str()).unwrap()
}
+fn read_contents(path: &str) -> String {
+ let mut f = std::fs::File::open(path).unwrap();
+ let mut contents = String::new();
+ f.read_to_string(&mut contents).unwrap();
+ contents
+}
+
#[test]
fn compile() {
let mut template = jsonpath::compile("$..friends[2]");
@@ -66,4 +73,19 @@ fn select() {
"price" : 8.99
}]);
assert_eq!(json, ret);
+}
+
+#[test]
+fn select_str() {
+ let json_str = read_contents("./benches/example.json");
+ let result_str = jsonpath::select_str(&json_str, "$..book[2]").unwrap();
+ let ret = json!([{
+ "category" : "fiction",
+ "author" : "Herman Melville",
+ "title" : "Moby Dick",
+ "isbn" : "0-553-21311-3",
+ "price" : 8.99
+ }]);
+ let json: Value = serde_json::from_str(&result_str).unwrap();
+ assert_eq!(json, ret);
}
\ No newline at end of file
diff --git a/tests/serde.rs b/tests/serde.rs
new file mode 100644
index 0000000..09422ef
--- /dev/null
+++ b/tests/serde.rs
@@ -0,0 +1,39 @@
+extern crate jsonpath_lib as jsonpath;
+extern crate serde_json;
+
+use std::io::Read;
+
+use serde_json::Value;
+
+use jsonpath::prelude::*;
+
+fn read_json(path: &str) -> String {
+ let mut f = std::fs::File::open(path).unwrap();
+ let mut contents = String::new();
+ f.read_to_string(&mut contents).unwrap();
+ contents
+}
+
+#[test]
+fn de() {
+ let json_str = read_json("./benches/example.json");
+ // RefValue -> Value
+ let ref_value: RefValue = serde_json::from_str(json_str.as_str()).unwrap();
+ let value_wrapper: RefValueWrapper = ref_value.into();
+ let value: Value = value_wrapper.into();
+
+ // Value
+ let json: Value = serde_json::from_str(json_str.as_str()).unwrap();
+ assert_eq!(value, json);
+}
+
+#[test]
+fn ser() {
+ let json_str = read_json("./benches/example.json");
+ let ref_value: RefValue = serde_json::from_str(json_str.as_str()).unwrap();
+ let ref_value_str = serde_json::to_string(&ref_value).unwrap();
+
+ let json: Value = serde_json::from_str(json_str.as_str()).unwrap();
+ let json_str = serde_json::to_string(&json).unwrap();
+ assert_eq!(ref_value_str, json_str);
+}
\ No newline at end of file
diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml
index 8a606db..ba881df 100644
--- a/wasm/Cargo.toml
+++ b/wasm/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "jsonpath-wasm"
-version = "0.1.4"
+version = "0.1.5"
authors = ["Changseok Han "]
description = "JsonPath Webassembly version compiled by Rust - Demo: https://freestrings.github.io/jsonpath"
keywords = ["library", "jsonpath", "json", "webassembly"]
diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs
index a104dcf..3319b24 100644
--- a/wasm/src/lib.rs
+++ b/wasm/src/lib.rs
@@ -29,14 +29,14 @@ cfg_if! {
fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue {
let mut jf = JsonValueFilter::new_from_value(json);
jf.visit(node);
- let taken = jf.take_value().into_value();
+ let taken: Value = jf.take_value().into();
match JsValue::from_serde(&taken) {
Ok(js_value) => js_value,
Err(e) => JsValue::from_str(&format!("Json deserialize error: {:?}", e))
}
}
-fn into_serde_json(js_value: &JsValue) -> Result {
+fn into_serde_json(js_value: &JsValue) -> Result {
if js_value.is_string() {
match serde_json::from_str(js_value.as_string().unwrap().as_str()) {
Ok(json) => Ok(json),
@@ -52,7 +52,7 @@ fn into_serde_json(js_value: &JsValue) -> Result {
fn into_ref_value(js_value: &JsValue, node: Node) -> JsValue {
match into_serde_json(js_value) {
- Ok(json) => filter_ref_value((&json).into(), node),
+ Ok(json) => filter_ref_value(json.into(), node),
Err(e) => JsValue::from_str(&format!("Json serialize error: {}", e))
}
}
@@ -85,7 +85,7 @@ pub fn alloc_json(js_value: JsValue) -> usize {
let mut idx = CACHE_JSON_IDX.lock().unwrap();
*idx += 1;
- map.insert(*idx, (&json).into());
+ map.insert(*idx, json.into());
*idx
}
Err(e) => {
@@ -136,7 +136,7 @@ pub fn selector(js_value: JsValue) -> JsValue {
}
_ => {
match into_serde_json(&js_value) {
- Ok(json) => (&json).into(),
+ Ok(json) => json.into(),
Err(e) => return JsValue::from_str(e.as_str())
}
}