diff --git a/Cargo.toml b/Cargo.toml index b00e850..72a69ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath_lib" -version = "0.1.2" +version = "0.1.3" authors = ["Changseok Han "] description = "JsonPath in Rust and Webassembly - Webassembly Demo: https://freestrings.github.io/jsonpath" @@ -27,4 +27,8 @@ bencher = "0.1.5" [lib] name = "jsonpath_lib" -path = "src/lib.rs" \ No newline at end of file +path = "src/lib.rs" + +[profile.release] +debug = true +lto = false diff --git a/README.md b/README.md index 2aa8adf..35d5e21 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # jsonpath-lib [![Build Status](https://travis-ci.org/freestrings/jsonpath.svg?branch=master)](https://travis-ci.org/freestrings/jsonpath) -[![version](https://img.shields.io/crates/v/:jsonpath.svg)](https://crates.io/crates/jsonpath_lib) +![crates.io](https://img.shields.io/crates/v/jsonpath_lib.svg) `Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현이다. Rust 구현과 동일한 기능을 `Webassembly` 로 제공하는 것도 목표. @@ -16,17 +16,18 @@ To enjoy Rust! [With Javascript (Webassembly)](#with-javascript-webassembly) - [jsonpath-wasm library](#jsonpath-wasm-library) -- [javascript - jsonpath.read(json: string|object, jsonpath: string)](#javascript---jsonpathreadjson-stringobject-jsonpath-string) +- [javascript - jsonpath.select(json: string|object, jsonpath: string)](#javascript---jsonpathselectjson-stringobject-jsonpath-string) - [javascript - jsonpath.compile(jsonpath: string)](#javascript---jsonpathcompilejsonpath-string) -- [javascript - jsonpath.reader(json: string|object)](#javascript---jsonpathreaderjson-stringobject) +- [javascript - jsonpath.selector(json: string|object)](#javascript---jsonpathselectorjson-stringobject) +- [javascript - alloc_json, dealloc_json](#javascript---alloc_json-dealloc_json) - [javascript - examples](#javascript---examples) [With Rust (as library)](#with-rust-as-library) - [jsonpath_lib library](#jsonpath_lib-library) -- [rust - jsonpath::read(json: serde_json::value::Value, jsonpath: &str)](#rust---jsonpathreadjson-serde_jsonvaluevalue-jsonpath-str) +- [rust - jsonpath::select(json: serde_json::value::Value, jsonpath: &str)](#rust---jsonpathselectjson-serde_jsonvaluevalue-jsonpath-str) - [rust - jsonpath::compile(jsonpath: &str)](#rust---jsonpathcompilejsonpath-str) -- [rust - jsonpath::reader(json: serde_json::value::Value)](#rust---jsonpathreaderjson-serde_jsonvaluevalue) +- [rust - jsonpath::selector(json: serde_json::value::Value)](#rust---jsonpathselectorjson-serde_jsonvaluevalue) - [rust - examples](#rust---examples) [With AWS API Gateway](#with-aws-api-gateway) @@ -45,7 +46,7 @@ import * as jsonpath from "jsonpath-wasm"; let jsonpath = require('jsonpath-wasm'); ``` -### javascript - jsonpath.read(json: string|object, jsonpath: string) +### javascript - jsonpath.select(json: string|object, jsonpath: string) ```javascript let jsonObj = { @@ -56,8 +57,8 @@ let jsonObj = { }; let ret = [{"id": 0}, {"id": 0}]; -let a = jsonpath.read(JSON.stringify(jsonObj), "$..friends[0]"); -let b = jsonpath.read(jsonObj, "$..friends[0]"); +let a = jsonpath.select(JSON.stringify(jsonObj), "$..friends[0]"); +let b = jsonpath.select(jsonObj, "$..friends[0]"); console.log( JSON.stringify(ret) == JSON.stringify(a), JSON.stringify(a) == JSON.stringify(b) @@ -101,7 +102,7 @@ console.log(JSON.stringify(template(jsonObj2)) == ret2); console.log(JSON.stringify(template(JSON.stringify(jsonObj2))) == ret2); ``` -### javascript - jsonpath.reader(json: string|object) +### javascript - jsonpath.selector(json: string|object) ```javascript let jsonObj = { @@ -115,14 +116,55 @@ let ret1 = JSON.stringify([ {"id": 0}, {"id": 0} ]); let ret2 = JSON.stringify([ {"id": 1}, {"id": 1} ]); // 1. read as json object -let reader = jsonpath.reader(jsonObj); -console.log(JSON.stringify(reader("$..friends[0]")) == ret1); -console.log(JSON.stringify(reader("$..friends[1]")) == ret2); +let selector = jsonpath.selector(jsonObj); +console.log(JSON.stringify(selector("$..friends[0]")) == ret1); +console.log(JSON.stringify(selector("$..friends[1]")) == ret2); // 2. read as json string -let reader2 = jsonpath.reader(JSON.stringify(jsonObj)); -console.log(JSON.stringify(reader2("$..friends[0]")) == ret1); -console.log(JSON.stringify(reader2("$..friends[1]")) == ret2); +let selector = jsonpath.selector(JSON.stringify(jsonObj)); +console.log(JSON.stringify(selector("$..friends[0]")) == ret1); +console.log(JSON.stringify(selector("$..friends[1]")) == ret2); +``` + +### javascript - alloc_json, dealloc_json + +wasm-bindgen은 Javascript와 Webassembly 간 값을 주고받을 때 JSON 객체는 String으로 변환되기 때문에, 반복해서 사용되는 JSON 객체를 Webassembly 영역에 생성해 두면 성능에 도움이 된다. + +Since wasm-bindgen converts JSON objects to String when exchanging values between Javascript and Webassembly, it is helpful to create repeated Json objects in Webassembly area. + +```javascript + +let jsonObj = { + "school": { + "friends": [{"id": 0}, {"id": 1}] + }, + "friends": [{"id": 0},{"id": 1}] +}; + +let path = '$..friends[0]'; +let template = jsonpath.compile(path); +let selector = jsonpath.selector(jsonObj); + +let ptr = jsonpath.alloc_json(jsonObj); +if(ptr == 0) console.error('invalid ptr'); // `0` is invalid pointer +let selector2 = jsonpath.selector(ptr); + +let ret1 = selector(path) +let ret2 = selector2(path) +let ret3 = template(jsonObj); +let ret4 = template(ptr); +let ret5 = jsonpath.select(jsonObj, path); +let ret6 = jsonpath.select(ptr, path); + +console.log( + JSON.stringify(ret1) == JSON.stringify(ret2),// true + JSON.stringify(ret1) == JSON.stringify(ret3),// true + JSON.stringify(ret1) == JSON.stringify(ret4),// true + JSON.stringify(ret1) == JSON.stringify(ret5),// true + JSON.stringify(ret1) == JSON.stringify(ret6));// true + +jsonpath.dealloc_json(ptr); + ``` ### javascript - examples @@ -201,7 +243,7 @@ extern crate jsonpath_lib as jsonpath; extern crate serde_json; ``` -### rust - jsonpath::read(json: serde_json::value::Value, jsonpath: &str) +### rust - jsonpath::select(json: serde_json::value::Value, jsonpath: &str) ```rust let json_obj = json!({ @@ -210,7 +252,7 @@ let json_obj = json!({ }, "friends": [{"id": 0}, {"id": 1}] }); -let json = jsonpath::read(json_obj, "$..friends[0]").unwrap(); +let json = jsonpath::select(json_obj, "$..friends[0]").unwrap(); let ret = json!([ {"id": 0}, {"id": 0} ]); assert_eq!(json, ret) ``` @@ -243,7 +285,7 @@ let ret = json!([ {"id": 0}, {"name": "Millicent Norman"} ]); assert_eq!(json, ret); ``` -### rust - jsonpath::reader(json: serde_json::value::Value) +### rust - jsonpath::selector(json: serde_json::value::Value) ```rust let json_obj = json!({ @@ -253,13 +295,13 @@ let json_obj = json!({ "friends": [{"id": 0},{"id": 1}] }); -let mut reader = jsonpath::reader(json_obj); +let mut selector = jsonpath::selector(json_obj); -let json = reader("$..friends[0]").unwrap(); +let json = selector("$..friends[0]").unwrap(); let ret = json!([ {"id": 0}, {"id": 0} ]); assert_eq!(json, ret); -let json = reader("$..friends[1]").unwrap(); +let json = selector("$..friends[1]").unwrap(); let ret = json!([ {"id": 1}, {"id": 1} ]); assert_eq!(json, ret); ``` @@ -305,13 +347,13 @@ let json_obj = json!({ "expensive": 10 }); -let mut reader = jsonpath::reader(json_obj); +let mut selector = jsonpath::selector(json_obj); ``` #### $.store.book[*].author ```rust -let json = reader("$.store.book[*].author").unwrap(); +let json = selector("$.store.book[*].author").unwrap(); let ret = json!([ "Nigel Rees", "Evelyn Waugh", @@ -323,7 +365,7 @@ assert_eq!(json, ret); #### $..author ```rust -let json = reader("$..author").unwrap(); +let json = selector("$..author").unwrap(); let ret = json!([ "Nigel Rees", "Evelyn Waugh", @@ -335,7 +377,7 @@ assert_eq!(json, ret); #### $.store.* ```rust -let json = reader("$.store.*").unwrap(); +let json = selector("$.store.*").unwrap(); let ret = json!([ [ { @@ -375,14 +417,14 @@ assert_eq!(ret, json); #### $.store..price ```rust -let json = reader("$.store..price").unwrap(); +let json = selector("$.store..price").unwrap(); let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]); assert_eq!(ret, json); ``` #### $..book[2] ```rust -let json = reader("$..book[2]").unwrap(); +let json = selector("$..book[2]").unwrap(); let ret = json!([{ "category" : "fiction", "author" : "Herman Melville", @@ -395,7 +437,7 @@ assert_eq!(ret, json); #### $..book[-2] ```rust -let json = reader("$..book[-2]").unwrap(); +let json = selector("$..book[-2]").unwrap(); let ret = json!([{ "category" : "fiction", "author" : "Herman Melville", @@ -408,7 +450,7 @@ assert_eq!(ret, json); #### $..book[0,1] ```rust -let json = reader("$..book[0,1]").unwrap(); +let json = selector("$..book[0,1]").unwrap(); let ret = json!([ { "category": "reference", @@ -428,7 +470,7 @@ assert_eq!(ret, json); #### $..book[:2] ```rust -let json = reader("$..book[:2]").unwrap(); +let json = selector("$..book[:2]").unwrap(); let ret = json!([ { "category": "reference", @@ -448,7 +490,7 @@ assert_eq!(ret, json); #### $..book[2:] ```rust -let json = reader("$..book[2:]").unwrap(); +let json = selector("$..book[2:]").unwrap(); let ret = json!([ { "category": "fiction", @@ -470,7 +512,7 @@ assert_eq!(ret, json); #### $..book[?(@.isbn)] ```rust -let json = reader("$..book[?(@.isbn)]").unwrap(); +let json = selector("$..book[?(@.isbn)]").unwrap(); let ret = json!([ { "category": "fiction", @@ -492,7 +534,7 @@ assert_eq!(ret, json); #### $.store.book[?(@.price < 10)] ```rust -let json = reader("$.store.book[?(@.price < 10)]").unwrap(); +let json = selector("$.store.book[?(@.price < 10)]").unwrap(); let ret = json!([ { "category": "reference", @@ -513,7 +555,7 @@ assert_eq!(ret, json); #### $..book[?((@.price == 12.99 || $.store.bicycle.price < @.price) || @.category == "reference")] ```rust -let json = reader(r#"$..book[ +let json = selector(r#"$..book[ ?( (@.price == 12.99 || $.store.bicycle.price < @.price) || @.category == "reference" @@ -554,15 +596,21 @@ assert_eq!(ret, json); ### Browser [Bench Demo](https://freestrings.github.io/jsonpath/bench) +``` +'$..book[?(@.price<30 && @.category=="fiction")]' (loop 2,000) +``` + #### Chrome: 72.0 > Something to wrong in chrome ``` -jsonpath, 134 -jsonpath-wasm- reader, 1409 -jsonpath-wasm- compile, 3237 -jsonpath-wasm- read, 5302 +jsonpath, 166 +jsonpath-wasm- selector, 256 +jsonpath-wasm- compile, 1168 +jsonpath-wasm- compile-alloc, 645 +jsonpath-wasm- select, 3224 +jsonpath-wasm- select-alloc, 1427 ``` #### Firefox: 65.0 @@ -570,40 +618,65 @@ jsonpath-wasm- read, 5302 > jsonpath-wasm is faster than jsonpath ``` -jsonpath, 301 -jsonpath-wasm- reader, 166 -jsonpath-wasm- compile, 130 -jsonpath-wasm- read, 144 +jsonpath, 125 +jsonpath-wasm- selector, 101 +jsonpath-wasm- compile, 169 +jsonpath-wasm- compile-alloc, 78 +jsonpath-wasm- select, 186 +jsonpath-wasm- select-alloc, 93 ``` ### NodeJs * NodeJS: 11.0 -* CPU: Intel Core i5-4460 -* Memory: 16GB > Rust > jsonpath > jsonpath-wasm + ```bash cd benches && ./bench_node_vs_rust.sh - $..book[?(@.price<30 && @.category==fiction)] (loop 100,000) Rust: -real 0m1.141s -user 0m1.137s -sys 0m0.004s +real 0m0.862s +user 0m0.862s +sys 0m0.000s NodeJs - jsonpath module: -real 0m3.718s -user 0m4.175s -sys 0m0.050s +real 0m3.667s +user 0m4.139s +sys 0m0.045s -NodeJs - jsonpath-wasm module: +NodeJs - jsonpath-wasm module - selector: + +real 0m5.331s +user 0m5.494s +sys 0m0.093s + +NodeJs - jsonpath-wasm module - compile: + +real 0m8.665s +user 0m8.809s +sys 0m0.197s + +NodeJs - jsonpath-wasm module - compile-alloc: + +real 0m4.014s +user 0m4.173s +sys 0m0.088s + +NodeJs - jsonpath-wasm module - select: + +real 0m9.843s +user 0m9.897s +sys 0m0.244s + +NodeJs - jsonpath-wasm module - select-alloc: + +real 0m5.212s +user 0m5.339s +sys 0m0.096s -real 0m10.205s -user 0m10.281s -sys 0m0.383s ``` \ No newline at end of file diff --git a/benches/bench_bin/Cargo.toml b/benches/bench_bin/Cargo.toml index c11ab6b..d7d1690 100644 --- a/benches/bench_bin/Cargo.toml +++ b/benches/bench_bin/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bench_bin" -version = "0.1.0" +version = "0.1.1" [dependencies] jsonpath_lib = {path = "../../"} diff --git a/benches/bench_bin/src/main.rs b/benches/bench_bin/src/main.rs index 9eee77c..00174f1 100644 --- a/benches/bench_bin/src/main.rs +++ b/benches/bench_bin/src/main.rs @@ -14,8 +14,8 @@ fn read_json(path: &str) -> String { fn main() { let string = read_json("../example.json"); let json: Value = serde_json::from_str(string.as_str()).unwrap(); - let mut reader = jsonpath::reader(json); + let mut selector = jsonpath::selector(json); for _ in 1..100000 { - let _ = reader(r#"$..book[?(@.price<30 && @.category=="fiction")]"#).unwrap(); + let _ = selector(r#"$..book[?(@.price<30 && @.category=="fiction")]"#).unwrap(); } } diff --git a/benches/bench_node_vs_rust.sh b/benches/bench_node_vs_rust.sh index 99bd5c1..974760f 100755 --- a/benches/bench_node_vs_rust.sh +++ b/benches/bench_node_vs_rust.sh @@ -10,6 +10,14 @@ printf "\n\n" echo "Rust: " && time ./bench.sh printf "\n" -cd "${DIR}"/javascript && echo "NodeJs - jsonpath module: " && time ./bench.sh jsonpathOnly +cd "${DIR}"/javascript && echo "NodeJs - jsonpath module: " && time ./bench.sh jsonpath printf "\n" -cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm module: " && time ./bench.sh jsonpathWasmOnly +cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm module - selector: " && time ./bench.sh wasmSelector +printf "\n" +cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm module - compile: " && time ./bench.sh wasmCompile +printf "\n" +cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm module - compile-alloc: " && time ./bench.sh wasmCompileAlloc +printf "\n" +cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm module - select:" && time ./bench.sh wasmSelect +printf "\n" +cd "${DIR}"/javascript && echo "NodeJs - jsonpath-wasm module - select-alloc:" && time ./bench.sh wasmSelectAlloc \ No newline at end of file diff --git a/benches/javascript/bench.js b/benches/javascript/bench.js index b7ade0c..4927116 100644 --- a/benches/javascript/bench.js +++ b/benches/javascript/bench.js @@ -1,118 +1,124 @@ let json = { - "store": { - "book": [ + 'store': { + 'book': [ { - "category": "reference", - "author": "Nigel Rees", - "title": "Sayings of the Century", - "price": 8.95 + 'category': 'reference', + 'author': 'Nigel Rees', + 'title': 'Sayings of the Century', + 'price': 8.95, }, { - "category": "fiction", - "author": "Evelyn Waugh", - "title": "Sword of Honour", - "price": 12.99 + 'category': 'fiction', + 'author': 'Evelyn Waugh', + 'title': 'Sword of Honour', + 'price': 12.99, }, { - "category": "fiction", - "author": "Herman Melville", - "title": "Moby Dick", - "isbn": "0-553-21311-3", - "price": 8.99 + 'category': 'fiction', + 'author': 'Herman Melville', + 'title': 'Moby Dick', + 'isbn': '0-553-21311-3', + 'price': 8.99, }, { - "category": "fiction", - "author": "J. R. R. Tolkien", - "title": "The Lord of the Rings", - "isbn": "0-395-19395-8", - "price": 22.99 - } + 'category': 'fiction', + 'author': 'J. R. R. Tolkien', + 'title': 'The Lord of the Rings', + 'isbn': '0-395-19395-8', + 'price': 22.99, + }, ], - "bicycle": { - "color": "red", - "price": 19.95 - } + 'bicycle': { + 'color': 'red', + 'price': 19.95, + }, }, - "expensive": 10 + 'expensive': 10, }; const jp = require('jsonpath'); const jpw = require('@nodejs/jsonpath-wasm'); -const Benchmark = require('benchmark'); +const iter = 100000; -function compareJsonpath(path) { - let r1 = jp.query(json, path); - let r2 = jpw.read(json, path); - - let template = jpw.compile(path); - - var suite = new Benchmark.Suite; - - suite.add('jp', function() { - jp.query(json, path); - }) - .add('jpw', function() { - template(json); - }) - .on('cycle', function(event) { - console.log(String(event.target)); - }) - .on('complete', function() { - console.log('Fastest is ' + this.filter('fastest').map('name')); - console.log('Slowest is ' + this.filter('slowest').map('name')); - }) - .run({ 'async': true }); -} - -function compareEmptyFunction() { - var suite = new Benchmark.Suite; - - suite.add('js', function() { - }) - .add('rust', function() { - jpw.testa(); - }) - .on('cycle', function(event) { - console.log(String(event.target)); - }) - .on('complete', function() { - console.log('Fastest is ' + this.filter('fastest').map('name')); - console.log('Slowest is ' + this.filter('slowest').map('name')); - }) - .run({}); -} - -function jsonpathOnly() { - for(var i = 0; i < 100000 ; i++) { +function jsonpath() { + for (var i = 0; i < iter; i++) { let _ = jp.query(json, '$..book[?(@.price<30 && @.category=="fiction")]'); } } -function jsonpathWasmOnly() { - let reader = jpw.reader(json); - for(var i = 0; i < 100000 ; i++) { - let _ = reader('$..book[?(@.price<30 && @.category=="fiction")]'); +function wasmSelector() { + let selector = jpw.selector(json); + for (var i = 0; i < iter; i++) { + let _ = selector('$..book[?(@.price<30 && @.category=="fiction")]'); } } -if(process.argv.length < 3) { - let functions = ['', 'compareJsonpath', 'compareEmptyFunction', 'jsonpathOnly', 'jsonpathWasmOnly']; - console.log("node bench.js", functions.join("\n\t|")); - return; +function wasmCompile() { + let template = jpw.compile('$..book[?(@.price<30 && @.category=="fiction")]'); + for (var i = 0; i < iter; i++) { + let _ = template(json); + } +} + +function wasmCompileAlloc() { + let ptr = jpw.alloc_json(json); + if (ptr == 0) { + console.error('Invalid pointer'); + return; + } + + try { + let template = jpw.compile('$..book[?(@.price<30 && @.category=="fiction")]'); + for (var i = 0; i < iter; i++) { + let _ = template(ptr); + } + } finally { + jpw.dealloc_json(ptr); + } +} + +function wasmSelect() { + for (var i = 0; i < iter; i++) { + let _ = jpw.select(json, '$..book[?(@.price<30 && @.category=="fiction")]'); + } +} + +function wasmSelectAlloc() { + let ptr = jpw.alloc_json(json); + if (ptr == 0) { + console.error('Invalid pointer'); + return; + } + + try { + for (var i = 0; i < iter; i++) { + let _ = jpw.select(ptr, '$..book[?(@.price<30 && @.category=="fiction")]'); + } + } finally { + jpw.dealloc_json(ptr); + } } let functionName = process.argv[2]; switch (functionName) { - case 'compareJsonpath': - compareJsonpath('$..book[?(@.price<30 && @.category=="fiction")]'); + case 'jsonpath': + jsonpath(); break; - case 'compareEmptyFunction': - compareEmptyFunction(); + case 'wasmSelector': + wasmSelector(); break; - case 'jsonpathWasmOnly': - jsonpathWasmOnly(); + case 'wasmCompile': + wasmCompile(); break; + case 'wasmSelect': + wasmSelect(); + break; + case 'wasmCompileAlloc': + wasmCompileAlloc(); + break; + case 'wasmSelectAlloc': + wasmSelectAlloc(); default: - jsonpathOnly(); -} \ No newline at end of file + console.error('Invalid function name'); +} diff --git a/benches/javascript/package-lock.json b/benches/javascript/package-lock.json index 77b7634..bb77472 100644 --- a/benches/javascript/package-lock.json +++ b/benches/javascript/package-lock.json @@ -9,15 +9,6 @@ "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" }, - "benchmark": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", - "integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=", - "requires": { - "lodash": "^4.17.4", - "platform": "^1.3.3" - } - }, "cjson": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.2.1.tgz", @@ -131,11 +122,6 @@ "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" - }, "nomnom": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", @@ -165,11 +151,6 @@ "wordwrap": "~1.0.0" } }, - "platform": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", - "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==" - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", diff --git a/benches/javascript/package.json b/benches/javascript/package.json index 6913866..2ef7ddd 100644 --- a/benches/javascript/package.json +++ b/benches/javascript/package.json @@ -6,7 +6,6 @@ "test": "echo \"Error: no test specified\" && exit 1" }, "dependencies": { - "jsonpath": "*", - "benchmark": "*" + "jsonpath": "*" } } diff --git a/docs/0.bootstrap.js b/docs/0.bootstrap.js index e8a75d0..24514ce 100644 --- a/docs/0.bootstrap.js +++ b/docs/0.bootstrap.js @@ -1,25 +1,25 @@ (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{ -/***/ "../pkg/jsonpath_wasm.js": -/*!*******************************!*\ - !*** ../pkg/jsonpath_wasm.js ***! - \*******************************/ -/*! exports provided: compile, reader, read, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_string_new, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper28, __wbindgen_closure_wrapper30, __wbindgen_throw */ +/***/ "../browser_pkg/jsonpath_wasm.js": +/*!***************************************!*\ + !*** ../browser_pkg/jsonpath_wasm.js ***! + \***************************************/ +/*! 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_wrapper101, __wbindgen_closure_wrapper103, __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__, \"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__, \"read\", function() { return read; });\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_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_wrapper28\", function() { return __wbindgen_closure_wrapper28; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper30\", function() { return __wbindgen_closure_wrapper30; });\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 */ \"../pkg/jsonpath_wasm_bg.wasm\");\n/* tslint:disable */\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\nconst heap = new Array(32);\n\nheap.fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nfunction getObject(idx) { return heap[idx]; }\n\nlet heap_next = heap.length;\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\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 {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* @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\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_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_wrapper28(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(9);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(10);\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_wrapper30(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(11);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(12);\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:///../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_wrapper101\", function() { return __wbindgen_closure_wrapper101; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper103\", function() { return __wbindgen_closure_wrapper103; });\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_wrapper101(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(16);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(17);\n const cb = function(arg0) {\n this.cnt++;\n 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_wrapper103(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_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?"); /***/ }), -/***/ "../pkg/jsonpath_wasm_bg.wasm": -/*!************************************!*\ - !*** ../pkg/jsonpath_wasm_bg.wasm ***! - \************************************/ -/*! exports provided: memory, compile, reader, read, __wbindgen_malloc, __wbindgen_free, __wbg_function_table */ +/***/ "../browser_pkg/jsonpath_wasm_bg.wasm": +/*!********************************************!*\ + !*** ../browser_pkg/jsonpath_wasm_bg.wasm ***! + \********************************************/ +/*! 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 */ \"../pkg/jsonpath_wasm.js\");\n\n\n// exec wasm module\nwasmExports[\"__webpack_init__\"]()\n\n//# sourceURL=webpack:///../pkg/jsonpath_wasm_bg.wasm?"); +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?"); /***/ }), @@ -31,7 +31,7 @@ eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __we /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! jsonpath-wasm */ \"../pkg/jsonpath_wasm.js\");\n\n\nfunction getTextarea() {\n return document.querySelector('#json-example');\n}\n\nfunction getJsonpathInput() {\n return document.querySelector('#jsonpath-input');\n}\n\nfunction getReadBtn() {\n return document.querySelector('#read-json');\n}\n\nfunction getReadResult() {\n return document.querySelector('#read-result');\n}\n\nfunction initData(url) {\n return fetch(url)\n .then((res) => res.text())\n .then((jsonStr) => getTextarea().value = jsonStr)\n .catch(console.error);\n}\n\nfunction initEvent() {\n getJsonpathInput().onkeyup = function(e) {\n var charCode = (typeof e.which === \"number\") ? e.which : e.keyCode;\n if(charCode == 13) {\n read();\n }\n }\n\n getReadBtn().onclick = function() {\n read();\n }\n\n function read() {\n let ret = jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"read\"](getTextarea().value, getJsonpathInput().value);\n if(typeof ret === 'string') {\n getReadResult().innerText = ret;\n } else {\n getReadResult().innerText = JSON.stringify(ret, null, 2);\n }\n }\n}\n\nfunction readPathParam() {\n let params = location.search.substr(1)\n .split('&')\n .map((item) => item.split('='))\n .reduce((acc, param) => {\n acc[param[0]] = decodeURIComponent(param[1]);\n return acc;\n }, {});\n\n if(params.path) {\n getJsonpathInput().value = params.path;\n let doc = getReadBtn().ownerDocument;\n let event = doc.createEvent('MouseEvents');\n event.initEvent('click', true, true);\n event.synthetic = true;\n getReadBtn().dispatchEvent(event, true);\n }\n}\n\ninitData('data/example.json').then(initEvent).then(readPathParam);\n\n//# sourceURL=webpack:///./index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @browser/jsonpath-wasm */ \"../browser_pkg/jsonpath_wasm.js\");\n\n\nfunction getTextarea() {\n return document.querySelector('#json-example');\n}\n\nfunction getJsonpathInput() {\n return document.querySelector('#jsonpath-input');\n}\n\nfunction getReadBtn() {\n return document.querySelector('#read-json');\n}\n\nfunction getReadResult() {\n return document.querySelector('#read-result');\n}\n\nfunction initData(url) {\n return fetch(url)\n .then((res) => res.text())\n .then((jsonStr) => getTextarea().value = jsonStr)\n .catch(console.error);\n}\n\nfunction initEvent() {\n getJsonpathInput().onkeyup = function(e) {\n var charCode = (typeof e.which === \"number\") ? e.which : e.keyCode;\n if(charCode == 13) {\n read();\n }\n }\n\n getReadBtn().onclick = function() {\n read();\n }\n\n function read() {\n let ret = _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"read\"](getTextarea().value, getJsonpathInput().value);\n if(typeof ret === 'string') {\n getReadResult().innerText = ret;\n } else {\n getReadResult().innerText = JSON.stringify(ret, null, 2);\n }\n }\n}\n\nfunction readPathParam() {\n let params = location.search.substr(1)\n .split('&')\n .map((item) => item.split('='))\n .reduce((acc, param) => {\n acc[param[0]] = decodeURIComponent(param[1]);\n return acc;\n }, {});\n\n if(params.path) {\n getJsonpathInput().value = params.path;\n let doc = getReadBtn().ownerDocument;\n let event = doc.createEvent('MouseEvents');\n event.initEvent('click', true, true);\n event.synthetic = true;\n getReadBtn().dispatchEvent(event, true);\n }\n}\n\ninitData('data/example.json').then(initEvent).then(readPathParam);\n\n//# sourceURL=webpack:///./index.js?"); /***/ }) diff --git a/docs/9a826648f4cbc2bc8591.module.wasm b/docs/9a826648f4cbc2bc8591.module.wasm new file mode 100644 index 0000000..b09af39 Binary files /dev/null and b/docs/9a826648f4cbc2bc8591.module.wasm differ diff --git a/docs/bench/0.bootstrap.js b/docs/bench/0.bootstrap.js index f111607..f43bb0e 100644 --- a/docs/bench/0.bootstrap.js +++ b/docs/bench/0.bootstrap.js @@ -4,11 +4,11 @@ /*!***************************************!*\ !*** ../browser_pkg/jsonpath_wasm.js ***! \***************************************/ -/*! exports provided: compile, reader, read, testa, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_string_new, __wbindgen_is_string, __wbindgen_string_get, __wbindgen_cb_forget, __wbindgen_json_parse, __wbindgen_json_serialize, __wbindgen_closure_wrapper33, __wbindgen_closure_wrapper35, __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_wrapper101, __wbindgen_closure_wrapper103, __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__, \"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__, \"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__, \"__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_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_wrapper33\", function() { return __wbindgen_closure_wrapper33; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper35\", function() { return __wbindgen_closure_wrapper35; });\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\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\nconst heap = new Array(32);\n\nheap.fill(undefined);\n\nheap.push(undefined, null, true, false);\n\nfunction getObject(idx) { return heap[idx]; }\n\nlet heap_next = heap.length;\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\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 {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* @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 __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_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_wrapper33(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(5);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(6);\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_wrapper35(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(3);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(4);\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_wrapper101\", function() { return __wbindgen_closure_wrapper101; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"__wbindgen_closure_wrapper103\", function() { return __wbindgen_closure_wrapper103; });\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_wrapper101(a, b, _ignored) {\n const f = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(16);\n const d = _jsonpath_wasm_bg__WEBPACK_IMPORTED_MODULE_0__[\"__wbg_function_table\"].get(17);\n const cb = function(arg0) {\n this.cnt++;\n 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_wrapper103(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_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, compile, reader, 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?"); @@ -31,7 +31,7 @@ eval("\"use strict\";\n// Instantiate WebAssembly module\nvar wasmExports = __we /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @browser/jsonpath-wasm */ \"../browser_pkg/jsonpath_wasm.js\");\n/* harmony import */ var jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! jsonpath/jsonpath.js */ \"./node_modules/jsonpath/jsonpath.js\");\n/* harmony import */ var jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nfunction run(message, iter, cb) {\n let d = Date.now();\n for (let i = 0; i < iter; i++) {\n cb();\n }\n msg([message, Date.now() - d].join(\", \"));\n}\n\nfunction msg(msg) {\n console.log(msg);\n let div = document.createElement(\"div\");\n div.innerText = msg;\n document.body.appendChild(div);\n}\n\nlet json = {\n \"store\": {\n \"book\": [\n {\n \"category\": \"reference\",\n \"author\": \"Nigel Rees\",\n \"title\": \"Sayings of the Century\",\n \"price\": 8.95\n },\n {\n \"category\": \"fiction\",\n \"author\": \"Evelyn Waugh\",\n \"title\": \"Sword of Honour\",\n \"price\": 12.99\n },\n {\n \"category\": \"fiction\",\n \"author\": \"Herman Melville\",\n \"title\": \"Moby Dick\",\n \"isbn\": \"0-553-21311-3\",\n \"price\": 8.99\n },\n {\n \"category\": \"fiction\",\n \"author\": \"J. R. R. Tolkien\",\n \"title\": \"The Lord of the Rings\",\n \"isbn\": \"0-395-19395-8\",\n \"price\": 22.99\n }\n ],\n \"bicycle\": {\n \"color\": \"red\",\n \"price\": 19.95\n }\n },\n \"expensive\": 10\n};\n\nsetTimeout(function() {\n let path = '$..book[?(@.price<30 && @.category==\"fiction\")]';\n let template = _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"compile\"](path);\n let reader = _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"reader\"](json);\n run('jsonpath', 1000, function() { jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1__[\"query\"](json, path) });\n run('jsonpath-wasm- reader', 1000, function() { reader(path) });\n run('jsonpath-wasm- compile', 1000, function() { template(json) });\n run('jsonpath-wasm- read', 1000, function() { _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"read\"](json, path) });\n}, 0);\n\n\n//# sourceURL=webpack:///./index.js?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @browser/jsonpath-wasm */ \"../browser_pkg/jsonpath_wasm.js\");\n/* harmony import */ var jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! jsonpath/jsonpath.js */ \"./node_modules/jsonpath/jsonpath.js\");\n/* harmony import */ var jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1__);\n\n\n\nfunction run(message, iter, cb) {\n return new Promise(function(resolve, _reject) {\n let d = Date.now();\n for (let i = 0; i < iter; i++) {\n cb();\n }\n msg([message, Date.now() - d].join(\", \"));\n setTimeout(resolve, 0);\n })\n}\n\nfunction msg(msg) {\n console.log(msg);\n let div = document.createElement(\"div\");\n div.innerText = msg;\n document.body.appendChild(div);\n}\n\nlet json = {\n \"store\": {\n \"book\": [\n {\n \"category\": \"reference\",\n \"author\": \"Nigel Rees\",\n \"title\": \"Sayings of the Century\",\n \"price\": 8.95\n },\n {\n \"category\": \"fiction\",\n \"author\": \"Evelyn Waugh\",\n \"title\": \"Sword of Honour\",\n \"price\": 12.99\n },\n {\n \"category\": \"fiction\",\n \"author\": \"Herman Melville\",\n \"title\": \"Moby Dick\",\n \"isbn\": \"0-553-21311-3\",\n \"price\": 8.99\n },\n {\n \"category\": \"fiction\",\n \"author\": \"J. R. R. Tolkien\",\n \"title\": \"The Lord of the Rings\",\n \"isbn\": \"0-395-19395-8\",\n \"price\": 22.99\n }\n ],\n \"bicycle\": {\n \"color\": \"red\",\n \"price\": 19.95\n }\n },\n \"expensive\": 10\n};\n\nlet path = '$..book[?(@.price<30 && @.category==\"fiction\")]';\nlet template = _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"compile\"](path);\nlet selector = _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"selector\"](json);\n\nlet ptr = _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"alloc_json\"](json);\nif(ptr == 0) console.error('invalid ptr');\n\nlet iterCount = 3000;\n\nrun('jsonpath', iterCount, function() { jsonpath_jsonpath_js__WEBPACK_IMPORTED_MODULE_1__[\"query\"](json, path) })\n .then(function() {\n return run('jsonpath-wasm- selector', iterCount, function() { selector(path) });\n })\n .then(function() {\n return run('jsonpath-wasm- compile', iterCount, function() { template(json) });\n })\n .then(function() {\n return run('jsonpath-wasm- compile-alloc', iterCount, function() { template(ptr) });\n })\n .then(function() {\n return run('jsonpath-wasm- select', iterCount, function() { _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"select\"](json, path) });\n })\n .then(function() {\n return run('jsonpath-wasm- select-alloc', iterCount, function() { _browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"select\"](ptr, path) });\n })\n .finally(function() {\n if(!_browser_jsonpath_wasm__WEBPACK_IMPORTED_MODULE_0__[\"dealloc_json\"](ptr)) {\n console.error('fail to dealloc');\n }\n });\n\n\n//# sourceURL=webpack:///./index.js?"); /***/ }) diff --git a/docs/bench/95acaf85df86c0a76234.module.wasm b/docs/bench/95acaf85df86c0a76234.module.wasm deleted file mode 100644 index 3c25a96..0000000 Binary files a/docs/bench/95acaf85df86c0a76234.module.wasm and /dev/null differ diff --git a/docs/bench/9a826648f4cbc2bc8591.module.wasm b/docs/bench/9a826648f4cbc2bc8591.module.wasm new file mode 100644 index 0000000..b09af39 Binary files /dev/null and b/docs/bench/9a826648f4cbc2bc8591.module.wasm differ diff --git a/docs/bench/bootstrap.js b/docs/bench/bootstrap.js index b747c52..cd45796 100644 --- a/docs/bench/bootstrap.js +++ b/docs/bench/bootstrap.js @@ -55,20 +55,29 @@ /******/ "../browser_pkg/jsonpath_wasm_bg.wasm": function() { /******/ return { /******/ "./jsonpath_wasm": { +/******/ "__wbindgen_string_new": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32); +/******/ }, +/******/ "__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); +/******/ }, /******/ "__wbindgen_json_parse": function(p0i32,p1i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32); /******/ }, /******/ "__wbindgen_json_serialize": function(p0i32,p1i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32); /******/ }, -/******/ "__wbindgen_cb_forget": function(p0i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32); +/******/ "__widl_f_log_1_": function(p0i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__widl_f_log_1_"](p0i32); /******/ }, -/******/ "__wbindgen_object_drop_ref": function(p0i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32); -/******/ }, -/******/ "__wbindgen_string_new": function(p0i32,p1i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32); +/******/ "__wbindgen_number_get": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_number_get"](p0i32,p1i32); /******/ }, /******/ "__wbindgen_is_string": function(p0i32) { /******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32); @@ -76,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_wrapper33": function(p0i32,p1i32,p2i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper33"](p0i32,p1i32,p2i32); +/******/ "__wbindgen_closure_wrapper101": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper101"](p0i32,p1i32,p2i32); /******/ }, -/******/ "__wbindgen_closure_wrapper35": function(p0i32,p1i32,p2i32) { -/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper35"](p0i32,p1i32,p2i32); +/******/ "__wbindgen_closure_wrapper103": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper103"](p0i32,p1i32,p2i32); /******/ } /******/ } /******/ }; @@ -186,7 +192,7 @@ /******/ promises.push(installedWasmModuleData); /******/ else { /******/ var importObject = wasmImportObjects[wasmModuleId](); -/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"95acaf85df86c0a76234"}[wasmModuleId] + ".module.wasm"); +/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"9a826648f4cbc2bc8591"}[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/bootstrap.js b/docs/bootstrap.js index 9205dbf..1c451f3 100644 --- a/docs/bootstrap.js +++ b/docs/bootstrap.js @@ -52,41 +52,47 @@ /******/ function promiseResolve() { return Promise.resolve(); } /******/ /******/ var wasmImportObjects = { -/******/ "../pkg/jsonpath_wasm_bg.wasm": function() { +/******/ "../browser_pkg/jsonpath_wasm_bg.wasm": function() { /******/ return { /******/ "./jsonpath_wasm": { -/******/ "__wbindgen_json_parse": function(p0i32,p1i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32); -/******/ }, -/******/ "__wbindgen_json_serialize": function(p0i32,p1i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32); -/******/ }, -/******/ "__wbindgen_cb_forget": function(p0i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32); +/******/ "__wbindgen_string_new": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32); /******/ }, /******/ "__wbindgen_object_drop_ref": function(p0i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32); -/******/ }, -/******/ "__wbindgen_string_new": function(p0i32,p1i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32); -/******/ }, -/******/ "__wbindgen_is_string": function(p0i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32); -/******/ }, -/******/ "__wbindgen_string_get": function(p0i32,p1i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32); +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32); /******/ }, /******/ "__wbindgen_object_clone_ref": function(p0i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](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); +/******/ }, +/******/ "__wbindgen_json_parse": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32); +/******/ }, +/******/ "__wbindgen_json_serialize": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32); +/******/ }, +/******/ "__widl_f_log_1_": function(p0i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__widl_f_log_1_"](p0i32); +/******/ }, +/******/ "__wbindgen_number_get": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_number_get"](p0i32,p1i32); +/******/ }, +/******/ "__wbindgen_is_string": function(p0i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32); +/******/ }, +/******/ "__wbindgen_string_get": function(p0i32,p1i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32); /******/ }, /******/ "__wbindgen_throw": function(p0i32,p1i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32); +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ }, -/******/ "__wbindgen_closure_wrapper28": function(p0i32,p1i32,p2i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper28"](p0i32,p1i32,p2i32); +/******/ "__wbindgen_closure_wrapper101": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper101"](p0i32,p1i32,p2i32); /******/ }, -/******/ "__wbindgen_closure_wrapper30": function(p0i32,p1i32,p2i32) { -/******/ return installedModules["../pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper30"](p0i32,p1i32,p2i32); +/******/ "__wbindgen_closure_wrapper103": function(p0i32,p1i32,p2i32) { +/******/ return installedModules["../browser_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper103"](p0i32,p1i32,p2i32); /******/ } /******/ } /******/ }; @@ -176,7 +182,7 @@ /******/ /******/ // Fetch + compile chunk loading for webassembly /******/ -/******/ var wasmModules = {"0":["../pkg/jsonpath_wasm_bg.wasm"]}[chunkId] || []; +/******/ var wasmModules = {"0":["../browser_pkg/jsonpath_wasm_bg.wasm"]}[chunkId] || []; /******/ /******/ wasmModules.forEach(function(wasmModuleId) { /******/ var installedWasmModuleData = installedWasmModules[wasmModuleId]; @@ -186,7 +192,7 @@ /******/ promises.push(installedWasmModuleData); /******/ else { /******/ var importObject = wasmImportObjects[wasmModuleId](); -/******/ var req = fetch(__webpack_require__.p + "" + {"../pkg/jsonpath_wasm_bg.wasm":"d6c7cff8a1d228da11b7"}[wasmModuleId] + ".module.wasm"); +/******/ var req = fetch(__webpack_require__.p + "" + {"../browser_pkg/jsonpath_wasm_bg.wasm":"9a826648f4cbc2bc8591"}[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/d6c7cff8a1d228da11b7.module.wasm b/docs/d6c7cff8a1d228da11b7.module.wasm deleted file mode 100644 index f3672d8..0000000 Binary files a/docs/d6c7cff8a1d228da11b7.module.wasm and /dev/null differ diff --git a/src/filter/mod.rs b/src/filter/mod.rs index 493a667..fe47e4f 100644 --- a/src/filter/mod.rs +++ b/src/filter/mod.rs @@ -23,7 +23,7 @@ mod tests { fn new_value_filter(file: &str) -> ValueFilter { let string = read_json(file); let json: Value = serde_json::from_str(string.as_str()).unwrap(); - ValueFilter::new(json, false, false) + ValueFilter::new(json.into(), false, false) } fn do_filter(path: &str, file: &str) -> JsonValueFilter { @@ -71,7 +71,7 @@ mod tests { "Vincent Cannon", "Gray Berry" ]); - assert_eq!(&friends, current.get_val()); + assert_eq!(friends, current.get_val().into_value()); } let mut jf = new_value_filter("./benches/data_obj.json"); { @@ -84,7 +84,7 @@ mod tests { "Vincent Cannon", "Gray Berry" ]); - assert_eq!(&names, current.get_val()); + assert_eq!(names, current.get_val().into_value()); } } @@ -98,32 +98,32 @@ mod tests { ]); let jf = do_filter("$.school.friends[1, 2]", "./benches/data_obj.json"); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.school.friends[1:]", "./benches/data_obj.json"); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.school.friends[:-2]", "./benches/data_obj.json"); let friends = json!([ {"id": 0, "name": "Millicent Norman"} ]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$..friends[2].name", "./benches/data_obj.json"); let friends = json!(["Gray Berry", "Gray Berry"]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$..friends[*].name", "./benches/data_obj.json"); let friends = json!(["Vincent Cannon","Gray Berry","Millicent Norman","Vincent Cannon","Gray Berry"]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$['school']['friends'][*].['name']", "./benches/data_obj.json"); let friends = json!(["Millicent Norman","Vincent Cannon","Gray Berry"]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$['school']['friends'][0].['name']", "./benches/data_obj.json"); let friends = json!("Millicent Norman"); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); } #[test] @@ -139,16 +139,16 @@ mod tests { }); let jf = do_filter("$.school", "./benches/data_obj.json"); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.school[?(@.friends[0])]", "./benches/data_obj.json"); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.school[?(@.friends[10])]", "./benches/data_obj.json"); - assert_eq!(&Value::Null, jf.current_value()); + assert_eq!(Value::Null, jf.current_value().into_value()); let jf = do_filter("$.school[?(1==1)]", "./benches/data_obj.json"); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.school.friends[?(1==1)]", "./benches/data_obj.json"); let friends = json!([ @@ -156,7 +156,7 @@ mod tests { {"id": 1, "name": "Vincent Cannon" }, {"id": 2, "name": "Gray Berry"} ]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); } #[test] @@ -171,42 +171,42 @@ mod tests { {"id": 2, "name": "Gray Berry"} ] }); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.friends[?(@.name)]", "./benches/data_obj.json"); let friends = json!([ { "id" : 1, "name" : "Vincent Cannon" }, { "id" : 2, "name" : "Gray Berry" } ]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.friends[?(@.id >= 2)]", "./benches/data_obj.json"); let friends = json!([ { "id" : 2, "name" : "Gray Berry" } ]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.friends[?(@.id >= 2 || @.id == 1)]", "./benches/data_obj.json"); let friends = json!([ { "id" : 2, "name" : "Gray Berry" }, { "id" : 1, "name" : "Vincent Cannon" } ]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]", "./benches/data_obj.json"); - assert_eq!(&Value::Null, jf.current_value()); + assert_eq!(Value::Null, jf.current_value().into_value()); let jf = do_filter("$..friends[?(@.id == $.index)].id", "./benches/data_obj.json"); let friends = json!([0, 0]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$..book[?($.store.bicycle.price < @.price)].price", "./benches/example.json"); let friends = json!([22.99]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); let jf = do_filter("$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price", "./benches/example.json"); let friends = json!([12.99]); - assert_eq!(&friends, jf.current_value()); + assert_eq!(friends, jf.current_value().into_value()); } #[test] @@ -215,10 +215,10 @@ mod tests { let jf = do_filter("$.store.book[*].author", "./benches/example.json"); let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..author", "./benches/example.json"); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$.store.*", "./benches/example.json"); let ret = json!([ @@ -230,11 +230,11 @@ mod tests { ], {"color" : "red","price" : 19.95}, ]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$.store..price", "./benches/example.json"); let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..book[2]", "./benches/example.json"); let ret = json!([{ @@ -244,7 +244,7 @@ mod tests { "isbn" : "0-553-21311-3", "price" : 8.99 }]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..book[-2]", "./benches/example.json"); let ret = json!([{ @@ -254,7 +254,7 @@ mod tests { "isbn" : "0-553-21311-3", "price" : 8.99 }]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..book[0,1]", "./benches/example.json"); let ret = json!([ @@ -271,7 +271,7 @@ mod tests { "price" : 12.99 } ]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..book[:2]", "./benches/example.json"); let ret = json!([ @@ -288,7 +288,7 @@ mod tests { "price" : 12.99 } ]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..book[2:]", "./benches/example.json"); let ret = json!([ @@ -307,7 +307,7 @@ mod tests { "price" : 22.99 } ]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..book[?(@.isbn)]", "./benches/example.json"); let ret = json!([ @@ -326,7 +326,7 @@ mod tests { "price" : 22.99 } ]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$.store.book[?(@.price < 10)]", "./benches/example.json"); let ret = json!([ @@ -344,10 +344,10 @@ mod tests { "price" : 8.99 } ]); - assert_eq!(&ret, jf.current_value()); + assert_eq!(ret, jf.current_value().into_value()); let jf = do_filter("$..*", "./benches/example.json"); let json: Value = serde_json::from_str(read_json("./benches/giveme_every_thing_result.json").as_str()).unwrap(); - assert_eq!(&json, jf.current_value()); + assert_eq!(json, jf.current_value().into_value()); } } \ No newline at end of file diff --git a/src/filter/term.rs b/src/filter/term.rs index d738bc6..8fb2e6b 100644 --- a/src/filter/term.rs +++ b/src/filter/term.rs @@ -9,7 +9,7 @@ pub enum TermContext { } impl TermContext { - fn cmp(&mut self, other: &mut TermContext, cmp_fn: F, default: bool) -> TermContext { + fn cmp(&self, other: &TermContext, cmp_fn: F, default: bool) -> TermContext { match self { TermContext::Constants(et) => { match other { @@ -51,7 +51,7 @@ impl TermContext { } } - fn cmp_cond(&mut self, other: &mut TermContext, cmp_cond_type: CmpCondType) -> TermContext { + fn cmp_cond(&self, other: &TermContext, cmp_cond_type: CmpCondType) -> TermContext { match self { TermContext::Constants(et) => { match other { @@ -86,35 +86,35 @@ impl TermContext { } } - pub fn eq(&mut self, other: &mut TermContext) -> TermContext { + pub fn eq(&self, other: &TermContext) -> TermContext { self.cmp(other, CmpEq, false) } - pub fn ne(&mut self, other: &mut TermContext) -> TermContext { + pub fn ne(&self, other: &TermContext) -> TermContext { self.cmp(other, CmpNe, true) } - pub fn gt(&mut self, other: &mut TermContext) -> TermContext { + pub fn gt(&self, other: &TermContext) -> TermContext { self.cmp(other, CmpGt, false) } - pub fn ge(&mut self, other: &mut TermContext) -> TermContext { + pub fn ge(&self, other: &TermContext) -> TermContext { self.cmp(other, CmpGe, false) } - pub fn lt(&mut self, other: &mut TermContext) -> TermContext { + pub fn lt(&self, other: &TermContext) -> TermContext { self.cmp(other, CmpLt, false) } - pub fn le(&mut self, other: &mut TermContext) -> TermContext { + pub fn le(&self, other: &TermContext) -> TermContext { self.cmp(other, CmpLe, false) } - pub fn and(&mut self, other: &mut TermContext) -> TermContext { + pub fn and(&self, other: &TermContext) -> TermContext { self.cmp_cond(other, CmpCondType::And) } - pub fn or(&mut self, other: &mut TermContext) -> TermContext { + pub fn or(&self, other: &TermContext) -> TermContext { self.cmp_cond(other, CmpCondType::Or) } } diff --git a/src/filter/value_filter.rs b/src/filter/value_filter.rs index 8c08dba..4a4c2d8 100644 --- a/src/filter/value_filter.rs +++ b/src/filter/value_filter.rs @@ -1,29 +1,28 @@ -use core::borrow::Borrow; use std::error::Error; -use std::rc::Rc; use std::result; +use ref_value::*; + use serde_json::Value; use super::parser::*; - use super::term::*; use super::value_wrapper::*; trait ArrayIndex { - fn index(&self, v: &Value) -> usize; + fn index(&self, v: &RefValueWrapper) -> usize; - fn take_value(&self, v: &mut Value) -> Value { + fn take_value(&self, v: &RefValueWrapper) -> RefValueWrapper { let idx = self.index(v); - match v.get_mut(idx) { - Some(v) => v.take(), - _ => Value::Null + match v.get(idx) { + Some(v) => v, + _ => RefValue::Null.into() } } } impl ArrayIndex for f64 { - fn index(&self, v: &Value) -> usize { + fn index(&self, v: &RefValueWrapper) -> usize { if v.is_array() && self < &0_f64 { (v.as_array().unwrap().len() as f64 + self) as usize } else { @@ -33,7 +32,7 @@ impl ArrayIndex for f64 { } impl ArrayIndex for isize { - fn index(&self, v: &Value) -> usize { + fn index(&self, v: &RefValueWrapper) -> usize { if v.is_array() && self < &0_isize { (v.as_array().unwrap().len() as isize + self) as usize } else { @@ -43,7 +42,7 @@ impl ArrayIndex for isize { } impl ArrayIndex for usize { - fn index(&self, _: &Value) -> usize { + fn index(&self, _: &RefValueWrapper) -> usize { *self as usize } } @@ -63,54 +62,55 @@ pub struct ValueFilter { } impl ValueFilter { - pub fn new(v: Value, is_leaves: bool, filter_mode: bool) -> Self { + pub fn new(v: RefValueWrapper, is_leaves: bool, filter_mode: bool) -> Self { ValueFilter { vw: ValueWrapper::new(v, is_leaves), last_key: None, filter_mode } } - fn iter_to_value_vec<'a, I: Iterator>(iter: I) -> Vec { - iter.map(|v| v.take()) + fn iter_to_value_vec<'a, I: Iterator>(iter: I) -> Vec { + iter + .map(|v| v.clone()) .filter(|v| !v.is_null()) .collect() } - fn get_nested_array(v: &mut Value, key: F, filter_mode: bool) -> Value { + fn get_nested_array(v: &RefValueWrapper, key: F, filter_mode: bool) -> RefValueWrapper { if v.is_array() && v.as_array().unwrap().get(key.index(v)).is_some() { if filter_mode { - v.take() + v.clone() } else { let idx = key.index(v); - v.get_mut(idx).unwrap().take() + v.get(idx).unwrap().clone() } } else { key.take_value(v) } } - fn get_nested_object(v: &mut Value, key: &String, filter_mode: bool) -> Value { + fn get_nested_object(v: &RefValueWrapper, key: &String, filter_mode: bool) -> RefValueWrapper { if v.is_object() && v.as_object().unwrap().contains_key(key) { if filter_mode { - v.take() + v.clone() } else { - v.get_mut(key).unwrap().take() + v.get(key.clone()).unwrap().clone() } } else { - Value::Null + RefValue::Null.into() } } - fn collect_all(key: Option<&String>, v: &Value, buf: &mut Vec) { - match v { - Value::Array(vec) => { + fn collect_all(key: Option<&String>, v: &RefValueWrapper, buf: &mut Vec) { + match v.get_data_ref() { + RefValue::Array(vec) => { if key.is_none() { for v in vec { buf.push(v.clone()); } } for i in vec { - Self::collect_all(key, &i, buf); + Self::collect_all(key, &i.into(), buf); } } - Value::Object(v) => { + RefValue::Object(v) => { for (k, v) in v.into_iter() { if match key { Some(map_key) => map_key == k, @@ -120,7 +120,7 @@ impl ValueFilter { } } for (_, v) in v.into_iter() { - Self::collect_all(key, &v, buf); + Self::collect_all(key, &v.into(), buf); } } _ => {} @@ -133,7 +133,7 @@ impl ValueFilter { Self::collect_all(None, &self.vw.get_val(), &mut buf); trace!("step_leaves_all - {:?}", buf); self.last_key = Some(ValueFilterKey::All); - self.vw = ValueWrapper::new(Value::Array(buf), true); + self.vw = ValueWrapper::new(RefValue::Array(buf).into(), true); &self.vw } @@ -143,53 +143,63 @@ impl ValueFilter { pub fn step_leaves_string(&mut self, key: &String) -> &ValueWrapper { debug!("step_leaves_string"); - let mut buf: Vec = Vec::new(); + let mut buf = Vec::new(); Self::collect_all(Some(key), &self.vw.get_val(), &mut buf); trace!("step_leaves_string - {:?}", buf); self.last_key = Some(ValueFilterKey::String(key.clone())); - self.vw = ValueWrapper::new(Value::Array(buf), true); + self.vw = ValueWrapper::new(RefValue::Array(buf).into(), true); &self.vw } pub fn step_in_all(&mut self) -> &ValueWrapper { debug!("step_in_all"); - let vec = match &mut self.vw.get_val_mut() { - Value::Object(map) => Self::iter_to_value_vec(map.values_mut()), - Value::Array(list) => Self::iter_to_value_vec(list.iter_mut()), - Value::Null => Vec::new(), - other => vec![other.take()] + let vec = match self.vw.get_val().get_data_ref() { + RefValue::Object(ref map) => { + Self::iter_to_value_vec(map.values()) + } + RefValue::Array(ref list) => { + Self::iter_to_value_vec(list.iter()) + } + RefValue::Null => Vec::new(), + _ => vec![self.vw.get_val().clone_data()] }; self.last_key = Some(ValueFilterKey::All); - self.vw.replace(Value::Array(vec)); - trace!("step_in_all - {:?}", self.vw.get_val()); + self.vw.replace(RefValue::Array(vec).into()); + trace!("step_in_all - {:?}", self.vw.get_val().get_data_ref()); &self.vw } pub fn step_in_num(&mut self, key: &f64) -> &ValueWrapper { debug!("step_in_num"); - trace!("step_in_num - before: leaves {}, filterMode {} - {:?}", self.vw.is_leaves(), self.filter_mode, self.vw.get_val()); + trace!("step_in_num - before: leaves {}, filterMode {} - {:?}" + , self.vw.is_leaves() + , self.filter_mode + , self.vw.get_val().get_data_ref()); let v = if self.vw.is_leaves() { let filter_mode = self.filter_mode; - match &mut self.vw.get_val_mut() { - Value::Array(v) => { - let vec: Vec = v.iter_mut() - .map(|v| Self::get_nested_array(v, *key, filter_mode)) - .filter(|v| !v.is_null()) - .collect(); - Value::Array(vec) + match self.vw.get_val().get_data_ref() { + RefValue::Array(ref vec) => { + let mut ret = Vec::new(); + for v in vec { + let wrapper = Self::get_nested_array(&v.into(), *key, filter_mode); + if !wrapper.is_null() { + ret.push(wrapper.clone_data()); + } + } + RefValue::Array(ret).into() } - other => key.take_value(other) + _ => key.take_value(&self.vw.get_val()) } } else { - key.take_value(self.vw.get_val_mut()) + key.take_value(&self.vw.get_val()) }; self.last_key = Some(ValueFilterKey::Num(key.index(&v))); self.vw.replace(v); - trace!("step_in_num - after: {:?}", self.vw.get_val()); + trace!("step_in_num - after: {:?}", self.vw.get_val().get_data_ref()); &self.vw } @@ -199,55 +209,68 @@ impl ValueFilter { pub fn step_in_string(&mut self, key: &String) -> &ValueWrapper { debug!("step_in_string"); - trace!("step_in_string - before: {},{},{:?}", self.vw.is_leaves(), self.filter_mode, self.vw.get_val()); + trace!("step_in_string - before: {},{},{:?}" + , self.vw.is_leaves() + , self.filter_mode + , self.vw.get_val().get_data_ref()); let filter_mode = self.filter_mode; let is_leaves = self.vw.is_leaves(); - let v = match &mut self.vw.get_val_mut() { - Value::Array(ref mut vec) if is_leaves => { + let val = match self.vw.get_val().get_data_ref() { + RefValue::Array(ref vec) if is_leaves => { let mut buf = Vec::new(); - for mut item in vec { - if let Value::Array(v) = item { - let mut ret: Vec = v.iter_mut() - .map(|v| Self::get_nested_object(v, key, filter_mode)) - .filter(|v| !v.is_null()) - .collect(); + for mut v in vec { + let wrapper: RefValueWrapper = v.into(); + if wrapper.is_array() { + let vec = wrapper.as_array().unwrap(); + let mut ret = Vec::new(); + for v in vec { + let nested_wrapper = Self::get_nested_object(&v.into(), key, filter_mode); + if !nested_wrapper.is_null() { + ret.push(nested_wrapper.clone_data()); + } + } buf.append(&mut ret); } else { - match item.get_mut(key) { - Some(v) => buf.push(v.take()), + match wrapper.get(key.clone()) { + Some(v) => buf.push(v.clone_data()), _ => {} } } } - Value::Array(buf) + RefValue::Array(buf).into() } - Value::Array(v) if !is_leaves => { - let vec: Vec = v.iter_mut() - .map(|v| Self::get_nested_object(v, key, filter_mode)) - .filter(|v| !v.is_null()) - .collect(); - - Value::Array(vec) + RefValue::Array(ref vec) if !is_leaves => { + let mut ret = Vec::new(); + for v in vec { + let wrapper = Self::get_nested_object(&v.into(), key, filter_mode); + if !wrapper.is_null() { + ret.push(wrapper.clone_data()); + } + } + RefValue::Array(ret).into() } - other => { - match other.get_mut(key) { - Some(v) => v.take(), - _ => Value::Null + _ => { + match self.vw.get_val().get(key.clone()) { + Some(v) => v.clone(), + _ => RefValue::Null.into() } } }; self.last_key = Some(ValueFilterKey::String(key.clone())); - self.vw.replace(v); - trace!("step_in_string - after: {},{},{:?}", self.vw.is_leaves(), self.filter_mode, self.vw.get_val()); + self.vw.replace(val); + trace!("step_in_string - after: {},{},{:?}" + , self.vw.is_leaves() + , self.filter_mode + , self.vw.get_val().get_data_ref()); &self.vw } } pub struct JsonValueFilter { - json: Rc>, + json: RefValueWrapper, filter_stack: Vec, token_stack: Vec, term_stack: Vec, @@ -257,12 +280,12 @@ impl JsonValueFilter { pub fn new(json: &str) -> result::Result { let json: Value = serde_json::from_str(json) .map_err(|e| e.description().to_string())?; - Ok(JsonValueFilter::new_from_value(Rc::new(Box::new(json)))) + Ok(JsonValueFilter::new_from_value(json.into())) } - pub fn new_from_value(json: Rc>) -> Self { + pub fn new_from_value(json: RefValueWrapper) -> Self { JsonValueFilter { - json: json, + json, filter_stack: Vec::new(), token_stack: Vec::new(), term_stack: Vec::new(), @@ -287,14 +310,13 @@ impl JsonValueFilter { Some(self.filter_stack.push(vf)) }); } else { - let v: &Value = self.json.as_ref().borrow(); self.filter_stack.push({ - ValueFilter::new(v.clone(), false, from_current) + ValueFilter::new(self.json.clone(), false, from_current) }); } } - fn replace_filter_stack(&mut self, v: Value, is_leaves: bool) { + fn replace_filter_stack(&mut self, v: RefValueWrapper, is_leaves: bool) { if self.filter_stack.is_empty() { self.filter_stack.push(ValueFilter::new(v, is_leaves, false)); } else { @@ -312,17 +334,17 @@ impl JsonValueFilter { } } - pub fn current_value(&self) -> &Value { + pub fn current_value(&self) -> RefValueWrapper { match self.filter_stack.last() { - Some(v) => &v.vw.get_val(), - _ => &Value::Null + Some(v) => v.vw.get_val().clone(), + _ => RefValue::Null.into() } } - pub fn take_value(&mut self) -> Value { + pub fn take_value(&mut self) -> RefValueWrapper { match self.filter_stack.last_mut() { - Some(v) => v.vw.get_val_mut().take(), - _ => Value::Null + Some(v) => v.vw.get_val().clone(), + _ => RefValue::Null.into() } } @@ -331,25 +353,28 @@ impl JsonValueFilter { match self.filter_stack.last_mut() { Some(ref mut vf) if vf.vw.is_array() && vf.vw.is_leaves() => { - if let Value::Array(mut val) = vf.vw.get_val_mut().take() { - let mut ret = Vec::new(); - for mut v in &mut val { + let mut ret = Vec::new(); + if let RefValue::Array(val) = vf.vw.get_val().get_data_ref() { + for mut v in val { for i in &indices { - let v = i.take_value(v); + let v = i.take_value(&v.into()); if !v.is_null() { - ret.push(v); + ret.push(v.clone_data()); } } } - vf.vw.replace(Value::Array(ret)); } + vf.vw.replace(RefValue::Array(ret).into()); } Some(ref mut vf) if vf.vw.is_array() && !vf.vw.is_leaves() => { - let ret = indices.into_iter() - .map(|i| i.take_value(vf.vw.get_val_mut())) - .filter(|v| !v.is_null()) - .collect(); - vf.vw.replace(Value::Array(ret)); + let mut ret = Vec::new(); + for i in indices { + let wrapper = i.take_value(&vf.vw.get_val()); + if !wrapper.is_null() { + ret.push(wrapper.clone_data()); + } + } + vf.vw.replace(RefValue::Array(ret).into()); } _ => {} } @@ -358,43 +383,51 @@ impl JsonValueFilter { fn token_range(&mut self, from: Option, to: Option) { self.token_stack.pop(); - fn _from_to(from: Option, to: Option, val: &Value) -> (usize, usize) { + fn _from_to(from: Option, to: Option, val: &RefValueWrapper) -> (usize, usize) { let from = match from { Some(v) => v.index(val), _ => 0 }; let to = match to { Some(v) => v.index(val), - _ => if let Value::Array(v) = val { v.len() } else { 0 } + _ => { + if let RefValue::Array(v) = val.get_data_ref() { + v.len() + } else { + 0 + } + } }; (from, to) } - fn _range(from: usize, to: usize, v: &mut Value) -> Vec { + fn _range(from: usize, to: usize, v: &RefValueWrapper) -> Vec { trace!("range - {}:{}", from, to); (from..to).into_iter() .map(|i| i.take_value(v)) .filter(|v| !v.is_null()) + .map(|v| v.clone_data()) .collect() } match self.filter_stack.last_mut() { Some(ref mut vf) if vf.vw.is_array() && vf.vw.is_leaves() => { - if let Value::Array(mut vec) = vf.vw.get_val_mut().take() { - let mut buf = Vec::new(); - for mut item in &mut vec { - let (from, to) = _from_to(from, to, item); - let mut v: Vec = _range(from, to, item); + let mut buf = Vec::new(); + if let RefValue::Array(vec) = vf.vw.get_val().get_data_ref() { + for mut v in vec { + let wrapper = v.into(); + let (from, to) = _from_to(from, to, &wrapper); + let mut v: Vec = _range(from, to, &wrapper); buf.append(&mut v); } - vf.vw.replace(Value::Array(buf)); } + vf.vw.replace(RefValue::Array(buf).into()); } Some(ref mut vf) if vf.vw.is_array() && !vf.vw.is_leaves() => { - let (from, to) = _from_to(from, to, vf.vw.get_val()); - let v: Vec = _range(from, to, vf.vw.get_val_mut()); - vf.vw.replace(Value::Array(v)); + let (from, to) = _from_to(from, to, &vf.vw.get_val()); + let vec: Vec = _range(from, to, vf.vw.get_val()); + vf.vw.replace(RefValue::Array(vec).into()); } _ => {} } @@ -449,19 +482,19 @@ impl JsonValueFilter { _ => {} } } - Some(TermContext::Json(_, mut vw)) => { - self.replace_filter_stack(vw.get_val_mut().take(), vw.is_leaves()); + Some(TermContext::Json(_, vw)) => { + self.replace_filter_stack(vw.get_val().clone(), vw.is_leaves()); } _ => { match self.filter_stack.pop() { Some(mut vf) => { let is_leaves = vf.vw.is_leaves(); - match vf.vw.get_val_mut() { - Value::Null | Value::Bool(false) => { - self.replace_filter_stack(Value::Null, is_leaves); + match vf.vw.get_val().get_data_ref() { + RefValue::Null | RefValue::Bool(false) => { + self.replace_filter_stack(RefValue::Null.into(), is_leaves); } - other => { - self.replace_filter_stack(other.take(), is_leaves); + _ => { + self.replace_filter_stack(vf.vw.get_val().clone(), is_leaves); } } } @@ -479,18 +512,18 @@ impl JsonValueFilter { trace!("right {:?}", right); if left.is_some() && right.is_some() { - let mut left = left.unwrap(); - let mut right = right.unwrap(); + let left = left.unwrap(); + let right = right.unwrap(); let tc = match ft { - FilterToken::Equal => left.eq(&mut right), - FilterToken::NotEqual => left.ne(&mut right), - FilterToken::Greater => left.gt(&mut right), - FilterToken::GreaterOrEqual => left.ge(&mut right), - FilterToken::Little => left.lt(&mut right), - FilterToken::LittleOrEqual => left.le(&mut right), - FilterToken::And => left.and(&mut right), - FilterToken::Or => left.or(&mut right), + FilterToken::Equal => left.eq(&right), + FilterToken::NotEqual => left.ne(&right), + FilterToken::Greater => left.gt(&right), + FilterToken::GreaterOrEqual => left.ge(&right), + FilterToken::Little => left.lt(&right), + FilterToken::LittleOrEqual => left.le(&right), + FilterToken::And => left.and(&right), + FilterToken::Or => left.or(&right), }; self.term_stack.push(tc); } diff --git a/src/filter/value_wrapper.rs b/src/filter/value_wrapper.rs index 82175ac..10fb08d 100644 --- a/src/filter/value_wrapper.rs +++ b/src/filter/value_wrapper.rs @@ -1,6 +1,5 @@ use indexmap::map::IndexMap; - -use serde_json::Value; +use ref_value::*; use super::cmp::*; use super::term::*; @@ -8,12 +7,12 @@ use super::value_filter::*; #[derive(Debug)] pub struct ValueWrapper { - val: Value, + val: RefValueWrapper, is_leaves: bool, } impl ValueWrapper { - pub fn new(val: Value, leaves: bool) -> Self { + pub fn new(val: RefValueWrapper, leaves: bool) -> Self { ValueWrapper { val, is_leaves: leaves } } @@ -25,7 +24,7 @@ impl ValueWrapper { self.is_leaves = is_leaves; } - pub fn cmp(&mut self, other: &mut ValueWrapper, cmp_type: CmpType) -> TermContext { + pub fn cmp(&self, other: &ValueWrapper, cmp_type: CmpType) -> TermContext { match cmp_type { CmpType::Eq => { TermContext::Json(None, self.intersect(other)) @@ -39,24 +38,19 @@ impl ValueWrapper { } } - fn cmp_with_term(val: &Value, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool { - match val { - Value::Bool(ref v1) => { + fn cmp_with_term(val: &RefValueWrapper, et: &ExprTerm, cmp_fn: &F, default: bool, reverse: bool) -> bool { + match val.get_data_ref() { + RefValue::Bool(ref v1) => { match et { ExprTerm::Bool(v2) => if reverse { cmp_fn.cmp_bool(v2, v1) } else { cmp_fn.cmp_bool(v1, v2) }, _ => default } } - Value::Number(ref v1) => match v1.as_f64() { - Some(ref v1) => { - match et { - ExprTerm::Number(v2) => if reverse { cmp_fn.cmp_f64(v2, v1) } else { cmp_fn.cmp_f64(v1, v2) }, - _ => default - } - } + RefValue::Number(ref v1) => match et { + ExprTerm::Number(v2) => if reverse { cmp_fn.cmp_f64(v2, &v1.as_f64().unwrap()) } else { cmp_fn.cmp_f64(&v1.as_f64().unwrap(), v2) }, _ => default }, - Value::String(ref v1) => { + RefValue::String(ref v1) => { match et { ExprTerm::String(v2) => if reverse { cmp_fn.cmp_string(v2, v1) } else { cmp_fn.cmp_string(v1, v2) }, _ => default @@ -66,12 +60,12 @@ impl ValueWrapper { } } - fn take_object_in_array(&mut self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option { - fn _filter_with_object bool>(v: &&mut Value, key: &String, fun: F) -> bool { - match &v { - Value::Object(map) => { + fn take_object_in_array(&self, key: &String, et: &ExprTerm, cmp: &F, reverse: bool) -> Option { + fn _filter_with_object bool>(v: &RefValueWrapper, key: &String, fun: F) -> bool { + match v.get_data_ref() { + RefValue::Object(map) => { match map.get(key) { - Some(vv) => fun(vv), + Some(val) => fun(&val.into()), _ => false } } @@ -79,21 +73,24 @@ impl ValueWrapper { } } - match self.val.take() { - Value::Array(mut vec) => { - let mut ret: Vec = vec.iter_mut() - .filter(|v| { - _filter_with_object(v, key, |vv| Self::cmp_with_term(vv, et, cmp, false, reverse)) - }) - .map(|v| v.take()) - .collect(); - Some(ValueWrapper::new(Value::Array(ret), false)) + match self.val.get_data_ref() { + RefValue::Array(vec) => { + let mut ret = Vec::new(); + for v in vec { + if _filter_with_object(&v.into(), key, |vv| { + Self::cmp_with_term(vv, et, cmp, false, reverse) + }) { + ret.push(v.clone()); + } + } + + Some(ValueWrapper::new(RefValue::Array(ret).into(), false)) } _ => None } } - fn take_with_key_type(&mut self, key: &Option, et: &ExprTerm, cmp: &F, reverse: bool) -> Option { + fn take_with_key_type(&self, key: &Option, et: &ExprTerm, cmp: &F, reverse: bool) -> Option { match key { Some(ValueFilterKey::String(key)) => { self.take_object_in_array(key, et, cmp, reverse) @@ -102,23 +99,25 @@ impl ValueWrapper { } } - pub fn take_with(&mut self, key: &Option, et: &ExprTerm, cmp: F, reverse: bool) -> Self { + pub fn take_with(&self, key: &Option, et: &ExprTerm, cmp: F, reverse: bool) -> Self { match self.take_with_key_type(key, et, &cmp, reverse) { Some(vw) => vw, _ => { - match self.val.take() { - Value::Array(mut vec) => { - let mut ret = vec.iter_mut() - .filter(|v| Self::cmp_with_term(&v, et, &cmp, false, reverse)) - .map(|v| v.take()) - .collect(); - ValueWrapper::new(Value::Array(ret), false) + match self.val.get_data_ref() { + RefValue::Array(vec) => { + let mut ret = Vec::new(); + for v in vec { + if Self::cmp_with_term(&v.into(), et, &cmp, false, reverse) { + ret.push(v.clone()); + } + } + ValueWrapper::new(RefValue::Array(ret).into(), false) } - other => { - if Self::cmp_with_term(&other, et, &cmp, false, reverse) { - ValueWrapper::new(other, false) + _ => { + if Self::cmp_with_term(&self.val, et, &cmp, false, reverse) { + ValueWrapper::new(self.val.clone(), false) } else { - ValueWrapper::new(Value::Null, false) + ValueWrapper::new(RefValue::Null.into(), false) } } } @@ -126,24 +125,25 @@ impl ValueWrapper { } } - pub fn replace(&mut self, val: Value) { - let is_null = match &val { - Value::Array(v) => if v.is_empty() { true } else { false }, - Value::Object(m) => if m.is_empty() { true } else { false }, + pub fn replace(&mut self, val: RefValueWrapper) { + let is_null = match val.get_data_ref() { + RefValue::Array(v) => if v.is_empty() { true } else { false }, + RefValue::Object(m) => if m.is_empty() { true } else { false }, _ => val.is_null() }; - self.val = if is_null { Value::Null } else { val }; + self.val = if is_null { + let v = RefValueWrapper::wrap(RefValue::Null); + RefValueWrapper::new(v) + } else { + val + }; } - pub fn get_val(&self) -> &Value { + pub fn get_val(&self) -> &RefValueWrapper { &self.val } - pub fn get_val_mut(&mut self) -> &mut Value { - &mut self.val - } - - pub fn clone_val(&self) -> Value { + pub fn clone_val(&self) -> RefValueWrapper { self.val.clone() } @@ -151,150 +151,161 @@ impl ValueWrapper { self.val.is_array() } - fn uuid(v: &Value) -> String { - fn _fn(v: &Value) -> String { - match v { - Value::Null => "null".to_string(), - Value::String(v) => v.to_string(), - Value::Bool(v) => v.to_string(), - Value::Number(v) => v.to_string(), - Value::Array(v) => { - v.iter().enumerate() - .map(|(i, v)| { format!("{}{}", i, _fn(v)) }) - .collect() + fn uuid(v: &RefValueWrapper) -> String { + fn _fn(v: &RefValueWrapper, acc: &mut String) { + match v.get_data_ref() { + RefValue::Null => acc.push_str("null"), + RefValue::String(v) => acc.push_str(v), + RefValue::Bool(v) => acc.push_str(if *v { "true" } else { "false" }), + RefValue::Number(v) => acc.push_str(&*v.to_string()), + RefValue::Array(v) => { + for (i, v) in v.iter().enumerate() { + acc.push_str(&*i.to_string()); + _fn(&v.into(), acc); + } } - Value::Object(v) => { - v.into_iter().map(|(k, v)| { format!("{}{}", k, _fn(v)) }).collect() + RefValue::Object(ref v) => { + for (k, v) in v.into_iter() { + acc.push_str(&*k.to_string()); + _fn(&v.into(), acc); + } } } } - _fn(v) + let mut acc = String::new(); + _fn(v, &mut acc); + acc } - fn into_map(&mut self) -> IndexMap { + fn into_map(&self) -> IndexMap { let mut map = IndexMap::new(); - match &mut self.val { - Value::Array(v1) => { + match self.val.get_data_ref() { + RefValue::Array(ref v1) => { for v in v1 { - map.insert(Self::uuid(v), v.take()); + let wrapper = v.into(); + let key = Self::uuid(&wrapper); + map.insert(key, wrapper); } } - other => { - map.insert(Self::uuid(other), other.take()); + _ => { + map.insert(Self::uuid(&self.val), self.val.clone()); } } map } - pub fn except(&mut self, other: &mut Self) -> Self { + pub fn except(&self, other: &Self) -> Self { let map = self.into_map(); - let mut ret: IndexMap = IndexMap::new(); - match &mut other.val { - Value::Array(v1) => { + let mut ret: IndexMap = IndexMap::new(); + match other.val.get_data_ref() { + RefValue::Array(ref v1) => { for v in v1 { - let key = Self::uuid(v); + let wrapper = v.into(); + let key = Self::uuid(&wrapper); if !map.contains_key(&key) { - ret.insert(key, v.take()); + ret.insert(key, wrapper); } } } - other => { - let key = Self::uuid(other); + _ => { + let key = Self::uuid(&other.val); if !map.contains_key(&key) { - ret.insert(key, other.take()); + ret.insert(key, other.val.clone()); } } } - let v = ret.values_mut().into_iter().map(|v| v.take()).collect(); - ValueWrapper::new(v, false) + let vec = ret.values().into_iter().map(|v| v.clone_data()).collect(); + ValueWrapper::new(RefValue::Array(vec).into(), false) } - pub fn intersect(&mut self, other: &mut Self) -> Self { + pub fn intersect(&self, other: &Self) -> Self { let map = self.into_map(); - let mut ret: IndexMap = IndexMap::new(); - match &mut other.val { - Value::Array(v1) => { + let mut ret: IndexMap = IndexMap::new(); + match other.val.get_data_ref() { + RefValue::Array(ref v1) => { for v in v1 { - let key = Self::uuid(v); + let wrapper = v.into(); + let key = Self::uuid(&wrapper); if map.contains_key(&key) { - ret.insert(key, v.take()); + ret.insert(key, wrapper); } } } - other => { - let key = Self::uuid(other); + _ => { + let key = Self::uuid(&other.val); if map.contains_key(&key) { - ret.insert(key, other.take()); + ret.insert(key, other.val.clone()); } } } - let v = ret.values_mut().into_iter().map(|v| v.take()).collect(); - ValueWrapper::new(v, false) + let vec = ret.values().into_iter().map(|v| v.clone_data()).collect(); + ValueWrapper::new(RefValue::Array(vec).into(), false) } - pub fn union(&mut self, other: &mut Self) -> Self { + pub fn union(&self, other: &Self) -> Self { let mut map = self.into_map(); - match &mut other.val { - Value::Array(v1) => { + match other.val.get_data_ref() { + RefValue::Array(ref v1) => { for v in v1 { - let key = Self::uuid(v); + let wrapper = v.into(); + let key = Self::uuid(&wrapper); if !map.contains_key(&key) { - map.insert(key, v.take()); + map.insert(key, wrapper); } } } - other => { - let key = Self::uuid(other); + _ => { + let key = Self::uuid(&other.val); if !map.contains_key(&key) { - map.insert(key, other.take()); + map.insert(key, other.val.clone()); } } } - let mut vw = ValueWrapper::new(Value::Null, false); - let list: Vec = map.values_mut().into_iter().map(|val| val.take()).collect(); - vw.replace(Value::Array(list)); + let mut vw = ValueWrapper::new(RefValue::Null.into(), false); + let list = map.values().into_iter().map(|val| val.clone_data()).collect(); + vw.replace(RefValue::Array(list).into()); vw } - pub fn into_term(&mut self, key: &mut Option) -> TermContext { - match self.val.take() { - Value::String(s) => TermContext::Constants(ExprTerm::String(s)), - Value::Number(n) => TermContext::Constants(ExprTerm::Number(n.as_f64().unwrap())), - Value::Bool(b) => TermContext::Constants(ExprTerm::Bool(b)), - other => TermContext::Json(match key { + pub fn into_term(&self, key: &Option) -> TermContext { + match self.val.get_data_ref() { + RefValue::String(ref s) => TermContext::Constants(ExprTerm::String(s.clone())), + RefValue::Number(ref n) => TermContext::Constants(ExprTerm::Number(n.as_f64().unwrap())), + RefValue::Bool(b) => TermContext::Constants(ExprTerm::Bool(*b)), + _ => TermContext::Json(match key { Some(vk) => Some(vk.clone()), _ => None - }, ValueWrapper::new(other, false)) + }, ValueWrapper::new(self.val.clone(), false)) } } - pub fn filter(&mut self, key: &mut Option) -> Self { - let v = match &mut self.val { - Value::Array(vec) => { - let ret = vec.iter_mut() - .filter(|v| match key { - Some(ValueFilterKey::String(val_key)) => { - v.get(val_key.as_str()).is_some() + pub fn filter(&self, key: &Option) -> Self { + let v = match self.val.get_data_ref() { + RefValue::Array(ref vec) => { + let mut ret = Vec::new(); + for v in vec { + if let Some(ValueFilterKey::String(k)) = key { + let wrapper: RefValueWrapper = v.into(); + if wrapper.get(k.clone()).is_some() { + ret.push(v.clone()); } - _ => false - }) - .map(|v| v.take()) - .collect(); - Value::Array(ret) + } + } + RefValue::Array(ret).into() } - Value::Object(map) => { + RefValue::Object(ref map) => { match key { - Some(ValueFilterKey::String(val_key)) => match map.get_mut(val_key) { - Some(v) => v.take(), - _ => Value::Null + Some(ValueFilterKey::String(k)) => match map.get(k) { + Some(v) => v.into(), + _ => RefValue::Null.into() }, - _ => Value::Null + _ => RefValue::Null.into() } } - other => other.take() + _ => self.val.clone() }; ValueWrapper::new(v, false) diff --git a/src/lib.rs b/src/lib.rs index 9232cb2..5b33663 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,26 +43,26 @@ //! "expensive": 10 //! }); //! -//! let mut reader = jsonpath::reader(json_obj); +//! let mut selector = jsonpath::selector(json_obj); //! //! // //! // $.store.book[*].author //! // -//! let json = reader("$.store.book[*].author").unwrap(); +//! let json = selector("$.store.book[*].author").unwrap(); //! let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]); //! assert_eq!(json, ret); //! //! // //! // $..author //! // -//! let json = reader("$..author").unwrap(); +//! let json = selector("$..author").unwrap(); //! let ret = json!(["Nigel Rees","Evelyn Waugh","Herman Melville","J. R. R. Tolkien"]); //! assert_eq!(json, ret); //! //! // //! // $.store.* //! // -//! let json = reader("$.store.*").unwrap(); +//! let json = selector("$.store.*").unwrap(); //! let ret = json!([ //! [ //! {"category" : "reference", "author" : "Nigel Rees","title" : "Sayings of the Century", "price" : 8.95}, @@ -77,14 +77,14 @@ //! // //! // $.store..price //! // -//! let json = reader("$.store..price").unwrap(); +//! let json = selector("$.store..price").unwrap(); //! let ret = json!([8.95, 12.99, 8.99, 22.99, 19.95]); //! assert_eq!(ret, json); //! //! // //! // $..book[2] //! // -//! let json = reader("$..book[2]").unwrap(); +//! let json = selector("$..book[2]").unwrap(); //! let ret = json!([{ //! "category" : "fiction", //! "author" : "Herman Melville", @@ -97,7 +97,7 @@ //! // //! // $..book[-2] //! // -//! let json = reader("$..book[-2]").unwrap(); +//! let json = selector("$..book[-2]").unwrap(); //! let ret = json!([{ //! "category" : "fiction", //! "author" : "Herman Melville", @@ -110,7 +110,7 @@ //! // //! // $..book[0,1] //! // -//! let json = reader("$..book[0,1]").unwrap(); +//! let json = selector("$..book[0,1]").unwrap(); //! let ret = json!([ //! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}, //! {"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99} @@ -120,7 +120,7 @@ //! // //! // $..book[:2] //! // -//! let json = reader("$..book[:2]").unwrap(); +//! let json = selector("$..book[:2]").unwrap(); //! let ret = json!([ //! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}, //! {"category" : "fiction","author" : "Evelyn Waugh","title" : "Sword of Honour","price" : 12.99} @@ -130,7 +130,7 @@ //! // //! // $..book[2:] //! // -//! let json = reader("$..book[2:]").unwrap(); +//! let json = selector("$..book[2:]").unwrap(); //! let ret = json!([ //! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, //! {"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} @@ -140,7 +140,7 @@ //! // //! // $..book[?(@.isbn)] //! // -//! let json = reader("$..book[?(@.isbn)]").unwrap(); +//! let json = selector("$..book[?(@.isbn)]").unwrap(); //! let ret = json!([ //! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99}, //! {"category" : "fiction","author" : "J. R. R. Tolkien","title" : "The Lord of the Rings","isbn" : "0-395-19395-8","price" : 22.99} @@ -150,7 +150,7 @@ //! // //! // $.store.book[?(@.price < 10)] //! // -//! let json = reader("$.store.book[?(@.price < 10)]").unwrap(); +//! let json = selector("$.store.book[?(@.price < 10)]").unwrap(); //! let ret = json!([ //! {"category" : "reference","author" : "Nigel Rees","title" : "Sayings of the Century","price" : 8.95}, //! {"category" : "fiction","author" : "Herman Melville","title" : "Moby Dick","isbn" : "0-553-21311-3","price" : 8.99} @@ -175,14 +175,17 @@ extern crate indexmap; pub mod parser; #[doc(hidden)] pub mod filter; +#[doc(hidden)] +pub mod ref_value; use parser::parser::*; use filter::value_filter::*; use std::result; -use std::rc::Rc; use serde_json::Value; +use ref_value::*; + type Result = result::Result; /// # Read multiple Json multiple times with the same JsonPath @@ -223,9 +226,9 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(Value) -> Result + 'a { move |json| { match &node { Ok(n) => { - let mut jf = JsonValueFilter::new_from_value(Rc::new(Box::new(json))); + let mut jf = JsonValueFilter::new_from_value(json.into()); jf.visit(n.clone()); - Ok(jf.take_value()) + Ok(jf.take_value().into_value()) } Err(e) => Err(e.clone()) } @@ -246,26 +249,31 @@ pub fn compile<'a>(path: &'a str) -> impl FnMut(Value) -> Result + 'a { /// "friends": [{"id": 0},{"id": 1}] /// }); /// -/// let mut reader = jsonpath::reader(json_obj); +/// let mut selector = jsonpath::selector(json_obj); /// -/// let json = reader("$..friends[0]").unwrap(); +/// let json = selector("$..friends[0]").unwrap(); /// let ret = json!([ {"id": 0}, {"id": 0} ]); /// assert_eq!(json, ret); /// -/// let json = reader("$..friends[1]").unwrap(); +/// let json = selector("$..friends[1]").unwrap(); /// let ret = json!([ {"id": 1}, {"id": 1} ]); /// assert_eq!(json, ret); /// ``` -pub fn reader(json: Value) -> impl FnMut(&str) -> Result { - let n = Rc::new(Box::new(json)); +pub fn selector(json: Value) -> impl FnMut(&str) -> Result { + let wrapper: RefValueWrapper = json.into(); move |path: &str| { - let mut jf = JsonValueFilter::new_from_value(n.clone()); + let mut jf = JsonValueFilter::new_from_value(wrapper.clone()); let mut parser = Parser::new(path); parser.parse(&mut jf)?; - Ok(jf.take_value()) + Ok(jf.take_value().into_value()) } } +/// # Read the same Json multiple times using different JsonPath - Deprecated. use selector +pub fn reader(json: Value) -> impl FnMut(&str) -> Result { + selector(json) +} + /// # Read Json using JsonPath /// /// ```rust @@ -278,15 +286,20 @@ pub fn reader(json: Value) -> impl FnMut(&str) -> Result { /// }, /// "friends": [{"id": 0}, {"id": 1}] /// }); -/// let json = jsonpath::read(json_obj, "$..friends[0]").unwrap(); +/// let json = jsonpath::select(json_obj, "$..friends[0]").unwrap(); /// let ret = json!([ {"id": 0}, {"id": 0} ]); /// assert_eq!(json, ret); /// ``` -pub fn read(json: Value, path: &str) -> Result { - let mut jf = JsonValueFilter::new_from_value(Rc::new(Box::new(json))); +pub fn select(json: Value, path: &str) -> Result { + let mut jf = JsonValueFilter::new_from_value(json.into()); let mut parser = Parser::new(path); parser.parse(&mut jf)?; - Ok(jf.take_value()) + Ok(jf.take_value().into_value()) +} + +/// # Read Json using JsonPath - Deprecated. use select +pub fn read(json: Value, path: &str) -> Result { + select(json, path) } #[cfg(test)] @@ -323,9 +336,9 @@ mod tests { } #[test] - fn reader() { + fn selector() { let json_obj = read_json("./benches/data_obj.json"); - let mut reader = super::reader(json_obj); + let mut reader = super::selector(json_obj); let json = reader("$..friends[2]").unwrap(); let ret = json!([ {"id": 2,"name": "Gray Berry"}, @@ -342,9 +355,9 @@ mod tests { } #[test] - fn read() { + fn select() { let json_obj = read_json("./benches/example.json"); - let json = super::read(json_obj, "$..book[2]").unwrap(); + let json = super::select(json_obj, "$..book[2]").unwrap(); let ret = json!([{ "category" : "fiction", "author" : "Herman Melville", diff --git a/src/parser/parser.rs b/src/parser/parser.rs index c76c2d1..4639149 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -13,25 +13,21 @@ type Result = result::Result; mod utils { use std::result; - pub fn vec_to_int(vec: &Vec, msg_handler: F) -> result::Result + pub fn string_to_isize(string: &String, msg_handler: F) -> result::Result where F: Fn() -> String { - match vec.iter().map(|c| *c).collect::().as_str().parse::() { + match string.as_str().parse::() { Ok(n) => Ok(n), _ => Err(msg_handler()) } } - pub fn vec_to_float(vec: &Vec, msg_handler: F) -> result::Result + pub fn string_to_f64(string: &String, msg_handler: F) -> result::Result where F: Fn() -> String { - match vec.iter().map(|c| *c).collect::().as_str().parse::() { + match string.as_str().parse::() { Ok(n) => Ok(n), _ => Err(msg_handler()) } } - - pub fn vec_to_string(vec: &Vec) -> String { - vec.iter().map(|c| *c).collect::() - } } #[derive(Debug, PartialEq, Clone)] @@ -236,7 +232,7 @@ impl<'a> Parser<'a> { debug!("#key"); match self.tokenizer.next_token() { Ok(Token::Key(_, v)) => { - Ok(self.node(ParseToken::Key(utils::vec_to_string(&v)))) + Ok(self.node(ParseToken::Key(v))) } _ => { Err(self.tokenizer.err_msg()) @@ -247,9 +243,9 @@ impl<'a> Parser<'a> { fn array_quota_value(&mut self) -> Result { debug!("#array_quota_value"); match self.tokenizer.next_token() { - Ok(Token::SingleQuoted(_, ref vec)) - | Ok(Token::DoubleQuoted(_, ref vec)) => { - Ok(self.node(ParseToken::Key(utils::vec_to_string(vec)))) + Ok(Token::SingleQuoted(_, val)) + | Ok(Token::DoubleQuoted(_, val)) => { + Ok(self.node(ParseToken::Key(val))) } Err(TokenError::Eof) => { Ok(self.node(ParseToken::Eof)) @@ -299,9 +295,8 @@ impl<'a> Parser<'a> { fn array_value_key(&mut self) -> Result { debug!("#array_value_key"); match self.tokenizer.next_token() { - Ok(Token::Key(pos, ref vec)) => { - let digit = utils::vec_to_int(vec, - || self.tokenizer.err_msg_with_pos(pos))?; + Ok(Token::Key(pos, ref val)) => { + let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?; self.eat_whitespace(); match self.tokenizer.peek_token() { @@ -357,9 +352,8 @@ impl<'a> Parser<'a> { self.eat_token(); self.eat_whitespace(); match self.tokenizer.next_token() { - Ok(Token::Key(pos, ref vec)) => { - let digit = utils::vec_to_int(vec, - || self.tokenizer.err_msg_with_pos(pos))?; + Ok(Token::Key(pos, ref val)) => { + let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?; values.push(digit); } _ => { @@ -387,9 +381,8 @@ impl<'a> Parser<'a> { fn range_to(&mut self) -> Result { debug!("#range_to"); match self.tokenizer.next_token() { - Ok(Token::Key(pos, ref vec)) => { - let digit = utils::vec_to_int(vec, - || self.tokenizer.err_msg_with_pos(pos))?; + Ok(Token::Key(pos, ref val)) => { + let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?; Ok(self.node(ParseToken::Range(None, Some(digit)))) } _ => { @@ -401,9 +394,8 @@ impl<'a> Parser<'a> { fn range(&mut self, num: isize) -> Result { debug!("#range"); match self.tokenizer.next_token() { - Ok(Token::Key(pos, ref vec)) => { - let digit = utils::vec_to_int(vec, - || self.tokenizer.err_msg_with_pos(pos))?; + Ok(Token::Key(pos, ref val)) => { + let digit = utils::string_to_isize(val, || self.tokenizer.err_msg_with_pos(pos))?; Ok(self.node(ParseToken::Range(Some(num), Some(digit)))) } _ => { @@ -505,14 +497,13 @@ impl<'a> Parser<'a> { fn term_num(&mut self) -> Result { debug!("#term_num"); match self.tokenizer.next_token() { - Ok(Token::Key(pos, mut vec)) => { + Ok(Token::Key(pos, val)) => { match self.tokenizer.peek_token() { Ok(Token::Dot(_)) => { - self.term_num_float(&mut vec) + self.term_num_float(val.as_str()) } _ => { - let number = utils::vec_to_float(&vec, - || self.tokenizer.err_msg_with_pos(pos))?; + let number = utils::string_to_f64(&val, || self.tokenizer.err_msg_with_pos(pos))?; Ok(self.node(ParseToken::Number(number))) } } @@ -526,17 +517,16 @@ impl<'a> Parser<'a> { } } - fn term_num_float(&mut self, mut num: &mut Vec) -> Result { + fn term_num_float(&mut self, mut num: &str) -> Result { debug!("#term_num_float"); self.eat_token(); match self.tokenizer.next_token() { - Ok(Token::Key(pos, mut frac)) => { - let mut f = vec![]; - f.append(&mut num); + Ok(Token::Key(pos, frac)) => { + let mut f = String::new(); + f.push_str(&mut num); f.push('.'); - f.append(&mut frac); - let number = utils::vec_to_float(&f, - || self.tokenizer.err_msg_with_pos(pos))?; + f.push_str(frac.as_str()); + let number = utils::string_to_f64(&f, || self.tokenizer.err_msg_with_pos(pos))?; Ok(self.node(ParseToken::Number(number))) } _ => { diff --git a/src/parser/path_reader.rs b/src/parser/path_reader.rs index a8212a4..b3e4da9 100644 --- a/src/parser/path_reader.rs +++ b/src/parser/path_reader.rs @@ -23,19 +23,23 @@ impl<'a> PathReader<'a> { Ok((self.pos + ch.len_utf8(), ch)) } - pub fn take_while(&mut self, fun: F) -> result::Result<(usize, Vec), ReaderError> + pub fn take_while(&mut self, fun: F) -> result::Result<(usize, String), ReaderError> where F: Fn(&char) -> bool { - let vec: Vec = self.input.chars() - .by_ref() - .take_while(fun) - .collect(); + let mut char_len: usize = 0; + let mut ret = String::new(); + for c in self.input.chars().by_ref() { + if !fun(&c) { + break; + } + char_len += c.len_utf8(); + ret.push(c); + } - let char_len: usize = vec.iter().by_ref().map(|c| c.len_utf8()).sum(); self.pos += char_len; self.input = &self.input[char_len..]; - Ok((self.pos, vec)) + Ok((self.pos, ret)) } pub fn next_char(&mut self) -> result::Result<(usize, char), ReaderError> { diff --git a/src/parser/tokenizer.rs b/src/parser/tokenizer.rs index 93d70e5..d08b0a2 100644 --- a/src/parser/tokenizer.rs +++ b/src/parser/tokenizer.rs @@ -75,9 +75,9 @@ pub enum Token { Split(usize), OpenParenthesis(usize), CloseParenthesis(usize), - Key(usize, Vec), - DoubleQuoted(usize, Vec), - SingleQuoted(usize, Vec), + Key(usize, String), + DoubleQuoted(usize, String), + SingleQuoted(usize, String), Equal(usize), GreaterOrEqual(usize), Greater(usize), @@ -153,15 +153,15 @@ impl<'a> Tokenizer<'a> { } fn single_quota(&mut self, pos: usize, ch: char) -> result::Result { - let (_, vec) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?; + let (_, val) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?; self.input.next_char().map_err(to_token_error)?; - Ok(Token::SingleQuoted(pos, vec)) + Ok(Token::SingleQuoted(pos, val)) } fn double_quota(&mut self, pos: usize, ch: char) -> result::Result { - let (_, vec) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?; + let (_, val) = self.input.take_while(|c| *c != ch).map_err(to_token_error)?; self.input.next_char().map_err(to_token_error)?; - Ok(Token::DoubleQuoted(pos, vec)) + Ok(Token::DoubleQuoted(pos, val)) } fn equal(&mut self, pos: usize, _: char) -> result::Result { @@ -414,9 +414,9 @@ mod tests { vec![ Token::Absolute(0), Token::Dot(1), - Token::Key(2, vec!['0', '1']), + Token::Key(2, "01".to_string()), Token::Dot(4), - Token::Key(5, vec!['a']) + Token::Key(5, "a".to_string()) ] , Some(TokenError::Eof) )); @@ -449,7 +449,7 @@ mod tests { Token::Absolute(0), Token::Dot(1), Token::Dot(2), - Token::Key(3, vec!['a', 'b']) + Token::Key(3, "ab".to_string()) ] , Some(TokenError::Eof) )); @@ -460,7 +460,7 @@ mod tests { Token::Absolute(0), Token::Dot(1), Token::Dot(2), - Token::Key(3, vec!['가']), + Token::Key(3, "가".to_string()), Token::Whitespace(6, 0), Token::OpenArray(7), ] @@ -471,10 +471,10 @@ mod tests { ( vec![ Token::OpenArray(0), - Token::Key(1, vec!['-', '1']), + Token::Key(1, "-1".to_string()), Token::Comma(3), Token::Whitespace(4, 0), - Token::Key(5, vec!['2']), + Token::Key(5, "2".to_string()), Token::Whitespace(6, 0), Token::CloseArray(7), ] @@ -486,19 +486,19 @@ mod tests { vec![ Token::OpenArray(0), Token::Whitespace(1, 0), - Token::Key(2, vec!['1']), + Token::Key(2, "1".to_string()), Token::Whitespace(3, 0), - Token::Key(4, vec!['2']), + Token::Key(4, "2".to_string()), Token::Whitespace(5, 0), Token::Comma(6), Token::Whitespace(7, 0), - Token::Key(8, vec!['3']), + Token::Key(8, "3".to_string()), Token::Whitespace(9, 0), - Token::DoubleQuoted(10, vec!['a', 'b', 'c']), + Token::DoubleQuoted(10, "abc".to_string()), Token::Whitespace(15, 0), Token::Split(16), Token::Whitespace(17, 0), - Token::Key(18, vec!['-', '1', '0']), + Token::Key(18, "-10".to_string()), Token::Whitespace(21, 0), Token::CloseArray(22), ] @@ -512,12 +512,12 @@ mod tests { Token::OpenParenthesis(1), Token::At(2), Token::Dot(3), - Token::Key(4, vec!['a', '가']), + Token::Key(4, "a가".to_string()), Token::Whitespace(8, 0), Token::Little(9), - Token::Key(10, vec!['4', '1']), + Token::Key(10, "41".to_string()), Token::Dot(12), - Token::Key(13, vec!['0', '1']), + Token::Key(13, "01".to_string()), Token::CloseParenthesis(15), ] , Some(TokenError::Eof) @@ -530,12 +530,12 @@ mod tests { Token::OpenParenthesis(1), Token::At(2), Token::Dot(3), - Token::Key(4, vec!['a']), + Token::Key(4, "a".to_string()), Token::Whitespace(5, 0), Token::Little(6), - Token::Key(7, vec!['4', 'a']), + Token::Key(7, "4a".to_string()), Token::Dot(9), - Token::Key(10, vec!['0', '1']), + Token::Key(10, "01".to_string()), Token::CloseParenthesis(12), ] , Some(TokenError::Eof) @@ -547,11 +547,11 @@ mod tests { Token::OpenParenthesis(1), Token::Absolute(2), Token::Dot(3), - Token::Key(4, vec!['c']), + Token::Key(4, "c".to_string()), Token::Greater(5), Token::At(6), Token::Dot(7), - Token::Key(8, vec!['d']), + Token::Key(8, "d".to_string()), Token::CloseParenthesis(9) ] , Some(TokenError::Eof) diff --git a/src/ref_value/mod.rs b/src/ref_value/mod.rs new file mode 100644 index 0000000..761e10a --- /dev/null +++ b/src/ref_value/mod.rs @@ -0,0 +1,384 @@ +extern crate indexmap; +extern crate serde_json; + +use std::sync::Arc; +use std::convert::Into; + +use indexmap::map::IndexMap; +use serde_json::Number; +use serde_json::Value; + +pub type TypeRefValue = Arc>; + +impl Into for TypeRefValue { + fn into(self) -> RefValueWrapper { + RefValueWrapper::new(self.clone()) + } +} + +impl Into for &TypeRefValue { + fn into(self) -> RefValueWrapper { + RefValueWrapper::new(self.clone()) + } +} + +/// +/// serde_json::Value 참고 +/// + +pub trait RefIndex { + fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue>; + fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue>; + fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue; +} + +impl RefIndex for usize { + fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue> { + match *v { + RefValue::Array(ref vec) => vec.get(*self), + _ => None, + } + } + fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue> { + match *v { + RefValue::Array(ref mut vec) => vec.get_mut(*self), + _ => None, + } + } + fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue { + match *v { + RefValue::Array(ref mut vec) => { + let len = vec.len(); + vec.get_mut(*self).unwrap_or_else(|| { + panic!( + "cannot access index {} of JSON array of length {}", + self, len + ) + }) + } + _ => panic!("cannot access index {} of JSON {:?}", self, v), + } + } +} + +impl RefIndex for str { + fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue> { + match *v { + RefValue::Object(ref map) => map.get(self), + _ => None, + } + } + fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue> { + match *v { + RefValue::Object(ref mut map) => map.get_mut(self), + _ => None, + } + } + fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue { + if let RefValue::Null = *v { + *v = RefValue::Object(IndexMap::new()); + } + match *v { + RefValue::Object(ref mut map) => { + map.entry(self.to_owned()).or_insert(RefValueWrapper::wrap(RefValue::Null)) + }, + _ => panic!("cannot access key {:?} in JSON {:?}", self, v), + } + } +} + +impl RefIndex for String { + fn index_into<'v>(&self, v: &'v RefValue) -> Option<&'v TypeRefValue> { + self[..].index_into(v) + } + fn index_into_mut<'v>(&self, v: &'v mut RefValue) -> Option<&'v mut TypeRefValue> { + self[..].index_into_mut(v) + } + fn index_or_insert<'v>(&self, v: &'v mut RefValue) -> &'v mut TypeRefValue { + self[..].index_or_insert(v) + } +} + +#[derive(Debug)] +pub struct RefValueWrapper { + data: TypeRefValue +} + +impl RefValueWrapper { + pub fn new(ref_value: TypeRefValue) -> Self { + RefValueWrapper { data: ref_value } + } + + pub fn wrap(ref_val: RefValue) -> TypeRefValue { + Arc::new(Box::new(ref_val)) + } + + pub fn into_value(&self) -> Value { + ValueConverter::new(&self.data) + } + + pub fn clone(&self) -> Self { + RefValueWrapper { data: self.data.clone() } + } + + pub fn clone_data(&self) -> TypeRefValue { + self.data.clone() + } + + pub fn get(&self, index: I) -> Option { + index.index_into(&**self.data).map(|v| Self::new(v.clone())) + } + + pub fn is_object(&self) -> bool { + (**self.data).is_object() + } + + pub fn as_object(&self) -> Option<&IndexMap> { + (**self.data).as_object() + } + + pub fn is_array(&self) -> bool { + (**self.data).is_array() + } + + pub fn as_array(&self) -> Option<&Vec> { + (**self.data).as_array() + } + + pub fn is_string(&self) -> bool { + (**self.data).is_string() + } + + pub fn as_str(&self) -> Option<&str> { + (**self.data).as_str() + } + + pub fn is_number(&self) -> bool { + (**self.data).is_number() + } + + pub fn as_number(&self) -> Option { + (**self.data).as_number() + } + + pub fn is_boolean(&self) -> bool { + (**self.data).is_boolean() + } + + pub fn as_bool(&self) -> Option { + (**self.data).as_bool() + } + + pub fn is_null(&self) -> bool { + (**self.data).is_null() + } + + pub fn as_null(&self) -> Option<()> { + (**self.data).as_null() + } + + pub fn get_data_ref(&self) -> &RefValue { + &(**self.data) + } +} + +impl Into for Value { + fn into(self) -> RefValueWrapper { + let ref_val = RefValueConverter::new(self); + RefValueWrapper::new(ref_val) + } +} + +#[derive(Debug)] +pub enum RefValue { + Null, + Bool(bool), + Number(Number), + String(String), + Array(Vec), + Object(IndexMap), +} + +impl RefValue { + pub fn get(&self, index: I) -> Option<&TypeRefValue> { + index.index_into(self) + } + + pub fn is_object(&self) -> bool { + self.as_object().is_some() + } + + pub fn as_object(&self) -> Option<&IndexMap> { + match *self { + RefValue::Object(ref map) => Some(map), + _ => None, + } + } + + pub fn is_array(&self) -> bool { + self.as_array().is_some() + } + + pub fn as_array(&self) -> Option<&Vec> { + match *self { + RefValue::Array(ref array) => Some(&*array), + _ => None, + } + } + + pub fn is_string(&self) -> bool { + self.as_str().is_some() + } + + pub fn as_str(&self) -> Option<&str> { + match *self { + RefValue::String(ref s) => Some(s), + _ => None, + } + } + + pub fn is_number(&self) -> bool { + match *self { + RefValue::Number(_) => true, + _ => false, + } + } + + pub fn as_number(&self) -> Option { + match *self { + RefValue::Number(ref n) => Some(n.clone()), + _ => None, + } + } + + pub fn is_boolean(&self) -> bool { + self.as_bool().is_some() + } + + pub fn as_bool(&self) -> Option { + match *self { + RefValue::Bool(b) => Some(b), + _ => None, + } + } + + pub fn is_null(&self) -> bool { + self.as_null().is_some() + } + + pub fn as_null(&self) -> Option<()> { + match *self { + RefValue::Null => Some(()), + _ => None, + } + } +} + +impl Into for RefValue { + + fn into(self) -> RefValueWrapper { + let wrap = RefValueWrapper::wrap(self); + RefValueWrapper::new(wrap) + } +} + +struct RefValueConverter; + +impl RefValueConverter { + fn new(value: Value) -> TypeRefValue { + RefValueConverter {}.visit_value(value) + } + + fn visit_value(&self, value: Value) -> TypeRefValue { + match value { + Value::Null => self.visit_null(), + Value::Bool(v) => self.visit_bool(v), + Value::Number(v) => self.visit_number(v), + Value::String(v) => self.visit_string(v), + Value::Array(v) => self.visit_array(v), + Value::Object(v) => self.visit_object(v), + } + } + fn visit_null(&self) -> TypeRefValue { + RefValueWrapper::wrap(RefValue::Null) + } + fn visit_bool(&self, value: bool) -> TypeRefValue { + RefValueWrapper::wrap(RefValue::Bool(value)) + } + fn visit_number(&self, value: serde_json::Number) -> TypeRefValue { + RefValueWrapper::wrap(RefValue::Number(value)) + } + fn visit_string(&self, value: String) -> TypeRefValue { + RefValueWrapper::wrap(RefValue::String(value.to_string())) + } + fn visit_array(&self, value: Vec) -> TypeRefValue { + let mut values = Vec::new(); + for v in value { + values.push(self.visit_value(v)); + } + RefValueWrapper::wrap(RefValue::Array(values)) + } + fn visit_object(&self, mut value: serde_json::Map) -> TypeRefValue { + let mut map = IndexMap::new(); + let keys: Vec = value.keys().into_iter().map(|k| k.to_string()).collect(); + for k in keys { + let value = self.visit_value(match value.get_mut(&k) { + Some(v) => v.take(), + _ => Value::Null + }); + map.insert(k, value); + } + RefValueWrapper::wrap(RefValue::Object(map)) + } +} + +struct ValueConverter; + +impl ValueConverter { + fn new(value: &TypeRefValue) -> Value { + ValueConverter {}.visit_value(value) + } + + fn visit_value(&self, value: &TypeRefValue) -> Value { + match &***value { + RefValue::Null => self.visit_null(), + RefValue::Bool(v) => self.visit_bool(v), + RefValue::Number(v) => self.visit_number(v), + RefValue::String(v) => self.visit_string(v), + RefValue::Array(v) => self.visit_array(v), + RefValue::Object(v) => self.visit_object(v), + } + } + fn visit_null(&self) -> Value { + Value::Null + } + fn visit_bool(&self, value: &bool) -> Value { + Value::Bool(*value) + } + fn visit_number(&self, value: &serde_json::Number) -> Value { + Value::Number(value.clone()) + } + fn visit_string(&self, value: &String) -> Value { + Value::String(value.clone()) + } + fn visit_array(&self, value: &Vec) -> Value { + let mut values = Vec::new(); + for v in value { + values.push(self.visit_value(v)); + } + Value::Array(values) + } + fn visit_object(&self, map: &IndexMap) -> Value { + let mut ret = serde_json::Map::new(); + let keys: Vec = map.keys().into_iter().map(|k: &String| k.to_string()).collect(); + let tmp_null = &RefValueWrapper::wrap(RefValue::Null); + for k in keys { + let value = self.visit_value(match map.get(&k) { + Some(e) => e, + _ => tmp_null + }); + ret.insert(k, value); + } + Value::Object(ret) + } +} \ No newline at end of file diff --git a/wasm/.gitignore b/wasm/.gitignore index 705d66b..cf9ef61 100644 --- a/wasm/.gitignore +++ b/wasm/.gitignore @@ -4,3 +4,5 @@ Cargo.lock bin/ pkg/ wasm-pack.log +.idea/* +.vscode \ No newline at end of file diff --git a/wasm/Cargo.toml b/wasm/Cargo.toml index 06c41dc..703770e 100644 --- a/wasm/Cargo.toml +++ b/wasm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "jsonpath-wasm" -version = "0.1.2" +version = "0.1.3" authors = ["Changseok Han "] description = "JsonPath Webassembly version compiled by Rust - Demo: https://freestrings.github.io/jsonpath" @@ -22,8 +22,10 @@ wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } console_error_panic_hook = { version = "0.1.1", optional = true } wee_alloc = { version = "0.4.2", optional = true } -jsonpath_lib = {path = "../"} +jsonpath_lib = { path = "../" } serde_json = { version = "1.0", features = ["preserve_order"] } +lazy_static = "1.3.0" +web-sys = { version = "0.3", features = ['console'] } [dev-dependencies] wasm-bindgen-test = "0.2" diff --git a/wasm/build.sh b/wasm/build.sh index 21a5dad..791d4d5 100755 --- a/wasm/build.sh +++ b/wasm/build.sh @@ -6,8 +6,10 @@ set -e DIR="$(pwd)" cd "${DIR}"/www && \ - rm -rf "${DIR}"/dist && \ - rm -rf "${DIR}"/node_modules && \ + rm -rf "${DIR}"/www/dist && \ + rm -rf "${DIR}"/www/node_modules && \ + rm -rf "${DIR}"/www_bench/dist && \ + rm -rf "${DIR}"/www_bench/node_modules && \ npm install && \ cd "${DIR}" @@ -24,6 +26,10 @@ echo "-------------------- build nodejs pkg done --------------------" cd "${DIR}" +echo +echo +echo +echo echo echo echo "-------------------- start build browser pkg --------------------" @@ -34,10 +40,40 @@ cd "${DIR}"/browser_pkg && npm link && \ cd "${DIR}"/www && npm link @browser/jsonpath-wasm echo "-------------------- build browser pkg done --------------------" +echo +echo +echo +echo echo echo echo "-------------------- start build browser bench pkg --------------------" echo rm -rf "${DIR}"/www_bench/node_modules && \ cd "${DIR}"/www_bench && npm install && npm link @browser/jsonpath-wasm -echo "-------------------- build browser bench pkg done --------------------" \ No newline at end of file +echo "-------------------- build browser bench pkg done --------------------" + +echo +echo +echo +echo +echo +echo +echo "-------------------- start build docs --------------------" +cd "${DIR}"/www && \ + npm run build && \ + rm -f "${DIR}"/../docs/*.js && rm -f "${DIR}"/../docs/*.wasm && rm -f "${DIR}"/../docs/*.html && \ + cp "${DIR}"/www/dist/*.* "${DIR}"/../docs/ +echo "-------------------- build docs done --------------------" + +echo +echo +echo +echo +echo +echo +echo "-------------------- start build docs bench --------------------" +cd "${DIR}"/www_bench && \ + npm run build && \ + rm -f "${DIR}"/../docs/bench/*.js && rm -f "${DIR}"/../docs/bench/*.wasm && rm -f "${DIR}"/../docs/bench/*.html && \ + cp "${DIR}"/www_bench/dist/*.* "${DIR}"/../docs/bench/ +echo "-------------------- build docs bench done --------------------" \ No newline at end of file diff --git a/wasm/src/lib.rs b/wasm/src/lib.rs index ce2a0ca..4cddbee 100644 --- a/wasm/src/lib.rs +++ b/wasm/src/lib.rs @@ -1,19 +1,24 @@ extern crate cfg_if; -extern crate wasm_bindgen; - -extern crate serde_json; extern crate jsonpath_lib as jsonpath; +#[macro_use] +extern crate lazy_static; +extern crate serde_json; +extern crate wasm_bindgen; +extern crate web_sys; -mod utils; +use std::collections::HashMap; +use std::result::Result; +use std::sync::Mutex; use cfg_if::cfg_if; -use wasm_bindgen::prelude::*; -use std::result::Result; -use std::rc::Rc; -use serde_json::Value; - -use jsonpath::parser::parser::*; use jsonpath::filter::value_filter::*; +use jsonpath::parser::parser::*; +use jsonpath::ref_value::*; +use serde_json::Value; +use wasm_bindgen::prelude::*; +use web_sys::console; + +mod utils; cfg_if! { if #[cfg(feature = "wee_alloc")] { @@ -23,17 +28,17 @@ cfg_if! { } } -fn filter_value(json: Value, node: Node) -> JsValue { - let mut jf = JsonValueFilter::new_from_value(Rc::new(Box::new(json))); +fn filter_ref_value(json: RefValueWrapper, node: Node) -> JsValue { + let mut jf = JsonValueFilter::new_from_value(json); jf.visit(node); - let taken = jf.take_value(); + let taken = jf.take_value().into_value(); match JsValue::from_serde(&taken) { Ok(js_value) => js_value, Err(e) => JsValue::from_str(&format!("Json deserialize error: {:?}", e)) } } -fn into_value(js_value: &JsValue) -> Result { +fn into_serde_json(js_value: &JsValue) -> Result { if js_value.is_string() { match serde_json::from_str(js_value.as_string().unwrap().as_str()) { Ok(json) => Ok(json), @@ -47,20 +52,64 @@ fn into_value(js_value: &JsValue) -> Result { } } -fn into_js_value(js_value: &JsValue, node: Node) -> JsValue { - match into_value(js_value) { - Ok(json) => filter_value(json, node), +fn into_ref_value(js_value: &JsValue, node: Node) -> JsValue { + match into_serde_json(js_value) { + Ok(json) => filter_ref_value(json.into(), node), Err(e) => JsValue::from_str(&format!("Json serialize error: {}", e)) } } +fn get_ref_value(js_value: JsValue, node: Node) -> JsValue { + match js_value.as_f64() { + Some(val) => { + match CACHE_JSON.lock().unwrap().get(&(val as usize)) { + Some(json) => filter_ref_value(json.clone(), node), + _ => JsValue::from_str("Invalid pointer") + } + } + _ => into_ref_value(&js_value, node) + } +} + +lazy_static! { + static ref CACHE_JSON: Mutex> = Mutex::new(HashMap::new()); + static ref CACHE_JSON_IDX: Mutex = Mutex::new(0); +} + +#[wasm_bindgen] +pub fn alloc_json(js_value: JsValue) -> usize { + match into_serde_json(&js_value) { + Ok(json) => { + let mut map = CACHE_JSON.lock().unwrap(); + if map.len() >= std::u8::MAX as usize { + return 0; + } + + let mut idx = CACHE_JSON_IDX.lock().unwrap(); + *idx += 1; + map.insert(*idx, json.into()); + *idx + } + Err(e) => { + console::log_1(&e.into()); + 0 + } + } +} + +#[wasm_bindgen] +pub fn dealloc_json(ptr: usize) -> bool { + let mut map = CACHE_JSON.lock().unwrap(); + map.remove(&ptr).is_some() +} + #[wasm_bindgen] pub fn compile(path: &str) -> JsValue { let mut parser = Parser::new(path); let node = parser.compile(); let cb = Closure::wrap(Box::new(move |js_value: JsValue| { match &node { - Ok(node) => into_js_value(&js_value, node.clone()), + Ok(node) => get_ref_value(js_value, node.clone()), Err(e) => JsValue::from_str(&format!("Json path error: {:?}", e)) } }) as Box JsValue>); @@ -70,12 +119,35 @@ pub fn compile(path: &str) -> JsValue { ret } +/// +/// deprecated. use selector +/// #[wasm_bindgen] pub fn reader(js_value: JsValue) -> JsValue { + selector(js_value) +} + +#[wasm_bindgen] +pub fn selector(js_value: JsValue) -> JsValue { + let json = match js_value.as_f64() { + Some(val) => { + match CACHE_JSON.lock().unwrap().get(&(val as usize)) { + Some(json) => json.clone(), + _ => return JsValue::from_str("Invalid pointer") + } + } + _ => { + match into_serde_json(&js_value) { + Ok(json) => json.into(), + Err(e) => return JsValue::from_str(e.as_str()) + } + } + }; + let cb = Closure::wrap(Box::new(move |path: String| { let mut parser = Parser::new(path.as_str()); match parser.compile() { - Ok(node) => into_js_value(&js_value, node), + Ok(node) => filter_ref_value(json.clone(), node), Err(e) => return JsValue::from_str(e.as_str()) } }) as Box JsValue>); @@ -86,14 +158,21 @@ pub fn reader(js_value: JsValue) -> JsValue { } #[wasm_bindgen] -pub fn read(js_value: JsValue, path: &str) -> JsValue { +pub fn select(js_value: JsValue, path: &str) -> JsValue { let mut parser = Parser::new(path); match parser.compile() { - Ok(node) => into_js_value(&js_value, node), + Ok(node) => get_ref_value(js_value, node), Err(e) => return JsValue::from_str(e.as_str()) } } +/// +/// deprecated. use select +/// #[wasm_bindgen] -pub fn testa() { -} \ No newline at end of file +pub fn read(js_value: JsValue, path: &str) -> JsValue { + select(js_value, path) +} + +#[wasm_bindgen] +pub fn testa() {} \ No newline at end of file diff --git a/wasm/www_bench/index.js b/wasm/www_bench/index.js index 9e0dc41..e5e3fce 100644 --- a/wasm/www_bench/index.js +++ b/wasm/www_bench/index.js @@ -2,11 +2,14 @@ import * as jpw from "@browser/jsonpath-wasm"; import * as jp from "jsonpath/jsonpath.js"; function run(message, iter, cb) { - let d = Date.now(); - for (let i = 0; i < iter; i++) { - cb(); - } - msg([message, Date.now() - d].join(", ")); + return new Promise(function(resolve, _reject) { + let d = Date.now(); + for (let i = 0; i < iter; i++) { + cb(); + } + msg([message, Date.now() - d].join(", ")); + setTimeout(resolve, 0); + }) } function msg(msg) { @@ -54,12 +57,33 @@ let json = { "expensive": 10 }; -setTimeout(function() { - let path = '$..book[?(@.price<30 && @.category=="fiction")]'; - let template = jpw.compile(path); - let reader = jpw.reader(json); - run('jsonpath', 1000, function() { jp.query(json, path) }); - run('jsonpath-wasm- reader', 1000, function() { reader(path) }); - run('jsonpath-wasm- compile', 1000, function() { template(json) }); - run('jsonpath-wasm- read', 1000, function() { jpw.read(json, path) }); -}, 0); +let path = '$..book[?(@.price<30 && @.category=="fiction")]'; +let template = jpw.compile(path); +let selector = jpw.selector(json); + +let ptr = jpw.alloc_json(json); +if(ptr == 0) console.error('invalid ptr'); + +let iterCount = 2000; + +run('jsonpath', iterCount, function() { jp.query(json, path) }) + .then(function() { + return run('jsonpath-wasm- selector', iterCount, function() { selector(path) }); + }) + .then(function() { + return run('jsonpath-wasm- compile', iterCount, function() { template(json) }); + }) + .then(function() { + return run('jsonpath-wasm- compile-alloc', iterCount, function() { template(ptr) }); + }) + .then(function() { + return run('jsonpath-wasm- select', iterCount, function() { jpw.select(json, path) }); + }) + .then(function() { + return run('jsonpath-wasm- select-alloc', iterCount, function() { jpw.select(ptr, path) }); + }) + .finally(function() { + if(!jpw.dealloc_json(ptr)) { + console.error('fail to dealloc'); + } + });