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()) } }