diff --git a/Cargo.toml b/Cargo.toml index f90ba25..f079118 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath_lib" -version = "0.1.6" +version = "0.1.7" authors = ["Changseok Han "] description = "JsonPath in Rust and Webassembly - Webassembly Demo: https://freestrings.github.io/jsonpath" @@ -18,7 +18,7 @@ travis-ci = { repository = "freestrings/jsonpath", branch = "master" } [dependencies] log = "0.4" env_logger = "0.6.0" -serde = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["preserve_order"] } indexmap = "1.0.2" diff --git a/README.md b/README.md index 5fb2281..f0ee3f8 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,8 @@ 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::select_as_str(json_str: &str, jsonpath: &str)](#rust---jsonpathselect_as_strjson-str-jsonpath-str) +- [rust - jsonpath::select_as\(json_str: &str, jsonpath: &str)](#rust---jsonpathselect_astjson-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) @@ -209,16 +210,46 @@ let ret = json!([ {"id": 0}, {"id": 0} ]); assert_eq!(json, ret) ``` -### rust - jsonpath::select_str(json: &str, jsonpath: &str) +### rust - jsonpath::select_as_str(json: &str, jsonpath: &str) ```rust -let ret = jsonpath::select_str(r#"{ +let ret = jsonpath::select_as_str(r#"{ "school": { "friends": [{"id": 0}, {"id": 1}] }, "friends": [{"id": 0}, {"id": 1}] }"#, "$..friends[0]").unwrap(); assert_eq!(ret, r#"[{"id":0},{"id":0}]"#); ``` +### rust - jsonpath::select_as\(json: &str, jsonpath: &str) + +```rust +#[derive(Serialize, Deserialize, PartialEq, Debug)] +struct Person { + name: String, + age: u8, + phones: Vec, +} +let ret: Person = jsonpath::select_as(r#" +{ + "person": + { + "name": "Doe John", + "age": 44, + "phones": [ + "+44 1234567", + "+44 2345678" + ] + } +} +"#, "$.person").unwrap(); +let person = Person { + name: "Doe John".to_string(), + age: 44, + phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], +}; +assert_eq!(person, ret); +``` + ### rust - jsonpath::compile(jsonpath: &str) ```rust diff --git a/benches/bench.rs b/benches/bench.rs index 0dc42ff..29ef0a7 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -1,10 +1,14 @@ #![feature(test)] extern crate jsonpath_lib as jsonpath; +extern crate serde; extern crate serde_json; extern crate test; use std::io::Read; + +use serde::Deserialize; use serde_json::Value; + use self::test::Bencher; fn read_json(path: &str) -> String { @@ -68,3 +72,23 @@ fn bench_compile(b: &mut Bencher) { } }); } + + +#[bench] +fn bench_select_as(b: &mut Bencher) { + let json = get_string(); + + #[derive(Deserialize, PartialEq, Debug)] + struct Book { + category: String, + author: String, + title: String, + price: f64 + } + + b.iter(move || { + for _ in 1..100 { + let _: Book = jsonpath::select_as(&json, r#"$..book[?(@.price<30 && @.category=="fiction")][0]"#).unwrap(); + } + }); +} \ No newline at end of file diff --git a/docs/0.bootstrap.js b/docs/0.bootstrap.js index 3404cfb..8456ce7 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_wrapper100, __wbindgen_closure_wrapper102, __wbindgen_throw */ +/*! exports provided: alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __widl_f_log_1_, __wbindgen_string_new, __wbindgen_number_get, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper102, __wbindgen_closure_wrapper104, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __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_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?"); +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_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_wrapper102\", function() { return __wbindgen_closure_wrapper102; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper104\", function() { return __wbindgen_closure_wrapper104; });\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_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\nlet passStringToWasm;\nif (typeof cachedTextEncoder.encodeInto === 'function') {\n passStringToWasm = function(arg) {\n\n let size = arg.length;\n let ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_malloc\"](size);\n let writeOffset = 0;\n while (true) {\n const view = getUint8Memory().subarray(ptr + writeOffset, ptr + size);\n const { read, written } = cachedTextEncoder.encodeInto(arg, view);\n arg = arg.substring(read);\n writeOffset += written;\n if (arg.length === 0) {\n break;\n }\n ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_realloc\"](ptr, size, size * 2);\n size *= 2;\n }\n WASM_VECTOR_LEN = writeOffset;\n return ptr;\n };\n} else {\n passStringToWasm = function(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}\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\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) { return addHeapObject(getStringFromWasm(p, l)); }\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) { return typeof(getObject(i)) === 'string' ? 1 : 0; }\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) { return addHeapObject(JSON.parse(getStringFromWasm(ptr, len))); }\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_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_closure_wrapper104(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_object_clone_ref(idx) {\n return addHeapObject(getObject(idx));\n}\n\nfunction __wbindgen_object_drop_ref(i) { dropObject(i); }\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?"); /***/ }), @@ -16,7 +16,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /*!********************************************!*\ !*** ../browser_pkg/jsonpath_wasm_bg.wasm ***! \********************************************/ -/*! exports provided: memory, alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __wbindgen_malloc, __wbindgen_free, __wbg_function_table */ +/*! exports provided: memory, alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __wbindgen_malloc, __wbindgen_realloc, __wbindgen_free, __wbg_function_table */ /***/ (function(module, exports, __webpack_require__) { eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __webpack_require__.w[module.i];\n__webpack_require__.r(exports);\n// export exports from WebAssembly module\nfor(var name in wasmExports) if(name != \"__webpack_init__\") exports[name] = wasmExports[name];\n// exec imports from WebAssembly module (for esm order)\n/* harmony import */ var m0 = __webpack_require__(/*! ./jsonpath_wasm */ \"../browser_pkg/jsonpath_wasm.js\");\n\n\n// exec wasm module\nwasmExports[\"__webpack_init__\"]()\n\n//# sourceURL=webpack:///../browser_pkg/jsonpath_wasm_bg.wasm?"); diff --git a/docs/bench/0.bootstrap.js b/docs/bench/0.bootstrap.js index c354644..9b2334a 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_wrapper100, __wbindgen_closure_wrapper102, __wbindgen_throw */ +/*! exports provided: alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __widl_f_log_1_, __wbindgen_string_new, __wbindgen_number_get, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper102, __wbindgen_closure_wrapper104, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __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_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?"); +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_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_wrapper102\", function() { return __wbindgen_closure_wrapper102; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper104\", function() { return __wbindgen_closure_wrapper104; });\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_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\nlet passStringToWasm;\nif (typeof cachedTextEncoder.encodeInto === 'function') {\n passStringToWasm = function(arg) {\n\n let size = arg.length;\n let ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_malloc\"](size);\n let writeOffset = 0;\n while (true) {\n const view = getUint8Memory().subarray(ptr + writeOffset, ptr + size);\n const { read, written } = cachedTextEncoder.encodeInto(arg, view);\n arg = arg.substring(read);\n writeOffset += written;\n if (arg.length === 0) {\n break;\n }\n ptr = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbindgen_realloc\"](ptr, size, size * 2);\n size *= 2;\n }\n WASM_VECTOR_LEN = writeOffset;\n return ptr;\n };\n} else {\n passStringToWasm = function(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}\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\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) { return addHeapObject(getStringFromWasm(p, l)); }\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) { return typeof(getObject(i)) === 'string' ? 1 : 0; }\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) { return addHeapObject(JSON.parse(getStringFromWasm(ptr, len))); }\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_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_closure_wrapper104(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_object_clone_ref(idx) {\n return addHeapObject(getObject(idx));\n}\n\nfunction __wbindgen_object_drop_ref(i) { dropObject(i); }\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?"); /***/ }), @@ -16,7 +16,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) * /*!********************************************!*\ !*** ../browser_pkg/jsonpath_wasm_bg.wasm ***! \********************************************/ -/*! exports provided: memory, alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __wbindgen_malloc, __wbindgen_free, __wbg_function_table */ +/*! exports provided: memory, alloc_json, dealloc_json, compile, reader, selector, select, read, testa, __wbindgen_malloc, __wbindgen_realloc, __wbindgen_free, __wbg_function_table */ /***/ (function(module, exports, __webpack_require__) { eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __webpack_require__.w[module.i];\n__webpack_require__.r(exports);\n// export exports from WebAssembly module\nfor(var name in wasmExports) if(name != \"__webpack_init__\") exports[name] = wasmExports[name];\n// exec imports from WebAssembly module (for esm order)\n/* harmony import */ var m0 = __webpack_require__(/*! ./jsonpath_wasm */ \"../browser_pkg/jsonpath_wasm.js\");\n\n\n// exec wasm module\nwasmExports[\"__webpack_init__\"]()\n\n//# sourceURL=webpack:///../browser_pkg/jsonpath_wasm_bg.wasm?"); diff --git a/docs/bench/bootstrap.js b/docs/bench/bootstrap.js index f8a1b6b..81fd207 100644 --- a/docs/bench/bootstrap.js +++ b/docs/bench/bootstrap.js @@ -61,6 +61,9 @@ /******/ "__wbindgen_object_drop_ref": function(p0i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32); /******/ }, +/******/ "__wbindgen_object_clone_ref": function(p0i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32); +/******/ }, /******/ "__wbindgen_cb_forget": function(p0i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32); /******/ }, @@ -82,17 +85,14 @@ /******/ "__wbindgen_string_get": function(p0i32,p1i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32); /******/ }, -/******/ "__wbindgen_object_clone_ref": function(p0i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32); -/******/ }, /******/ "__wbindgen_throw": function(p0i32,p1i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ }, -/******/ "__wbindgen_closure_wrapper100": function(p0i32,p1i32,p2i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper100"](p0i32,p1i32,p2i32); -/******/ }, /******/ "__wbindgen_closure_wrapper102": function(p0i32,p1i32,p2i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper102"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbindgen_closure_wrapper104": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper104"](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":"e354e10adee0b37b85d7"}[wasmModuleId] + ".module.wasm"); +/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"c615fa3fad4c084c8bcd"}[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/c615fa3fad4c084c8bcd.module.wasm b/docs/bench/c615fa3fad4c084c8bcd.module.wasm new file mode 100644 index 0000000..e770f40 Binary files /dev/null and b/docs/bench/c615fa3fad4c084c8bcd.module.wasm differ diff --git a/docs/bench/e354e10adee0b37b85d7.module.wasm b/docs/bench/e354e10adee0b37b85d7.module.wasm deleted file mode 100644 index 83d18f9..0000000 Binary files a/docs/bench/e354e10adee0b37b85d7.module.wasm and /dev/null differ diff --git a/docs/bootstrap.js b/docs/bootstrap.js index 117aa80..7c92c09 100644 --- a/docs/bootstrap.js +++ b/docs/bootstrap.js @@ -61,6 +61,9 @@ /******/ "__wbindgen_object_drop_ref": function(p0i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32); /******/ }, +/******/ "__wbindgen_object_clone_ref": function(p0i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32); +/******/ }, /******/ "__wbindgen_cb_forget": function(p0i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32); /******/ }, @@ -82,17 +85,14 @@ /******/ "__wbindgen_string_get": function(p0i32,p1i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32); /******/ }, -/******/ "__wbindgen_object_clone_ref": function(p0i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32); -/******/ }, /******/ "__wbindgen_throw": function(p0i32,p1i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ }, -/******/ "__wbindgen_closure_wrapper100": function(p0i32,p1i32,p2i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper100"](p0i32,p1i32,p2i32); -/******/ }, /******/ "__wbindgen_closure_wrapper102": function(p0i32,p1i32,p2i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper102"](p0i32,p1i32,p2i32); +/******/ }, +/******/ "__wbindgen_closure_wrapper104": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper104"](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":"e354e10adee0b37b85d7"}[wasmModuleId] + ".module.wasm"); +/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"c615fa3fad4c084c8bcd"}[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/c615fa3fad4c084c8bcd.module.wasm b/docs/c615fa3fad4c084c8bcd.module.wasm new file mode 100644 index 0000000..e770f40 Binary files /dev/null and b/docs/c615fa3fad4c084c8bcd.module.wasm differ diff --git a/docs/e354e10adee0b37b85d7.module.wasm b/docs/e354e10adee0b37b85d7.module.wasm deleted file mode 100644 index 83d18f9..0000000 Binary files a/docs/e354e10adee0b37b85d7.module.wasm and /dev/null differ diff --git a/nodejs/native/src/lib.rs b/nodejs/native/src/lib.rs index 1b6110c..98bb2e7 100644 --- a/nodejs/native/src/lib.rs +++ b/nodejs/native/src/lib.rs @@ -4,7 +4,11 @@ extern crate neon; extern crate neon_serde; extern crate serde_json; -use jsonpath::prelude::*; +use std::ops::Deref; + +use jsonpath::filter::value_filter::JsonValueFilter; +use jsonpath::parser::parser::{Node, NodeVisitor, Parser}; +use jsonpath::ref_value::model::{RefValue, RefValueWrapper}; use neon::prelude::*; use serde_json::Value; @@ -70,7 +74,7 @@ declare_types! { let mut jf = JsonValueFilter::new_from_value(ref_value.into()); jf.visit(node); - match serde_json::to_string(&jf.take_value()) { + match serde_json::to_string(&jf.take_value().deref()) { Ok(json_str) => Ok(JsString::new(&mut ctx, &json_str).upcast()), Err(e) => panic!("{:?}", e) } @@ -107,7 +111,7 @@ declare_types! { let mut jf = JsonValueFilter::new_from_value(json); jf.visit(node); - match serde_json::to_string(&jf.take_value()) { + match serde_json::to_string(&jf.take_value().deref()) { Ok(json_str) => Ok(JsString::new(&mut ctx, &json_str).upcast()), Err(e) => panic!("{:?}", e) } diff --git a/src/filter/mod.rs b/src/filter/mod.rs index dc1a333..b3b7581 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -1,5 +1,4 @@ mod cmp; mod term; -mod value_filter; -mod value_wrapper; -pub mod prelude; \ No newline at end of file +pub mod value_filter; +pub mod value_wrapper; \ No newline at end of file diff --git a/src/filter/prelude.rs b/src/filter/prelude.rs deleted file mode 100644 index e79ac31..0000000 --- a/src/filter/prelude.rs +++ /dev/null @@ -1 +0,0 @@ -pub use super::value_filter::*; \ No newline at end of file diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs index 85b7134..fecafc3 100644 --- a/src/filter/value_filter.rs +++ b/src/filter/value_filter.rs @@ -6,8 +6,8 @@ use serde_json::Value; use filter::term::*; use filter::value_wrapper::*; -use parser::prelude::*; use ref_value::model::*; +use parser::parser::{ParseToken, FilterToken, NodeVisitor}; trait ArrayIndex { fn index(&self, v: &RefValueWrapper) -> usize; diff --git a/src/lib.rs b/src/lib.rs index 1503301..926990e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -162,26 +162,27 @@ extern crate env_logger; extern crate indexmap; #[macro_use] extern crate log; +#[macro_use] extern crate serde; extern crate serde_json; +use std::ops::Deref; use std::result; use serde_json::Value; -use prelude::*; +use filter::value_filter::JsonValueFilter; +use parser::parser::{NodeVisitor, Parser}; +use ref_value::model::{RefValue, RefValueWrapper}; #[doc(hidden)] -mod parser; +pub mod parser; #[doc(hidden)] -mod filter; +pub mod filter; #[doc(hidden)] -mod ref_value; -pub mod prelude; +pub mod ref_value; -type Result = result::Result; - -/// # Read multiple Json multiple times with the same JsonPath +/// # Compile a Jsonpath so it select a JsonObject immediately. /// /// ```rust /// extern crate jsonpath_lib as jsonpath; @@ -213,7 +214,7 @@ type Result = result::Result; /// let ret = json!([ {"id": 0}, {"name": "Millicent Norman"} ]); /// assert_eq!(json, ret); /// ``` -pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> Result + 'a { +pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> result::Result + 'a { let mut parser = Parser::new(path); let node = parser.compile(); move |json| { @@ -229,7 +230,7 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> Result + 'a { } -/// # Read the same Json multiple times using different JsonPath +/// # Use multiple JsonPaths for one JsonObject. /// /// ```rust /// extern crate jsonpath_lib as jsonpath; @@ -252,7 +253,7 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(&Value) -> Result + 'a { /// let ret = json!([ {"id": 1}, {"id": 1} ]); /// assert_eq!(json, ret); /// ``` -pub fn selector(json: &Value) -> impl FnMut(&str) -> Result { +pub fn selector(json: &Value) -> impl FnMut(&str) -> result::Result { let wrapper: RefValueWrapper = json.into(); move |path: &str| { let mut jf = JsonValueFilter::new_from_value(wrapper.clone()); @@ -262,12 +263,12 @@ pub fn selector(json: &Value) -> impl FnMut(&str) -> Result { } } -/// # Read the same Json multiple times using different JsonPath - Deprecated. use selector -pub fn reader(json: &Value) -> impl FnMut(&str) -> Result { +/// # Deprecated. use `selector` +pub fn reader(json: &Value) -> impl FnMut(&str) -> result::Result { selector(json) } -/// # Read Json using JsonPath +/// # Select a JsonObject /// /// ```rust /// extern crate jsonpath_lib as jsonpath; @@ -283,34 +284,84 @@ pub fn reader(json: &Value) -> impl FnMut(&str) -> Result { /// let ret = json!([ {"id": 0}, {"id": 0} ]); /// assert_eq!(json, ret); /// ``` -pub fn select(json: &Value, path: &str) -> Result { +pub fn select(json: &Value, path: &str) -> result::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()) } -/// # Read Json using JsonPath - Deprecated. use select -pub fn read(json: &Value, path: &str) -> Result { +/// # Deprecated. use `select` +pub fn read(json: &Value, path: &str) -> result::Result { select(json, path) } -/// # Read Json string using JsonPath +/// # Deprecaed. use `into_str` +pub fn select_str(json: &str, path: &str) -> result::Result { + select_as_str(json, path) +} + +/// # Return to json string /// /// ```rust /// extern crate jsonpath_lib as jsonpath; /// #[macro_use] extern crate serde_json; /// -/// let ret = jsonpath::select_str(r#"{ +/// let ret = jsonpath::select_as_str(r#"{ /// "school": { "friends": [{"id": 0}, {"id": 1}] }, /// "friends": [{"id": 0}, {"id": 1}] /// }"#, "$..friends[0]").unwrap(); /// assert_eq!(ret, r#"[{"id":0},{"id":0}]"#); /// ``` -pub fn select_str(json: &str, path: &str) -> result::Result { +pub fn select_as_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)) + serde_json::to_string(&jf.take_value().deref()).map_err(|e| format!("{:?}", e)) +} + +/// # Return to deserializeable. +/// ```rust +/// extern crate jsonpath_lib as jsonpath; +/// extern crate serde; +/// #[macro_use] extern crate serde_json; +/// +/// use serde::{Deserialize, Serialize}; +/// +/// #[derive(Serialize, Deserialize, PartialEq, Debug)] +/// struct Person { +/// name: String, +/// age: u8, +/// phones: Vec, +/// } +/// +/// let ret: Person = jsonpath::select_as(r#" +/// { +/// "person": +/// { +/// "name": "Doe John", +/// "age": 44, +/// "phones": [ +/// "+44 1234567", +/// "+44 2345678" +/// ] +/// } +/// } +/// "#, "$.person").unwrap(); +/// +/// let person = Person { +/// name: "Doe John".to_string(), +/// age: 44, +/// phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], +/// }; +/// +/// assert_eq!(person, ret); +/// ``` +pub fn select_as<'a, T: serde::Deserialize<'a>>(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)?; + T::deserialize(jf.take_value().deref()).map_err(|e| format!("{:?}", e)) } \ No newline at end of file diff --git a/src/parser/mod.rs b/src/parser/mod.rs index f5c15ce..331b73a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -1,4 +1,3 @@ mod path_reader; -mod tokenizer; -mod parser; -pub mod prelude; \ No newline at end of file +pub mod tokenizer; +pub mod parser; \ No newline at end of file diff --git a/src/parser/prelude.rs b/src/parser/prelude.rs deleted file mode 100644 index 09315fa..0000000 --- a/src/parser/prelude.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub use super::parser::*; -pub use super::tokenizer::*; \ No newline at end of file diff --git a/src/prelude.rs b/src/prelude.rs deleted file mode 100644 index ddebc84..0000000 --- a/src/prelude.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub use parser::prelude::*; -pub use filter::prelude::*; -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 deleted file mode 100644 index 887c206..0000000 --- a/src/ref_value/convert.rs +++ /dev/null @@ -1,111 +0,0 @@ -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 index a1552b6..a5765ca 100644 --- a/src/ref_value/de.rs +++ b/src/ref_value/de.rs @@ -1,20 +1,45 @@ -use std::error::Error; +use std::borrow::Cow; use std::fmt; +use std::ops::Deref; use std::result::Result; +use std::vec; use indexmap::IndexMap; -use serde::{Deserialize, Deserializer}; -use serde::de::{MapAccess, SeqAccess, Visitor}; +use serde::{self, Deserialize, Deserializer}; +use serde::de::{DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess, Visitor}; use serde_json::Value; use super::model::*; +use super::serde_error::SerdeError; + +/// +/// see `serde_json/value/de.rs` +/// + +macro_rules! deserialize_prim_number { + ($method:ident) => { + fn $method(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Number(ref n) => { + match n.deserialize_any(visitor) { + Ok(v) => Ok(v), + Err(e) => Err(SerdeError::new(format!("{:?}", e))) + } + } + _ => Err(SerdeError::from_str("invalid type")), + } + } + } +} impl<'de> Deserialize<'de> for RefValue { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - struct RefValueVisitor {} impl<'de> Visitor<'de> for RefValueVisitor { @@ -27,7 +52,7 @@ impl<'de> Deserialize<'de> for RefValue { #[inline] fn visit_bool(self, v: bool) -> Result where - E: Error, { + E: serde::de::Error, { Ok(RefValue::Bool(v)) } @@ -106,7 +131,6 @@ impl<'de> Deserialize<'de> for RefValue { Ok(RefValue::Array(vec)) } - #[inline] fn visit_map(self, mut visitor: A) -> Result where A: MapAccess<'de>, { @@ -128,4 +152,907 @@ impl<'de> Deserialize<'de> for RefValue { deserializer.deserialize_any(RefValueVisitor {}) } +} + +fn visit_array<'de, V>(array: Vec, visitor: V) -> Result + where + V: Visitor<'de>, +{ + let mut deserializer = SeqDeserializer::new(array); + let seq = visitor.visit_seq(&mut deserializer)?; + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(seq) + } else { + Err(SerdeError::from_str("fewer elements in array")) + } +} + +fn visit_object<'de, V>(object: IndexMap, visitor: V) -> Result + where + V: Visitor<'de>, +{ + let mut deserializer = MapDeserializer::new(object); + let map = visitor.visit_map(&mut deserializer)?; + let remaining = deserializer.iter.len(); + if remaining == 0 { + Ok(map) + } else { + Err(SerdeError::from_str("fewer elements in map")) + } +} + +fn to_vec(vec: &Vec) -> Vec { + vec.iter().map(|v| v.clone()).collect() +} + +fn to_map(object: &IndexMap) -> IndexMap { + let mut map = IndexMap::new(); + for (k, v) in object { + map.insert(k.to_string(), v.clone()); + } + map +} + +impl<'de> serde::Deserializer<'de> for RefValue { + type Error = SerdeError; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result where + V: Visitor<'de> { + match self { + RefValue::Null => visitor.visit_unit(), + RefValue::Bool(v) => visitor.visit_bool(v), + RefValue::Number(n) => { + n.deserialize_any(visitor).map_err(|e| SerdeError::new(format!("{:?}", e))) + } + RefValue::String(v) => visitor.visit_string(v), + RefValue::Array(array) => visit_array(array, visitor), + RefValue::Object(object) => visit_object(object, visitor) + } + } + + deserialize_prim_number!(deserialize_i8); + deserialize_prim_number!(deserialize_i16); + deserialize_prim_number!(deserialize_i32); + deserialize_prim_number!(deserialize_i64); + deserialize_prim_number!(deserialize_u8); + deserialize_prim_number!(deserialize_u16); + deserialize_prim_number!(deserialize_u32); + deserialize_prim_number!(deserialize_u64); + deserialize_prim_number!(deserialize_f32); + deserialize_prim_number!(deserialize_f64); + + #[inline] + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Null => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + #[inline] + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let (variant, value) = match self { + RefValue::Object(value) => { + let mut iter = value.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err(SerdeError::from_str("map with a single key")); + } + }; + if iter.next().is_some() { + return Err(SerdeError::from_str("map with a single key")); + } + (variant, Some(value)) + } + RefValue::String(variant) => (variant, None), + _ => { + return Err(SerdeError::from_str("string or map")); + } + }; + + visitor.visit_enum(EnumDeserializer { + variant: variant, + value: value, + }) + } + + #[inline] + fn deserialize_newtype_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let _ = name; + visitor.visit_newtype_struct(self) + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Bool(v) => visitor.visit_bool(v), + _ => Err(SerdeError::from_str("invalid type: bool")), + } + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::String(v) => visitor.visit_string(v), + _ => Err(SerdeError::from_str("invalid type: string")), + } + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_byte_buf(visitor) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::String(v) => visitor.visit_string(v), + RefValue::Array(v) => visit_array(v, visitor), + _ => Err(SerdeError::from_str("invalid type: string or array")), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Null => visitor.visit_unit(), + _ => Err(SerdeError::from_str("invalid type: null")), + } + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Array(v) => visit_array(v, visitor), + _ => Err(SerdeError::from_str("invalid type: array")), + } + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Object(v) => visit_object(v, visitor), + _ => Err(SerdeError::from_str("invalid type: object")) + } + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Array(v) => visit_array(v, visitor), + RefValue::Object(v) => visit_object(v, visitor), + _ => Err(SerdeError::from_str("invalid type: array, object")) + } + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + drop(self); + visitor.visit_unit() + } +} + +impl<'de> serde::Deserializer<'de> for &RefValue { + type Error = SerdeError; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result where + V: Visitor<'de> { + match self { + RefValue::Null => visitor.visit_unit(), + RefValue::Bool(v) => visitor.visit_bool(*v), + RefValue::Number(n) => { + n.deserialize_any(visitor).map_err(|e| SerdeError::new(format!("{:?}", e))) + } + RefValue::String(v) => visitor.visit_string(v.to_string()), + RefValue::Array(array) => visit_array(to_vec(array), visitor), + RefValue::Object(object) => { + visit_object(to_map(object), visitor) + } + } + } + + deserialize_prim_number!(deserialize_i8); + deserialize_prim_number!(deserialize_i16); + deserialize_prim_number!(deserialize_i32); + deserialize_prim_number!(deserialize_i64); + deserialize_prim_number!(deserialize_u8); + deserialize_prim_number!(deserialize_u16); + deserialize_prim_number!(deserialize_u32); + deserialize_prim_number!(deserialize_u64); + deserialize_prim_number!(deserialize_f32); + deserialize_prim_number!(deserialize_f64); + + #[inline] + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Null => visitor.visit_none(), + _ => visitor.visit_some(self), + } + } + + #[inline] + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let (variant, value) = match self { + RefValue::Object(value) => { + let mut iter = value.into_iter(); + let (variant, value) = match iter.next() { + Some(v) => v, + None => { + return Err(SerdeError::from_str("map with a single key")); + } + }; + if iter.next().is_some() { + return Err(SerdeError::from_str("map with a single key")); + } + (variant, Some(value)) + } + RefValue::String(variant) => (variant, None), + _ => { + return Err(SerdeError::from_str("string or map")); + } + }; + + visitor.visit_enum(EnumDeserializer { + variant: variant.to_string(), + value: match value { + Some(v) => Some(v.clone()), + _ => None + }, + }) + } + + #[inline] + fn deserialize_newtype_struct( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + let _ = name; + visitor.visit_newtype_struct(self) + } + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Bool(v) => visitor.visit_bool(*v), + _ => Err(SerdeError::from_str("invalid type: bool")), + } + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::String(v) => visitor.visit_string(v.to_string()), + _ => Err(SerdeError::from_str("invalid type: string")), + } + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_byte_buf(visitor) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::String(v) => visitor.visit_string(v.to_string()), + RefValue::Array(vec) => visit_array(to_vec(vec), visitor), + _ => Err(SerdeError::from_str("invalid type: string or array")), + } + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Null => visitor.visit_unit(), + _ => Err(SerdeError::from_str("invalid type: null")), + } + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Array(vec) => visit_array(to_vec(vec), visitor), + _ => Err(SerdeError::from_str("invalid type: array")), + } + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Object(object) => { + visit_object(to_map(object), visitor) + } + _ => Err(SerdeError::from_str("invalid type: object")) + } + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self { + RefValue::Array(vec) => visit_array(to_vec(vec), visitor), + RefValue::Object(object) => { + visit_object(to_map(object), visitor) + } + _ => Err(SerdeError::from_str("invalid type: array, object")) + } + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_string(visitor) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + drop(self); + visitor.visit_unit() + } +} + + +struct SeqDeserializer { + iter: vec::IntoIter, +} + +impl SeqDeserializer { + fn new(vec: Vec) -> Self { + SeqDeserializer { + iter: vec.into_iter(), + } + } +} + +impl<'de> serde::Deserializer<'de> for SeqDeserializer { + type Error = SerdeError; + + #[inline] + fn deserialize_any(mut self, visitor: V) -> Result + where + V: Visitor<'de>, + { + let len = self.iter.len(); + if len == 0 { + visitor.visit_unit() + } else { + let ret = visitor.visit_seq(&mut self)?; + let remaining = self.iter.len(); + if remaining == 0 { + Ok(ret) + } else { + Err(SerdeError::from_str("fewer elements in array")) + } + } + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +impl<'de> SeqAccess<'de> for SeqDeserializer { + type Error = SerdeError; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => seed.deserialize(value.deref()).map(Some), + None => Ok(None), + } + } + + fn size_hint(&self) -> Option { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +struct MapDeserializer { + iter: as IntoIterator>::IntoIter, + value: Option, +} + +impl MapDeserializer { + fn new(map: IndexMap) -> Self { + MapDeserializer { + iter: map.into_iter(), + value: None, + } + } +} + +impl<'de> MapAccess<'de> for MapDeserializer { + type Error = SerdeError; + + fn next_key_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, value)) => { + self.value = Some(value); + let key_de = MapKeyDeserializer { + key: Cow::Owned(key), + }; + seed.deserialize(key_de).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + match self.value.take() { + Some(value) => seed.deserialize(value.deref()), + None => Err(serde::de::Error::custom("value is missing")), + } + } + + fn size_hint(&self) -> Option { + match self.iter.size_hint() { + (lower, Some(upper)) if lower == upper => Some(upper), + _ => None, + } + } +} + +impl<'de> serde::Deserializer<'de> for MapDeserializer { + type Error = SerdeError; + + #[inline] + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_map(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct enum identifier ignored_any + } +} + +struct MapKeyDeserializer<'de> { + key: Cow<'de, str>, +} + +macro_rules! deserialize_integer_key { + ($method:ident => $visit:ident) => { + fn $method(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match (self.key.parse(), self.key) { + (Ok(integer), _) => visitor.$visit(integer), + (Err(_), Cow::Borrowed(s)) => visitor.visit_borrowed_str(s), + (Err(_), Cow::Owned(s)) => visitor.visit_string(s), + } + } + } +} + +impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> { + type Error = SerdeError; + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + BorrowedCowStrDeserializer::new(self.key).deserialize_any(visitor) + } + + deserialize_integer_key!(deserialize_i8 => visit_i8); + deserialize_integer_key!(deserialize_i16 => visit_i16); + deserialize_integer_key!(deserialize_i32 => visit_i32); + deserialize_integer_key!(deserialize_i64 => visit_i64); + deserialize_integer_key!(deserialize_u8 => visit_u8); + deserialize_integer_key!(deserialize_u16 => visit_u16); + deserialize_integer_key!(deserialize_u32 => visit_u32); + deserialize_integer_key!(deserialize_u64 => visit_u64); + + serde_if_integer128! { + deserialize_integer_key!(deserialize_i128 => visit_i128); + deserialize_integer_key!(deserialize_u128 => visit_u128); + } + + #[inline] + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + // Map keys cannot be null. + visitor.visit_some(self) + } + + #[inline] + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_enum( + self, + name: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.key + .into_deserializer() + .deserialize_enum(name, variants, visitor) + } + + forward_to_deserialize_any! { + bool f32 f64 char str string bytes byte_buf unit unit_struct seq tuple + tuple_struct map struct identifier ignored_any + } +} + +struct BorrowedCowStrDeserializer<'de> { + value: Cow<'de, str>, +} + +impl<'de> BorrowedCowStrDeserializer<'de> { + fn new(value: Cow<'de, str>) -> Self { + BorrowedCowStrDeserializer { value: value } + } +} + +impl<'de> serde::Deserializer<'de> for BorrowedCowStrDeserializer<'de> { + type Error = SerdeError; + + fn deserialize_any(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + match self.value { + Cow::Borrowed(string) => visitor.visit_borrowed_str(string), + Cow::Owned(string) => visitor.visit_string(string), + } + } + + fn deserialize_enum( + self, + _name: &str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + visitor.visit_enum(self) + } + + forward_to_deserialize_any! { + bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string + bytes byte_buf option unit unit_struct newtype_struct seq tuple + tuple_struct map struct identifier ignored_any + } +} + +impl<'de> serde::de::EnumAccess<'de> for BorrowedCowStrDeserializer<'de> { + type Error = SerdeError; + type Variant = UnitOnly; + + fn variant_seed(self, seed: T) -> Result<(T::Value, Self::Variant), Self::Error> + where + T: serde::de::DeserializeSeed<'de>, + { + let value = seed.deserialize(self)?; + Ok((value, UnitOnly)) + } +} + +struct UnitOnly; + +impl<'de> serde::de::VariantAccess<'de> for UnitOnly { + type Error = SerdeError; + + fn unit_variant(self) -> Result<(), Self::Error> { + Ok(()) + } + + fn newtype_variant_seed(self, _seed: T) -> Result + where + T: serde::de::DeserializeSeed<'de>, + { + Err(SerdeError::from_str("newtype variant")) + } + + fn tuple_variant(self, _len: usize, _visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeError::from_str("tuple variant")) + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + _visitor: V, + ) -> Result + where + V: serde::de::Visitor<'de>, + { + Err(SerdeError::from_str("struct variant")) + } +} + +struct EnumDeserializer { + variant: String, + value: Option, +} + +impl<'de> EnumAccess<'de> for EnumDeserializer { + type Error = SerdeError; + type Variant = VariantDeserializer; + + fn variant_seed(self, seed: V) -> Result<(V::Value, VariantDeserializer), Self::Error> + where + V: DeserializeSeed<'de>, + { + let variant = self.variant.into_deserializer(); + let visitor = VariantDeserializer { value: self.value }; + seed.deserialize(variant).map(|v| (v, visitor)) + } +} + +struct VariantDeserializer { + value: Option, +} + +impl<'de> VariantAccess<'de> for VariantDeserializer { + type Error = SerdeError; + + fn unit_variant(self) -> Result<(), Self::Error> { + match self.value { + Some(value) => Deserialize::deserialize(value.deref()), + None => Ok(()), + } + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(value.deref()), + None => Err(SerdeError::from_str("newtype variant")), + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.value { + Some(ref_value) => { + match ref_value.deref() { + RefValue::Array(vec) => { + serde::Deserializer::deserialize_any(SeqDeserializer::new(to_vec(vec)), visitor) + } + _ => Err(SerdeError::from_str("tuple variant")) + } + } + None => Err(SerdeError::from_str("tuple variant")), + } + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self.value { + Some(ref_value) => { + match ref_value.deref() { + RefValue::Object(vec) => { + serde::Deserializer::deserialize_any(MapDeserializer::new(to_map(vec)), visitor) + } + _ => Err(SerdeError::from_str("struct variant")) + } + } + _ => Err(SerdeError::from_str("struct variant")), + } + } } \ No newline at end of file diff --git a/src/ref_value/mod.rs b/src/ref_value/mod.rs index 2c17c17..05dec5f 100644 --- a/src/ref_value/mod.rs +++ b/src/ref_value/mod.rs @@ -1,4 +1,4 @@ pub mod model; -mod convert; pub mod de; -pub mod ser; \ No newline at end of file +pub mod ser; +pub mod serde_error; \ No newline at end of file diff --git a/src/ref_value/model.rs b/src/ref_value/model.rs index e063495..f6d80c9 100644 --- a/src/ref_value/model.rs +++ b/src/ref_value/model.rs @@ -3,10 +3,9 @@ use std::ops::Deref; use std::sync::Arc; use indexmap::map::IndexMap; +use serde::ser::Serialize; use serde_json::{Number, Value}; -use super::convert::*; - type TypeRefValue = Arc>; #[derive(Debug, PartialEq)] @@ -14,6 +13,15 @@ pub struct RefValueWrapper { data: TypeRefValue } +impl RefValueWrapper { + pub fn try_unwrap(self) -> RefValue { + match Arc::try_unwrap(self.data) { + Ok(ref_value) => *ref_value, + Err(e) => panic!("{:?}", e) + } + } +} + impl Eq for RefValueWrapper {} impl Deref for RefValueWrapper { @@ -131,10 +139,10 @@ impl Hash for RefValue { match self { RefValue::Null => { REF_VALUE_NULL.hash(state) - }, + } RefValue::Bool(b) => { b.hash(state) - }, + } RefValue::Number(n) => { if n.is_f64() { n.as_f64().unwrap().to_string().hash(state) @@ -146,7 +154,7 @@ impl Hash for RefValue { } RefValue::String(s) => { s.hash(state) - }, + } RefValue::Object(map) => { for (_, v) in map { v.hash(state); @@ -246,20 +254,61 @@ impl Into for RefValue { } } +//impl Into for &RefValue { +// fn into(self) -> RefValue { +// match self { +// RefValue::Null => RefValue::Null, +// RefValue::Bool(b) => RefValue::Bool(*b), +// RefValue::String(s) => RefValue::String(s.to_string()), +// RefValue::Number(n) => { +// if n.is_f64() { +// RefValue::Number(n.as_u64().unwrap().into()) +// } else if n.is_i64() { +// RefValue::Number(n.as_i64().unwrap().into()) +// } else if n.is_u64() { +// RefValue::Number(n.as_u64().unwrap().into()) +// } else { +// unreachable!() +// } +// } +// RefValue::Array(ay) => { +// let vec = ay.iter().map(|a| a.try_unwrap().into()).collect(); +// RefValue::Array(vec) +// } +// RefValue::Object(map) => { +// let mut ret = IndexMap::new(); +// for (k, v) in map { +// ret.insert(k.to_string(), v.try_unwrap().into()); +// } +// RefValue::Object(ret) +// } +// } +// } +//} + impl Into for &Value { fn into(self) -> RefValueWrapper { - RefValueConverter::new(&self) + match self.serialize(super::ser::Serializer) { + Ok(v) => v.into(), + Err(e) => panic!("Error Value into RefValue: {:?}", e) + } } } impl Into for RefValueWrapper { fn into(self) -> Value { - ValueConverter::new(&self) + match serde_json::to_value(self.deref()) { + Ok(v) => v, + Err(e) => panic!("Error RefValueWrapper into Value: {:?}", e) + } } } impl Into for &RefValueWrapper { fn into(self) -> Value { - ValueConverter::new(&self) + match serde_json::to_value(self.deref()) { + Ok(v) => v, + Err(e) => panic!("Error RefValueWrapper into Value: {:?}", e) + } } } \ No newline at end of file diff --git a/src/ref_value/ser.rs b/src/ref_value/ser.rs index a4a214d..c4b65fb 100644 --- a/src/ref_value/ser.rs +++ b/src/ref_value/ser.rs @@ -1,13 +1,22 @@ use std::result::Result; +use indexmap::IndexMap; use serde::{self, Serialize}; +use serde::ser::Impossible; use ref_value::model::{RefValue, RefValueWrapper}; +use super::serde_error::SerdeError; + +/// +/// see `serde_json/value/ser.rs` +/// impl Serialize for RefValue { #[inline] - fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::Serializer, + { match *self { RefValue::Null => serializer.serialize_unit(), RefValue::Bool(b) => serializer.serialize_bool(b), @@ -17,14 +26,14 @@ impl Serialize for RefValue { 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()))?; + let mut map = try!(serializer.serialize_map(Some(m.len()))); for (k, v) in m { - map.serialize_key(k)?; - map.serialize_value(v.deref())?; + try!(map.serialize_key(k)); + try!(map.serialize_value(v.deref())); } map.end() } @@ -32,32 +41,584 @@ impl Serialize for RefValue { } } -impl Serialize for RefValueWrapper { - #[inline] - fn serialize(&self, serializer: S) -> Result where - S: serde::Serializer { - use std::ops::Deref; +pub struct Serializer; - 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() +impl serde::Serializer for Serializer { + type Ok = RefValue; + type Error = SerdeError; + + type SerializeSeq = SerializeVec; + type SerializeTuple = SerializeVec; + type SerializeTupleStruct = SerializeVec; + type SerializeTupleVariant = SerializeTupleVariant; + type SerializeMap = SerializeMap; + type SerializeStruct = SerializeMap; + type SerializeStructVariant = SerializeStructVariant; + + #[inline] + fn serialize_bool(self, value: bool) -> Result { + Ok(RefValue::Bool(value)) + } + + #[inline] + fn serialize_i8(self, value: i8) -> Result { + self.serialize_i64(value as i64) + } + + #[inline] + fn serialize_i16(self, value: i16) -> Result { + self.serialize_i64(value as i64) + } + + #[inline] + fn serialize_i32(self, value: i32) -> Result { + self.serialize_i64(value as i64) + } + + fn serialize_i64(self, value: i64) -> Result { + Ok(RefValue::Number(value.into())) + } + + #[inline] + fn serialize_u8(self, value: u8) -> Result { + self.serialize_u64(value as u64) + } + + #[inline] + fn serialize_u16(self, value: u16) -> Result { + self.serialize_u64(value as u64) + } + + #[inline] + fn serialize_u32(self, value: u32) -> Result { + self.serialize_u64(value as u64) + } + + #[inline] + fn serialize_u64(self, value: u64) -> Result { + Ok(RefValue::Number(value.into())) + } + + #[inline] + fn serialize_f32(self, value: f32) -> Result { + self.serialize_f64(value as f64) + } + + #[inline] + fn serialize_f64(self, value: f64) -> Result { + Ok(serde_json::Number::from_f64(value).map_or(RefValue::Null, RefValue::Number)) + } + + #[inline] + fn serialize_char(self, value: char) -> Result { + let mut s = String::new(); + s.push(value); + self.serialize_str(&s) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result { + Ok(RefValue::String(value.to_owned())) + } + + fn serialize_bytes(self, value: &[u8]) -> Result { + let vec = value.iter().map(|&b| RefValue::Number(b.into()).into()).collect(); + Ok(RefValue::Array(vec)) + } + + #[inline] + fn serialize_unit(self) -> Result { + Ok(RefValue::Null) + } + + #[inline] + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + self.serialize_str(variant) + } + + #[inline] + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + let mut values: IndexMap = IndexMap::new(); + values.insert(String::from(variant), { + value.serialize(Serializer)?.into() + }); + Ok(RefValue::Object(values)) + } + + #[inline] + fn serialize_none(self) -> Result { + self.serialize_unit() + } + + #[inline] + fn serialize_some(self, value: &T) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(SerializeVec { + vec: Vec::with_capacity(len.unwrap_or(0)), + }) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(SerializeTupleVariant { + name: String::from(variant), + vec: Vec::with_capacity(len), + }) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(SerializeMap::Map { + map: IndexMap::new(), + next_key: None, + }) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + match name { + _ => self.serialize_map(Some(len)), + } + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(SerializeStructVariant { + name: String::from(variant), + map: IndexMap::new(), + }) + } +} + +pub struct SerializeVec { + vec: Vec, +} + +pub struct SerializeTupleVariant { + name: String, + vec: Vec, +} + +pub enum SerializeMap { + Map { + map: IndexMap, + next_key: Option, + }, +} + +pub struct SerializeStructVariant { + name: String, + map: IndexMap, +} + +impl serde::ser::SerializeSeq for SerializeVec { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.vec.push({ + value.serialize(Serializer)?.into() + }); + Ok(()) + } + + fn end(self) -> Result { + Ok(RefValue::Array(self.vec)) + } +} + +impl serde::ser::SerializeTuple for SerializeVec { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } +} + +impl serde::ser::SerializeTupleStruct for SerializeVec { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + serde::ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + serde::ser::SerializeSeq::end(self) + } +} + +impl serde::ser::SerializeTupleVariant for SerializeTupleVariant { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.vec.push({ + let a: RefValue = value.serialize(Serializer)?; + a.into() + }); + Ok(()) + } + + fn end(self) -> Result { + let mut object: IndexMap = IndexMap::new(); + + object.insert(self.name, RefValue::Array(self.vec).into()); + + Ok(RefValue::Object(object)) + } +} + +impl serde::ser::SerializeMap for SerializeMap { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + match *self { + SerializeMap::Map { + ref mut next_key, .. + } => { + *next_key = Some(key.serialize(MapKeySerializer)?); + Ok(()) } } } -} \ No newline at end of file + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + match *self { + SerializeMap::Map { + ref mut map, + ref mut next_key, + } => { + let key = next_key.take(); + // Panic because this indicates a bug in the program rather than an + // expected failure. + let key = key.expect("serialize_value called before serialize_key"); + map.insert(key, { + let a: RefValue = value.serialize(Serializer)?; + a.into() + }); + Ok(()) + } + } + } + + fn end(self) -> Result { + match self { + SerializeMap::Map { map, .. } => Ok(RefValue::Object(map)), + } + } +} + +struct MapKeySerializer; + +fn key_must_be_a_string() -> SerdeError { + SerdeError::from_str("key must be string") +} + +impl serde::Serializer for MapKeySerializer { + type Ok = String; + type Error = SerdeError; + + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Impossible; + type SerializeStruct = Impossible; + type SerializeStructVariant = Impossible; + + #[inline] + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(variant.to_owned()) + } + + #[inline] + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_bool(self, _value: bool) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_i8(self, value: i8) -> Result { + Ok(value.to_string()) + } + + fn serialize_i16(self, value: i16) -> Result { + Ok(value.to_string()) + } + + fn serialize_i32(self, value: i32) -> Result { + Ok(value.to_string()) + } + + fn serialize_i64(self, value: i64) -> Result { + Ok(value.to_string()) + } + + fn serialize_u8(self, value: u8) -> Result { + Ok(value.to_string()) + } + + fn serialize_u16(self, value: u16) -> Result { + Ok(value.to_string()) + } + + fn serialize_u32(self, value: u32) -> Result { + Ok(value.to_string()) + } + + fn serialize_u64(self, value: u64) -> Result { + Ok(value.to_string()) + } + + fn serialize_f32(self, _value: f32) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_f64(self, _value: f64) -> Result { + Err(key_must_be_a_string()) + } + + #[inline] + fn serialize_char(self, value: char) -> Result { + Ok({ + let mut s = String::new(); + s.push(value); + s + }) + } + + #[inline] + fn serialize_str(self, value: &str) -> Result { + Ok(value.to_owned()) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_unit(self) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result + where + T: Serialize, + { + Err(key_must_be_a_string()) + } + + fn serialize_none(self) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_some(self, _value: &T) -> Result + where + T: Serialize, + { + Err(key_must_be_a_string()) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(key_must_be_a_string()) + } +} + +impl serde::ser::SerializeStruct for SerializeMap { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + match *self { + SerializeMap::Map { .. } => { + serde::ser::SerializeMap::serialize_key(self, key)?; + serde::ser::SerializeMap::serialize_value(self, value) + } + } + } + + fn end(self) -> Result { + match self { + SerializeMap::Map { .. } => serde::ser::SerializeMap::end(self), + } + } +} + +impl serde::ser::SerializeStructVariant for SerializeStructVariant { + type Ok = RefValue; + type Error = SerdeError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + self.map.insert(String::from(key), { + let a: RefValue = value.serialize(Serializer)?; + a.into() + }); + Ok(()) + } + + fn end(self) -> Result { + let mut object: IndexMap = IndexMap::new(); + + object.insert(self.name, RefValue::Object(self.map).into()); + + Ok(RefValue::Object(object)) + } +} diff --git a/src/ref_value/serde_error.rs b/src/ref_value/serde_error.rs new file mode 100644 index 0000000..7deb7f1 --- /dev/null +++ b/src/ref_value/serde_error.rs @@ -0,0 +1,38 @@ +use std::fmt; + +#[derive(Debug)] +pub struct SerdeError { + msg: String, +} + +impl<'a> SerdeError { + pub fn new(msg: String) -> Self { + SerdeError { msg: msg } + } + + pub fn from_str(msg: &str) -> Self { + SerdeError { msg: msg.to_string() } + } +} + +impl serde::de::Error for SerdeError { + #[cold] + fn custom(msg: T) -> SerdeError { + SerdeError { msg: msg.to_string() } + } +} + +impl serde::ser::Error for SerdeError { + #[cold] + fn custom(msg: T) -> SerdeError { + SerdeError { msg: msg.to_string() } + } +} + +impl std::error::Error for SerdeError {} + +impl fmt::Display for SerdeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.msg) + } +} \ No newline at end of file diff --git a/tests/filter.rs b/tests/filter.rs index 7200693..ec1b77f 100644 --- a/tests/filter.rs +++ b/tests/filter.rs @@ -6,8 +6,8 @@ extern crate serde_json; use std::io::Read; use serde_json::Value; - -use jsonpath::prelude::*; +use jsonpath::filter::value_filter::{ValueFilter, JsonValueFilter}; +use jsonpath::parser::parser::Parser; fn setup() { let _ = env_logger::try_init(); diff --git a/tests/lib.rs b/tests/lib.rs index 45f8469..6f5710d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,11 +1,13 @@ extern crate env_logger; extern crate jsonpath_lib as jsonpath; extern crate log; +extern crate serde; #[macro_use] extern crate serde_json; use std::io::Read; +use serde::{Deserialize, Serialize}; use serde_json::Value; fn read_json(path: &str) -> Value { @@ -88,4 +90,36 @@ fn select_str() { }]); let json: Value = serde_json::from_str(&result_str).unwrap(); assert_eq!(json, ret); +} + +#[test] +fn test_to_struct() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + struct Person { + name: String, + age: u8, + phones: Vec, + } + + let ret: Person = jsonpath::select_as(r#" + { + "person": + { + "name": "Doe John", + "age": 44, + "phones": [ + "+44 1234567", + "+44 2345678" + ] + } + } + "#, "$.person").unwrap(); + + let person = Person { + name: "Doe John".to_string(), + age: 44, + phones: vec!["+44 1234567".to_string(), "+44 2345678".to_string()], + }; + + assert_eq!(person, ret); } \ No newline at end of file diff --git a/tests/parser.rs b/tests/parser.rs index b51d0d3..b0973fb 100644 --- a/tests/parser.rs +++ b/tests/parser.rs @@ -2,8 +2,7 @@ extern crate env_logger; extern crate jsonpath_lib as jsonpath; use std::result; - -use jsonpath::prelude::*; +use jsonpath::parser::parser::{Parser, ParseToken, NodeVisitor, FilterToken}; struct NodeVisitorTestImpl<'a> { input: &'a str, diff --git a/tests/serde.rs b/tests/serde.rs index 09422ef..ff6511c 100644 --- a/tests/serde.rs +++ b/tests/serde.rs @@ -1,11 +1,11 @@ extern crate jsonpath_lib as jsonpath; +extern crate serde; extern crate serde_json; use std::io::Read; use serde_json::Value; - -use jsonpath::prelude::*; +use jsonpath::ref_value::model::{RefValue, RefValueWrapper}; fn read_json(path: &str) -> String { let mut f = std::fs::File::open(path).unwrap(); diff --git a/tests/tokenizer.rs b/tests/tokenizer.rs index 1e83c84..dbd14f8 100644 --- a/tests/tokenizer.rs +++ b/tests/tokenizer.rs @@ -1,6 +1,6 @@ extern crate jsonpath_lib as jsonpath; -use jsonpath::prelude::*; +use jsonpath::parser::tokenizer::{Tokenizer, Token, TokenError, PreloadedTokenizer}; fn collect_token(input: &str) -> (Vec, Option) { let mut tokenizer = Tokenizer::new(input); diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index 3319b24..b84882b 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -11,11 +11,14 @@ use std::result::Result; use std::sync::Mutex; use cfg_if::cfg_if; -use jsonpath::prelude::*; use serde_json::Value; use wasm_bindgen::prelude::*; use web_sys::console; +use jsonpath::filter::value_filter::JsonValueFilter; +use jsonpath::parser::parser::{Node, NodeVisitor, Parser}; +use jsonpath::ref_value::model::{RefValue, RefValueWrapper}; + mod utils; cfg_if! {