51 Commits

Author SHA1 Message Date
vms
810e0c6988 delete log 2021-06-01 18:09:18 +03:00
vms
bc626daec8 improve tests 2021-06-01 18:07:18 +03:00
vms
2042c63c86 bump minor version 2021-06-01 17:48:09 +03:00
vms
f997d5252b return error if key or index not found 2021-06-01 17:46:10 +03:00
vms
021f57b323 support flatenning 2020-12-23 15:12:58 +03:00
vms
4767c8368e prepare for publish 2020-12-23 10:21:40 +03:00
vms
538b433ae2 support iterator 2020-11-23 08:37:27 +03:00
f919a5305b Bump http-proxy from 1.18.0 to 1.18.1 in /wasm/www_bench
Bumps [http-proxy](https://github.com/http-party/node-http-proxy) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/http-party/node-http-proxy/releases)
- [Changelog](https://github.com/http-party/node-http-proxy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/http-party/node-http-proxy/compare/1.18.0...1.18.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-29 10:05:06 +09:00
0c29607451 Bump http-proxy from 1.18.0 to 1.18.1 in /wasm/www
Bumps [http-proxy](https://github.com/http-party/node-http-proxy) from 1.18.0 to 1.18.1.
- [Release notes](https://github.com/http-party/node-http-proxy/releases)
- [Changelog](https://github.com/http-party/node-http-proxy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/http-party/node-http-proxy/compare/1.18.0...1.18.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-29 10:04:49 +09:00
5ba05092b2 Bump elliptic from 6.5.2 to 6.5.3 in /wasm/www_bench
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-29 10:04:37 +09:00
4a423b812f Bump elliptic from 6.5.2 to 6.5.3 in /wasm/www
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-29 10:04:05 +09:00
9dcc5a0b7a Bump lodash from 4.17.15 to 4.17.19 in /wasm/tests
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-21 11:59:59 +09:00
0bae419fe6 Bump lodash from 4.17.15 to 4.17.19 in /wasm/www_bench
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-21 11:59:47 +09:00
edc335c4e3 Bump lodash from 4.17.15 to 4.17.19 in /wasm/www
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-21 11:59:34 +09:00
bf115e468c Bump websocket-extensions from 0.1.3 to 0.1.4 in /wasm/www_bench
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-06-21 15:51:48 +09:00
084ca7b838 Bump websocket-extensions from 0.1.3 to 0.1.4 in /wasm/www
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-06-21 15:51:37 +09:00
f98b8d7894 Clean some warnings
* 'msg' was used before it was defined.
* Missing semicolon.
2020-05-25 09:52:00 +09:00
9d78b6910c Clean code warnings
* 'readPath' was used before it was defined.
* Missing semicolon
2020-05-25 09:51:41 +09:00
49179464f6 fix build script 2020-04-15 10:09:19 +09:00
81bbf47545 Bump up npm dependencies 2020-04-14 12:07:50 +09:00
55e8088111 Bump up 0.2.5 2020-04-14 11:53:34 +09:00
c1d4c78da9 build wasm 2020-04-14 11:33:31 +09:00
75c28fc73d close #43 2020-04-14 11:09:57 +09:00
1512e9b72f Failure to match "$..['']", "$..['ref']", but succeeds on $..ref #43 2020-04-14 11:09:14 +09:00
a168c46c04 Failure to match "$..['']", "$..['ref']", but succeeds on $..ref #43 2020-04-14 11:09:14 +09:00
83a170eb08 Bump acorn from 6.1.1 to 6.4.1 in /wasm/examples/browser
Bumps [acorn](https://github.com/acornjs/acorn) from 6.1.1 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.1.1...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-04-07 09:49:53 +09:00
710f7ad544 close #39 2020-03-24 13:06:23 +09:00
74e79e6330 Empty result for filter expression returns array of null #39 2020-03-23 23:53:26 +09:00
ec92c95a69 Merge branch 'feature/code_cleanup' 2020-03-23 23:21:32 +09:00
da7cf723de fix clippy error 2020-03-23 23:03:19 +09:00
c99879cfbb filter, collector 정리 2020-03-23 22:50:08 +09:00
7991bba51d cmp, expr_term 분리 2020-03-22 23:48:24 +09:00
b8c82a9126 walk류 함수를 ValueWalker로 옮김 2020-03-22 23:22:53 +09:00
ba31b48c73 close #40 2020-03-22 22:36:26 +09:00
e9f69cd2b9 Bracket notation after recursive descent does not recurse #40 - fix clippy error 2020-03-22 22:34:47 +09:00
241a7f482d Bracket notation after recursive descent does not recurse #40 2020-03-22 22:25:07 +09:00
67cc6447a8 Bump acorn from 6.1.1 to 6.4.1 in /wasm/www_bench
Bumps [acorn](https://github.com/acornjs/acorn) from 6.1.1 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.1.1...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-20 10:57:31 +09:00
9bc4b81f33 Bump acorn from 6.1.1 to 6.4.1 in /wasm/www
Bumps [acorn](https://github.com/acornjs/acorn) from 6.1.1 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.1.1...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-03-20 10:57:08 +09:00
0d4d82fd49 close #38 2020-03-20 10:19:26 +09:00
de46a66148 Bracket notation not supported inside filter expression #38 - fix clippy error 2020-03-16 00:55:42 +09:00
ef52c63bc8 Bracket notation not supported inside filter expression #38 - add unit test 2020-03-16 00:50:51 +09:00
d618e60e13 Bracket notation not supported inside filter expression #38 2020-03-10 23:24:07 +09:00
a6f742e3ad 다중패스 필터 안되는 문제 수정 2020-03-10 23:22:35 +09:00
6f20013076 close #37 2020-02-23 20:43:31 +09:00
218321a4bd fix return_type_for_child_object_not_matched 2020-02-23 19:18:13 +09:00
d855c17899 split unit-tests 2020-02-23 14:45:14 +09:00
4919a03c6b fix clippy error 2020-02-16 22:43:39 +09:00
7a07bc7744 Remove useless code 2020-02-16 22:16:22 +09:00
32eef3f7c7 Restore wrong commit 2020-02-16 13:19:32 +09:00
b736c962d2 close #35 2020-02-16 13:17:44 +09:00
accd08139f Negative slice out of bounds does not return values #35 2020-02-16 13:14:31 +09:00
50 changed files with 6377 additions and 10497 deletions

View File

@ -1,12 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="filter" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib --test filter &quot;&quot;" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@ -1,12 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="lib" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib --test lib &quot;&quot;" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@ -1,12 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="mutable" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib --test mutable &quot;&quot;" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@ -1,12 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="readme" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="channel" value="DEFAULT" />
<option name="command" value="test --package jsonpath_lib --test readme &quot;&quot;" />
<option name="allFeatures" value="false" />
<option name="nocapture" value="false" />
<option name="backtrace" value="SHORT" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<envs />
<method v="2" />
</configuration>
</component>

View File

@ -24,15 +24,9 @@ matrix:
before_script: before_script:
- rustup component add clippy - rustup component add clippy
script: script:
- cargo clean - ./clippy.sh
- cargo clippy -- -D warnings
- cargo build --verbose --all
- cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity
- cargo test --verbose --all
- cd wasm && cargo clippy -- -D warnings -A clippy::suspicious_else_formatting
- cd ../../
after_success: | after_success: |
cargo tarpaulin --exclude-files nodejs wasm parser/mod.rs --out Xml cargo tarpaulin --exclude-files wasm parser/mod.rs --out Xml
bash <(curl -s https://codecov.io/bash) bash <(curl -s https://codecov.io/bash)
- rust: stable - rust: stable
os: osx os: osx
@ -53,8 +47,6 @@ matrix:
- sh /tmp/rustup.sh -y - sh /tmp/rustup.sh -y
- export PATH="$HOME/.cargo/bin:$PATH" - export PATH="$HOME/.cargo/bin:$PATH"
- source "$HOME/.cargo/env" - source "$HOME/.cargo/env"
- node -v
- npm -v
before_script: before_script:
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f
script: script:
@ -71,8 +63,6 @@ matrix:
- sh /tmp/rustup.sh -y - sh /tmp/rustup.sh -y
- export PATH="$HOME/.cargo/bin:$PATH" - export PATH="$HOME/.cargo/bin:$PATH"
- source "$HOME/.cargo/env" - source "$HOME/.cargo/env"
- node -v
- npm -v
before_script: before_script:
- curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f - curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -f
script: script:

View File

@ -1,19 +1,18 @@
[package] [package]
name = "jsonpath_lib" name = "jsonpath_lib-fl"
version = "0.2.4" version = "0.3.7"
authors = ["Changseok Han <freestrings@gmail.com>"] authors = ["Changseok Han <freestrings@gmail.com>"]
description = "It is JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript too. - Webassembly Demo: https://freestrings.github.io/jsonpath" description = "It is JsonPath engine written in Rust. it provide a similar API interface in Webassembly and Javascript too. - Webassembly Demo: https://freestrings.github.io/jsonpath"
readme = "README.md" readme = "README.md"
keywords = ["jsonpath", "json", "webassembly", "nodejs", "query"] keywords = ["jsonpath", "json", "webassembly", "lua", "query"]
categories = ['wasm', "parser-implementations", "api-bindings"]
repository = "https://github.com/freestrings/jsonpath" repository = "https://github.com/freestrings/jsonpath"
documentation = "https://docs.rs/jsonpath_lib/0.2.4/jsonpath_lib" documentation = "https://docs.rs/jsonpath_lib/0.2.5/jsonpath_lib"
license = "MIT" license = "MIT"
categories = ["parsing"]
[badges] [badges]
travis-ci = { repository = "freestrings/jsonpath", branch = "master" } travis-ci = { repository = "freestrings/jsonpath", branch = "master" }
@ -29,6 +28,6 @@ name = "jsonpath_lib"
path = "src/lib.rs" path = "src/lib.rs"
crate-type = ["cdylib", "rlib"] crate-type = ["cdylib", "rlib"]
[profile.release] #[profile.release]
#debug = true #debug = true
#lto = false #lto = false

View File

@ -5,7 +5,7 @@
![npm](https://img.shields.io/npm/v/jsonpath-wasm.svg?label=npm%20%60jsonpath-wasm%60) ![npm](https://img.shields.io/npm/v/jsonpath-wasm.svg?label=npm%20%60jsonpath-wasm%60)
![Codecov](https://img.shields.io/codecov/c/github/freestrings/jsonpath.svg?token=92c41b4e7cf04a9cbebc08f68c5da615) ![Codecov](https://img.shields.io/codecov/c/github/freestrings/jsonpath.svg?token=92c41b4e7cf04a9cbebc08f68c5da615)
`Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현이다. `Webassembly``Javascript`에서도 유사한 API 인터페이스를 제공 한다. `Rust` 버전 [JsonPath](https://goessner.net/articles/JsonPath/) 구현으로 `Webassembly``Javascript`에서도 유사한 API 인터페이스를 제공 한다.
It is JsonPath [JsonPath](https://goessner.net/articles/JsonPath/) engine written in `Rust`. it provide a similar API interface in `Webassembly` and` Javascript` too. It is JsonPath [JsonPath](https://goessner.net/articles/JsonPath/) engine written in `Rust`. it provide a similar API interface in `Webassembly` and` Javascript` too.

View File

@ -1,222 +0,0 @@
{
"name": "jsonpath-benches",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"JSONSelect": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz",
"integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40="
},
"cjson": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/cjson/-/cjson-0.2.1.tgz",
"integrity": "sha1-c82KrWXZ4VBfmvF0TTt5wVJ2gqU="
},
"colors": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz",
"integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q="
},
"deep-is": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
},
"ebnf-parser": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz",
"integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE="
},
"escodegen": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.21.tgz",
"integrity": "sha1-U9ZSz6EDA4gnlFilJmxf/HCcY8M=",
"requires": {
"esprima": "~1.0.2",
"estraverse": "~0.0.4",
"source-map": ">= 0.1.2"
},
"dependencies": {
"esprima": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
"integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0="
}
}
},
"esprima": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz",
"integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs="
},
"estraverse": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-0.0.4.tgz",
"integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI="
},
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
},
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"jison": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz",
"integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=",
"requires": {
"JSONSelect": "0.4.0",
"cjson": "~0.2.1",
"ebnf-parser": "~0.1.9",
"escodegen": "0.0.21",
"esprima": "1.0.x",
"jison-lex": "0.2.x",
"lex-parser": "~0.1.3",
"nomnom": "1.5.2"
},
"dependencies": {
"esprima": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
"integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0="
}
}
},
"jison-lex": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.2.1.tgz",
"integrity": "sha1-rEuBXozOUTLrErXfz+jXB7iETf4=",
"requires": {
"lex-parser": "0.1.x",
"nomnom": "1.5.2"
}
},
"jsonpath": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.0.1.tgz",
"integrity": "sha512-HY5kSg82LHIs0r0h9gYBwpNc1w1qGY0qJ7al01W1bJltsN2lp+mjjA/a79gXWuvD6Xf8oPkD2d5uKMZQXTGzqA==",
"requires": {
"esprima": "1.2.2",
"jison": "0.4.13",
"static-eval": "2.0.2",
"underscore": "1.7.0"
}
},
"levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
"requires": {
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2"
}
},
"lex-parser": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz",
"integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA="
},
"nomnom": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz",
"integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=",
"requires": {
"colors": "0.5.x",
"underscore": "1.1.x"
},
"dependencies": {
"underscore": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz",
"integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA="
}
}
},
"optionator": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
"integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
"requires": {
"deep-is": "~0.1.3",
"fast-levenshtein": "~2.0.4",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
"wordwrap": "~1.0.0"
}
},
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
},
"source-map": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
"integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
"optional": true
},
"static-eval": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
"integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==",
"requires": {
"escodegen": "^1.8.1"
},
"dependencies": {
"escodegen": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz",
"integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==",
"requires": {
"esprima": "^3.1.3",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1",
"source-map": "~0.6.1"
}
},
"esprima": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
"integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
},
"estraverse": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true
}
}
},
"type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
"requires": {
"prelude-ls": "~1.1.2"
}
},
"underscore": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz",
"integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk="
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
}
}
}

View File

@ -7,9 +7,8 @@ DIR="$(pwd)"
WASM="${DIR}"/wasm WASM="${DIR}"/wasm
WASM_WWW="${WASM}"/www WASM_WWW="${WASM}"/www
WASM_WWW_BENCH="${WASM}"/www_bench WASM_WWW_BENCH="${WASM}"/www_bench
WASM_BROWSER_PKG="${WASM}"/browser_pkg
WASM_NODEJS_PKG="${WASM}"/nodejs_pkg WASM_NODEJS_PKG="${WASM}"/nodejs_pkg
WASM_ALL_PKG="${WASM}"/all_pkg WASM_WEB_PKG="${WASM}"/web_pkg
WASM_TEST="${WASM}"/tests WASM_TEST="${WASM}"/tests
DOCS="${DIR}"/docs DOCS="${DIR}"/docs
DOCS_BENCH="${DOCS}"/bench DOCS_BENCH="${DOCS}"/bench
@ -19,6 +18,8 @@ __msg () {
} }
__cargo_clean () { __cargo_clean () {
rm -f "${DIR}"/Cargo.lock
rm -f "${WASM}"/Cargo.lock
cd "${WASM}" && cargo clean && \ cd "${WASM}" && cargo clean && \
cd "${DIR}" && cargo clean cd "${DIR}" && cargo clean
} }
@ -27,78 +28,64 @@ echo
__msg "clean wasm" __msg "clean wasm"
rm -rf \ rm -rf \
"${WASM_NODEJS_PKG}" \ "${WASM_NODEJS_PKG}" \
"${WASM_BROWSER_PKG}" \ "${WASM_WEB_PKG}" \
"${WASM_ALL_PKG}" \
"${WASM_WWW}"/node_modules \
"${WASM_WWW_BENCH}"/node_modules \
"${WASM_WWW}"/dist \ "${WASM_WWW}"/dist \
"${WASM_WWW}"/node_modules \
"${WASM_WWW}"/package-lock.json \
"${WASM_WWW_BENCH}"/dist \ "${WASM_WWW_BENCH}"/dist \
"${WASM_TEST}"/node_modules "${WASM_WWW_BENCH}"/node_modules \
"${WASM_WWW_BENCH}"/package-lock.json \
"${WASM_TEST}"/node_modules \
"${WASM_TEST}"/package-lock.json
if [ "$1" = "all" ]; then __msg "clean cargo clean"
__msg "clean all wasm" __cargo_clean
__cargo_clean
fi echo
wasm_pack_version=$(wasm-pack -V)
__msg "wasm-pack: ${wasm_pack_version}"
echo
__msg "wasm-pack nodejs"
cd "${WASM}" && wasm-pack build --release --target "nodejs" --out-dir "${WASM_NODEJS_PKG}"
__msg "npm install: wasm"
cd "${WASM_WWW}" && npm install
__msg "npm install: wasm_bench"
cd "${WASM_WWW_BENCH}" && npm install
__msg "npm install: wasm test" __msg "npm install: wasm test"
cd "${WASM_TEST}" && npm install cd "${WASM_TEST}" && npm install "${WASM_NODEJS_PKG}" && npm install
echo
echo
__msg "wasm-pack"
cd "${WASM}" && \
wasm-pack build --release --target=nodejs --out-dir "${WASM_NODEJS_PKG}"
cd "${WASM}" && \
wasm-pack build --release --target=browser --out-dir "${WASM_BROWSER_PKG}"
# && \
# wasm-pack test --chrome --firefox --headless
__msg "wasm npm packaging"
cp -r "${WASM_BROWSER_PKG}" "${WASM_ALL_PKG}/" && \
sed "s/require[\(]'\.\/jsonpath_wasm_bg/require\('\.\/jsonpath_wasm_nodejs/" "${WASM_NODEJS_PKG}/jsonpath_wasm.js" \
> "${WASM_ALL_PKG}/jsonpath_wasm_main.js" && \
sed "s/require[\(]'\.\/jsonpath_wasm/require\('\.\/jsonpath_wasm_main/" "${WASM_NODEJS_PKG}/jsonpath_wasm_bg.js" \
> "${WASM_ALL_PKG}/jsonpath_wasm_nodejs.js" && \
jq ".files += [\"jsonpath_wasm_nodejs.js\"]" ${WASM_ALL_PKG}/package.json \
| jq ".main = \"jsonpath_wasm_main.js\"" \
| jq ".keywords += [\"jsonpath\", \"json\", \"webassembly\", \"parsing\", \"rust\"]" \
> ${WASM_ALL_PKG}/temp.json && \
mv -v "${WASM_ALL_PKG}/temp.json" "${WASM_ALL_PKG}/package.json" && \
cd "${WASM_ALL_PKG}" && npm link
echo
__msg "link"
cd "${WASM_WWW}" && \
npm link jsonpath-wasm
cd "${WASM_WWW_BENCH}" && \
npm link jsonpath-wasm
cd "${WASM_TEST}" && \
npm link jsonpath-wasm
echo
echo echo
__msg "wasm test" __msg "wasm test"
cd "${WASM_TEST}" && npm test cd "${WASM_TEST}" && npm test
if [ "$1" = "all" ] || [ "$1" = "docs" ]; then if [ "$1" = "docs" ]; then
echo echo
__msg "docs" __msg "wasm-pack web"
cd "${WASM_WWW}" && \ cd "${WASM}" && wasm-pack build --release --out-dir "${WASM_WEB_PKG}"
npm run build &&
rm -f "${DOCS}"/*.js "${DOCS}"/*.wasm "${DOCS}"/*.html && \
cp "${WASM_WWW}"/dist/*.* "${DOCS}"/
cd "${WASM_WWW_BENCH}" && \ echo
npm run build && __msg "jsonpath-wasm npm link"
rm -f "${DOCS_BENCH}"/*.js "${DOCS_BENCH}"/*.wasm "${DOCS_BENCH}"/*.html && \ cd "${WASM_WEB_PKG}" && npm link
cp "${WASM_WWW_BENCH}"/dist/*.* "${DOCS_BENCH}"/
__msg "npm install: wasm"
cd "${WASM_WWW}" && npm install
__msg "npm install: wasm_bench"
cd "${WASM_WWW_BENCH}" && npm install
echo
__msg "link"
cd "${WASM_WWW}" && npm link jsonpath-wasm
cd "${WASM_WWW_BENCH}" && npm link jsonpath-wasm
echo
__msg "docs"
cd "${WASM_WWW}" && \
npm run build &&
rm -f "${DOCS}"/*.js "${DOCS}"/*.wasm "${DOCS}"/*.html && \
cp "${WASM_WWW}"/dist/*.* "${DOCS}"/
cd "${WASM_WWW_BENCH}" && \
npm run build &&
rm -f "${DOCS_BENCH}"/*.js "${DOCS_BENCH}"/*.wasm "${DOCS_BENCH}"/*.html && \
cp "${WASM_WWW_BENCH}"/dist/*.* "${DOCS_BENCH}"/
fi fi
__msg "wasm done" __msg "wasm done"

132
build.sh
View File

@ -1,132 +0,0 @@
#!/bin/bash
set -e
# project_root
DIR="$(pwd)"
WASM="${DIR}"/wasm
WASM_WWW="${WASM}"/www
WASM_WWW_BENCH="${WASM}"/www_bench
WASM_BROWSER_PKG="${WASM}"/browser_pkg
WASM_NODEJS_PKG="${WASM}"/nodejs_pkg
WASM_ALL_PKG="${WASM}"/all_pkg
WASM_TEST="${WASM}"/tests
BENCHES="${DIR}"/benchmark
BENCHES_JS="${BENCHES}"/javascript
NODEJS="${DIR}"/nodejs
DOCS="${DIR}"/docs
DOCS_BENCH="${DOCS}"/bench
__msg () {
echo ">>>>>>>>>>$1<<<<<<<<<<"
}
__cargo_clean () {
cd "${BENCHES}"/bench_bin && cargo clean && \
cd "${NODEJS}"/native && cargo clean && \
cd "${WASM}" && cargo clean && \
cd "${DIR}" && cargo clean
}
if [ "$1" = "clippy" ]
then
echo
__msg "clippy"
cargo clippy -- -D warnings && \
cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity && \
cd "${WASM}" && cargo clippy -- -A clippy::suspicious_else_formatting && \
cd "${NODEJS}" && cargo clippy
fi
echo
__msg "clean"
rm -rf \
"${WASM_NODEJS_PKG}" \
"${WASM_BROWSER_PKG}" \
"${WASM_ALL_PKG}" \
"${BENCHES_JS}"/node_modules \
"${NODEJS}"/node_modules \
"${WASM_WWW}"/node_modules \
"${WASM_WWW_BENCH}"/node_modules \
"${WASM_WWW}"/dist \
"${WASM_WWW_BENCH}"/dist \
"${WASM_TEST}"/node_modules
if [ "$1" = "all" ]; then
__msg "clean targets"
__cargo_clean
fi
__msg "npm install: wasm"
cd "${WASM_WWW}" && npm install
__msg "npm install: wasm_bench"
cd "${WASM_WWW_BENCH}" && npm install
__msg "npm install: nodejs"
cd "${NODEJS}" && npm install
__msg "npm install: benches_js"
cd "${BENCHES_JS}" && npm install
__msg "npm install: wasm test"
cd "${WASM_TEST}" && npm install
echo
echo
__msg "nodejs test"
cd "${NODEJS}" && npm test
echo
echo
__msg "wasm-pack"
cd "${WASM}" && \
wasm-pack build --release --target=nodejs --out-dir "${WASM_NODEJS_PKG}"
cd "${WASM}" && \
wasm-pack build --release --target=browser --out-dir "${WASM_BROWSER_PKG}"
# && \
# wasm-pack test --chrome --firefox --headless
__msg "wasm npm packaging"
cp -r "${WASM_BROWSER_PKG}" "${WASM_ALL_PKG}/" && \
sed "s/require[\(]'\.\/jsonpath_wasm_bg/require\('\.\/jsonpath_wasm_nodejs/" "${WASM_NODEJS_PKG}/jsonpath_wasm.js" \
> "${WASM_ALL_PKG}/jsonpath_wasm_main.js" && \
sed "s/require[\(]'\.\/jsonpath_wasm/require\('\.\/jsonpath_wasm_main/" "${WASM_NODEJS_PKG}/jsonpath_wasm_bg.js" \
> "${WASM_ALL_PKG}/jsonpath_wasm_nodejs.js" && \
jq ".files += [\"jsonpath_wasm_nodejs.js\"]" ${WASM_ALL_PKG}/package.json \
| jq ".main = \"jsonpath_wasm_main.js\"" \
| jq ".keywords += [\"jsonpath\", \"json\", \"webassembly\", \"parsing\", \"rust\"]" \
> ${WASM_ALL_PKG}/temp.json && \
mv -v "${WASM_ALL_PKG}/temp.json" "${WASM_ALL_PKG}/package.json" && \
cd "${WASM_ALL_PKG}" && npm link
echo
__msg "link"
cd "${WASM_WWW}" && \
npm link jsonpath-wasm
cd "${WASM_WWW_BENCH}" && \
npm link jsonpath-wasm
cd "${BENCHES_JS}" && \
npm link jsonpath-wasm
cd "${WASM_TEST}" && \
npm link jsonpath-wasm
echo
echo
__msg "wasm test"
cd "${WASM_TEST}" && npm test
echo
__msg "docs"
cd "${WASM_WWW}" && \
npm run build &&
rm -f "${DOCS}"/*.js "${DOCS}"/*.wasm "${DOCS}"/*.html && \
cp "${WASM_WWW}"/dist/*.* "${DOCS}"/
cd "${WASM_WWW_BENCH}" && \
npm run build &&
rm -f "${DOCS_BENCH}"/*.js "${DOCS_BENCH}"/*.wasm "${DOCS_BENCH}"/*.html && \
cp "${WASM_WWW_BENCH}"/dist/*.* "${DOCS_BENCH}"/
__msg "done"

11
clippy.sh Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -e
cargo clean
cargo clippy -- -D warnings
cargo build --verbose --all
cargo clippy --all-targets --all-features -- -D warnings -A clippy::cognitive_complexity
cargo test --verbose --all
cd wasm && cargo clippy -- -D warnings -A clippy::suspicious_else_formatting
cd ../

File diff suppressed because one or more lines are too long

38
docs/1.bootstrap.js Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -10,7 +10,7 @@
/******/ var moduleId, chunkId, i = 0, resolves = []; /******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) { /******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i]; /******/ chunkId = chunkIds[i];
/******/ if(installedChunks[chunkId]) { /******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]); /******/ resolves.push(installedChunks[chunkId][0]);
/******/ } /******/ }
/******/ installedChunks[chunkId] = 0; /******/ installedChunks[chunkId] = 0;
@ -52,53 +52,53 @@
/******/ function promiseResolve() { return Promise.resolve(); } /******/ function promiseResolve() { return Promise.resolve(); }
/******/ /******/
/******/ var wasmImportObjects = { /******/ var wasmImportObjects = {
/******/ "../all_pkg/jsonpath_wasm_bg.wasm": function() { /******/ "../web_pkg/jsonpath_wasm_bg.wasm": function() {
/******/ return { /******/ return {
/******/ "./jsonpath_wasm": { /******/ "./jsonpath_wasm.js": {
/******/ "__wbindgen_json_parse": function(p0i32,p1i32) { /******/ "__wbindgen_json_parse": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_json_serialize": function(p0i32,p1i32) { /******/ "__wbindgen_json_serialize": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32);
/******/ },
/******/ "__wbg_error_bb0b0e541b3bff31": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbg_error_bb0b0e541b3bff31"](p0i32,p1i32);
/******/ },
/******/ "__wbindgen_object_drop_ref": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32);
/******/ }, /******/ },
/******/ "__wbindgen_cb_forget": function(p0i32) { /******/ "__wbindgen_cb_forget": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32);
/******/ }, /******/ },
/******/ "__wbindgen_string_new": function(p0i32,p1i32) { /******/ "__wbg_error_e7d3e8dbb31828c8": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbg_error_e7d3e8dbb31828c8"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbg_call_88d2a6153573084e": function(p0i32,p1i32,p2i32,p3i32) { /******/ "__wbindgen_object_drop_ref": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbg_call_88d2a6153573084e"](p0i32,p1i32,p2i32,p3i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32);
/******/ },
/******/ "__wbindgen_is_string": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32);
/******/ },
/******/ "__wbindgen_string_get": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_object_clone_ref": function(p0i32) { /******/ "__wbindgen_object_clone_ref": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32);
/******/ },
/******/ "__wbindgen_string_new": function(p0i32,p1i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32);
/******/ },
/******/ "__wbg_call_1ad0eb4a7ab279eb": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbg_call_1ad0eb4a7ab279eb"](p0i32,p1i32,p2i32);
/******/ },
/******/ "__wbindgen_is_string": function(p0i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32);
/******/ },
/******/ "__wbindgen_string_get": function(p0i32,p1i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_debug_string": function(p0i32,p1i32) { /******/ "__wbindgen_debug_string": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_debug_string"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_debug_string"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_throw": function(p0i32,p1i32) { /******/ "__wbindgen_throw": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_rethrow": function(p0i32) { /******/ "__wbindgen_rethrow": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32);
/******/ }, /******/ },
/******/ "__wbindgen_closure_wrapper115": function(p0i32,p1i32,p2i32) { /******/ "__wbindgen_closure_wrapper28": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper115"](p0i32,p1i32,p2i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper28"](p0i32,p1i32,p2i32);
/******/ }, /******/ },
/******/ "__wbindgen_closure_wrapper117": function(p0i32,p1i32,p2i32) { /******/ "__wbindgen_closure_wrapper26": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper117"](p0i32,p1i32,p2i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper26"](p0i32,p1i32,p2i32);
/******/ } /******/ }
/******/ } /******/ }
/******/ }; /******/ };
@ -161,6 +161,8 @@
/******/ } /******/ }
/******/ script.src = jsonpScriptSrc(chunkId); /******/ script.src = jsonpScriptSrc(chunkId);
/******/ /******/
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ onScriptComplete = function (event) { /******/ onScriptComplete = function (event) {
/******/ // avoid mem leaks in IE. /******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null; /******/ script.onerror = script.onload = null;
@ -170,7 +172,8 @@
/******/ if(chunk) { /******/ if(chunk) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); /******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src; /******/ var realSrc = event && event.target && event.target.src;
/******/ var error = new Error('Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'); /******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType; /******/ error.type = errorType;
/******/ error.request = realSrc; /******/ error.request = realSrc;
/******/ chunk[1](error); /******/ chunk[1](error);
@ -188,7 +191,7 @@
/******/ /******/
/******/ // Fetch + compile chunk loading for webassembly /******/ // Fetch + compile chunk loading for webassembly
/******/ /******/
/******/ var wasmModules = {"0":["../all_pkg/jsonpath_wasm_bg.wasm"]}[chunkId] || []; /******/ var wasmModules = {"1":["../web_pkg/jsonpath_wasm_bg.wasm"]}[chunkId] || [];
/******/ /******/
/******/ wasmModules.forEach(function(wasmModuleId) { /******/ wasmModules.forEach(function(wasmModuleId) {
/******/ var installedWasmModuleData = installedWasmModules[wasmModuleId]; /******/ var installedWasmModuleData = installedWasmModules[wasmModuleId];
@ -198,7 +201,7 @@
/******/ promises.push(installedWasmModuleData); /******/ promises.push(installedWasmModuleData);
/******/ else { /******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId](); /******/ var importObject = wasmImportObjects[wasmModuleId]();
/******/ var req = fetch(__webpack_require__.p + "" + {"../all_pkg/jsonpath_wasm_bg.wasm":"33fd09cf53124f20b1e8"}[wasmModuleId] + ".module.wasm"); /******/ var req = fetch(__webpack_require__.p + "" + {"../web_pkg/jsonpath_wasm_bg.wasm":"a9530753c3f0aa3c5ead"}[wasmModuleId] + ".module.wasm");
/******/ var promise; /******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') { /******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) { /******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
@ -299,7 +302,7 @@
/*! no static exports found */ /*! no static exports found */
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
eval("// A dependency graph that contains any wasm must all be imported\n// asynchronously. This `bootstrap.js` file does the single async import, so\n// that no one else needs to worry about it again.\nPromise.all(/*! import() */[__webpack_require__.e(1), __webpack_require__.e(0)]).then(__webpack_require__.bind(null, /*! ./index.js */ \"./index.js\"))\n .catch(e => console.error(\"Error importing `index.js`:\", e));\n\n//# sourceURL=webpack:///./bootstrap.js?"); eval("// A dependency graph that contains any wasm must all be imported\n// asynchronously. This `bootstrap.js` file does the single async import, so\n// that no one else needs to worry about it again.\nPromise.all(/*! import() */[__webpack_require__.e(0), __webpack_require__.e(1)]).then(__webpack_require__.bind(null, /*! ./index.js */ \"./index.js\"))\n .catch(e => console.error(\"Error importing `index.js`:\", e));\n\n//# sourceURL=webpack:///./bootstrap.js?");
/***/ }) /***/ })

71
docs/bootstrap.js vendored
View File

@ -10,7 +10,7 @@
/******/ var moduleId, chunkId, i = 0, resolves = []; /******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) { /******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i]; /******/ chunkId = chunkIds[i];
/******/ if(installedChunks[chunkId]) { /******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]); /******/ resolves.push(installedChunks[chunkId][0]);
/******/ } /******/ }
/******/ installedChunks[chunkId] = 0; /******/ installedChunks[chunkId] = 0;
@ -52,53 +52,53 @@
/******/ function promiseResolve() { return Promise.resolve(); } /******/ function promiseResolve() { return Promise.resolve(); }
/******/ /******/
/******/ var wasmImportObjects = { /******/ var wasmImportObjects = {
/******/ "../all_pkg/jsonpath_wasm_bg.wasm": function() { /******/ "../web_pkg/jsonpath_wasm_bg.wasm": function() {
/******/ return { /******/ return {
/******/ "./jsonpath_wasm": { /******/ "./jsonpath_wasm.js": {
/******/ "__wbindgen_json_parse": function(p0i32,p1i32) { /******/ "__wbindgen_json_parse": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_parse"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_json_serialize": function(p0i32,p1i32) { /******/ "__wbindgen_json_serialize": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_json_serialize"](p0i32,p1i32);
/******/ },
/******/ "__wbg_error_bb0b0e541b3bff31": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbg_error_bb0b0e541b3bff31"](p0i32,p1i32);
/******/ },
/******/ "__wbindgen_object_drop_ref": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32);
/******/ }, /******/ },
/******/ "__wbindgen_cb_forget": function(p0i32) { /******/ "__wbindgen_cb_forget": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_cb_forget"](p0i32);
/******/ }, /******/ },
/******/ "__wbindgen_string_new": function(p0i32,p1i32) { /******/ "__wbg_error_e7d3e8dbb31828c8": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbg_error_e7d3e8dbb31828c8"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbg_call_88d2a6153573084e": function(p0i32,p1i32,p2i32,p3i32) { /******/ "__wbindgen_object_drop_ref": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbg_call_88d2a6153573084e"](p0i32,p1i32,p2i32,p3i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_drop_ref"](p0i32);
/******/ },
/******/ "__wbindgen_is_string": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32);
/******/ },
/******/ "__wbindgen_string_get": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_object_clone_ref": function(p0i32) { /******/ "__wbindgen_object_clone_ref": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_object_clone_ref"](p0i32);
/******/ },
/******/ "__wbindgen_string_new": function(p0i32,p1i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_new"](p0i32,p1i32);
/******/ },
/******/ "__wbg_call_1ad0eb4a7ab279eb": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbg_call_1ad0eb4a7ab279eb"](p0i32,p1i32,p2i32);
/******/ },
/******/ "__wbindgen_is_string": function(p0i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_is_string"](p0i32);
/******/ },
/******/ "__wbindgen_string_get": function(p0i32,p1i32) {
/******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_string_get"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_debug_string": function(p0i32,p1i32) { /******/ "__wbindgen_debug_string": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_debug_string"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_debug_string"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_throw": function(p0i32,p1i32) { /******/ "__wbindgen_throw": function(p0i32,p1i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_throw"](p0i32,p1i32);
/******/ }, /******/ },
/******/ "__wbindgen_rethrow": function(p0i32) { /******/ "__wbindgen_rethrow": function(p0i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_rethrow"](p0i32);
/******/ }, /******/ },
/******/ "__wbindgen_closure_wrapper115": function(p0i32,p1i32,p2i32) { /******/ "__wbindgen_closure_wrapper28": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper115"](p0i32,p1i32,p2i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper28"](p0i32,p1i32,p2i32);
/******/ }, /******/ },
/******/ "__wbindgen_closure_wrapper117": function(p0i32,p1i32,p2i32) { /******/ "__wbindgen_closure_wrapper26": function(p0i32,p1i32,p2i32) {
/******/ return installedModules["../all_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper117"](p0i32,p1i32,p2i32); /******/ return installedModules["../web_pkg/jsonpath_wasm.js"].exports["__wbindgen_closure_wrapper26"](p0i32,p1i32,p2i32);
/******/ } /******/ }
/******/ } /******/ }
/******/ }; /******/ };
@ -161,6 +161,8 @@
/******/ } /******/ }
/******/ script.src = jsonpScriptSrc(chunkId); /******/ script.src = jsonpScriptSrc(chunkId);
/******/ /******/
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ onScriptComplete = function (event) { /******/ onScriptComplete = function (event) {
/******/ // avoid mem leaks in IE. /******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null; /******/ script.onerror = script.onload = null;
@ -170,7 +172,8 @@
/******/ if(chunk) { /******/ if(chunk) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); /******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src; /******/ var realSrc = event && event.target && event.target.src;
/******/ var error = new Error('Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')'); /******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType; /******/ error.type = errorType;
/******/ error.request = realSrc; /******/ error.request = realSrc;
/******/ chunk[1](error); /******/ chunk[1](error);
@ -188,7 +191,7 @@
/******/ /******/
/******/ // Fetch + compile chunk loading for webassembly /******/ // Fetch + compile chunk loading for webassembly
/******/ /******/
/******/ var wasmModules = {"0":["../all_pkg/jsonpath_wasm_bg.wasm"]}[chunkId] || []; /******/ var wasmModules = {"1":["../web_pkg/jsonpath_wasm_bg.wasm"]}[chunkId] || [];
/******/ /******/
/******/ wasmModules.forEach(function(wasmModuleId) { /******/ wasmModules.forEach(function(wasmModuleId) {
/******/ var installedWasmModuleData = installedWasmModules[wasmModuleId]; /******/ var installedWasmModuleData = installedWasmModules[wasmModuleId];
@ -198,7 +201,7 @@
/******/ promises.push(installedWasmModuleData); /******/ promises.push(installedWasmModuleData);
/******/ else { /******/ else {
/******/ var importObject = wasmImportObjects[wasmModuleId](); /******/ var importObject = wasmImportObjects[wasmModuleId]();
/******/ var req = fetch(__webpack_require__.p + "" + {"../all_pkg/jsonpath_wasm_bg.wasm":"33fd09cf53124f20b1e8"}[wasmModuleId] + ".module.wasm"); /******/ var req = fetch(__webpack_require__.p + "" + {"../web_pkg/jsonpath_wasm_bg.wasm":"a9530753c3f0aa3c5ead"}[wasmModuleId] + ".module.wasm");
/******/ var promise; /******/ var promise;
/******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') { /******/ if(importObject instanceof Promise && typeof WebAssembly.compileStreaming === 'function') {
/******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) { /******/ promise = Promise.all([WebAssembly.compileStreaming(req), importObject]).then(function(items) {
@ -299,7 +302,7 @@
/*! no static exports found */ /*! no static exports found */
/***/ (function(module, exports, __webpack_require__) { /***/ (function(module, exports, __webpack_require__) {
eval("// A dependency graph that contains any wasm must all be imported\n// asynchronously. This `bootstrap.js` file does the single async import, so\n// that no one else needs to worry about it again.\n__webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ./index.js */ \"./index.js\"))\n .catch(e => console.error(\"Error importing `index.js`:\", e));\n\n\n//# sourceURL=webpack:///./bootstrap.js?"); eval("// A dependency graph that contains any wasm must all be imported\n// asynchronously. This `bootstrap.js` file does the single async import, so\n// that no one else needs to worry about it again.\nPromise.all(/*! import() */[__webpack_require__.e(0), __webpack_require__.e(1)]).then(__webpack_require__.bind(null, /*! ./index.js */ \"./index.js\"))\n .catch(e => console.error(\"Error importing `index.js`:\", e));\n\n\n//# sourceURL=webpack:///./bootstrap.js?");
/***/ }) /***/ })

View File

@ -305,6 +305,18 @@ pub fn select<'a>(json: &'a Value, path: &str) -> Result<Vec<&'a Value>, JsonPat
Selector::default().str_path(path)?.value(json).select() Selector::default().str_path(path)?.value(json).select()
} }
pub fn select_with_iter<'a>(
json: impl ExactSizeIterator<Item = &'a Value> + 'a,
path: &str,
) -> Result<(Vec<&'a Value>, Vec<usize>), JsonPathError> {
let mut selector = Selector::default();
let json = selector.str_path(path)?.values_iter(json).select()?;
let chose_indices = selector.chose_indices();
Ok((json, chose_indices))
}
/// It is the same to `select` function but it return the result as string. /// It is the same to `select` function but it return the result as string.
/// ///
/// ```rust /// ```rust
@ -377,7 +389,9 @@ pub fn select_as<T: serde::de::DeserializeOwned>(
path: &str, path: &str,
) -> Result<Vec<T>, JsonPathError> { ) -> Result<Vec<T>, JsonPathError> {
let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?; let json = serde_json::from_str(json_str).map_err(|e| JsonPathError::Serde(e.to_string()))?;
Selector::default().str_path(path)?.value(&json).select_as() let t = Selector::default().str_path(path)?.value(&json).select_as();
t
} }
/// Delete(= replace with null) the JSON property using the jsonpath. /// Delete(= replace with null) the JSON property using the jsonpath.

View File

@ -209,7 +209,8 @@ impl Parser {
fn array_keys(tokenizer: &mut TokenReader, first_key: String) -> ParseResult<Node> { fn array_keys(tokenizer: &mut TokenReader, first_key: String) -> ParseResult<Node> {
let mut keys = vec![first_key]; let mut keys = vec![first_key];
while tokenizer.peek_is(COMMA) {
while let Ok(Token::Comma(_)) = tokenizer.peek_token() {
Self::eat_token(tokenizer); Self::eat_token(tokenizer);
Self::eat_whitespace(tokenizer); Self::eat_whitespace(tokenizer);
@ -230,7 +231,7 @@ impl Parser {
debug!("#array_quote_value"); debug!("#array_quote_value");
match tokenizer.next_token() { match tokenizer.next_token() {
Ok(Token::SingleQuoted(_, val)) | Ok(Token::DoubleQuoted(_, val)) => { Ok(Token::SingleQuoted(_, val)) | Ok(Token::DoubleQuoted(_, val)) => {
if tokenizer.peek_is(COMMA) { if let Ok(Token::Comma(_)) = tokenizer.peek_token() {
Self::array_keys(tokenizer, val) Self::array_keys(tokenizer, val)
} else { } else {
Ok(Self::node(ParseToken::Key(val))) Ok(Self::node(ParseToken::Key(val)))
@ -529,41 +530,29 @@ impl Parser {
fn term(tokenizer: &mut TokenReader) -> ParseResult<Node> { fn term(tokenizer: &mut TokenReader) -> ParseResult<Node> {
debug!("#term"); debug!("#term");
if tokenizer.peek_is(AT) { match tokenizer.peek_token() {
Self::eat_token(tokenizer); Ok(Token::At(_)) => {
let node = Self::node(ParseToken::Relative); Self::eat_token(tokenizer);
let node = Self::node(ParseToken::Relative);
return match tokenizer.peek_token() { match tokenizer.peek_token() {
Ok(Token::Whitespace(_, _)) => { Ok(Token::Whitespace(_, _)) => {
Self::eat_whitespace(tokenizer); Self::eat_whitespace(tokenizer);
Ok(node) Ok(node)
}
_ => Self::paths(node, tokenizer),
} }
_ => Self::paths(node, tokenizer), }
}; Ok(Token::Absolute(_)) => Self::json_path(tokenizer),
} Ok(Token::DoubleQuoted(_, _)) | Ok(Token::SingleQuoted(_, _)) => {
Self::array_quote_value(tokenizer)
if tokenizer.peek_is(ABSOLUTE) { }
return Self::json_path(tokenizer); Ok(Token::Key(_, key)) => match key.as_bytes()[0] {
}
if tokenizer.peek_is(DOUBLE_QUOTE) || tokenizer.peek_is(SINGLE_QUOTE) {
return Self::array_quote_value(tokenizer);
}
if tokenizer.peek_is(KEY) {
let key = if let Ok(Token::Key(_, k)) = tokenizer.peek_token() {
k.clone()
} else {
unreachable!()
};
return match key.as_bytes()[0] {
b'-' | b'0'..=b'9' => Self::term_num(tokenizer), b'-' | b'0'..=b'9' => Self::term_num(tokenizer),
_ => Self::boolean(tokenizer), _ => Self::boolean(tokenizer),
}; },
_ => Err(tokenizer.err_msg()),
} }
Err(tokenizer.err_msg())
} }
fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult<Node> { fn op(prev: Node, tokenizer: &mut TokenReader) -> ParseResult<Node> {
@ -610,7 +599,7 @@ impl Parser {
fn close_token(ret: Node, token: Token, tokenizer: &mut TokenReader) -> ParseResult<Node> { fn close_token(ret: Node, token: Token, tokenizer: &mut TokenReader) -> ParseResult<Node> {
debug!("#close_token"); debug!("#close_token");
match tokenizer.next_token() { match tokenizer.next_token() {
Ok(ref t) if t.partial_eq(token) => Ok(ret), Ok(ref t) if t.is_match_token_type(token) => Ok(ret),
_ => Err(tokenizer.err_msg()), _ => Err(tokenizer.err_msg()),
} }
} }
@ -817,6 +806,25 @@ mod parser_tests {
]) ])
); );
assert_eq!(
run("$.$a"),
Ok(vec![
ParseToken::Absolute,
ParseToken::In,
ParseToken::Key("$a".to_owned())
])
);
assert_eq!(
run("$.['$a']"),
Ok(vec![
ParseToken::Absolute,
ParseToken::Array,
ParseToken::Key("$a".to_owned()),
ParseToken::ArrayEof,
])
);
if run("$.").is_ok() { if run("$.").is_ok() {
panic!(); panic!();
} }

View File

@ -2,30 +2,6 @@ use std::result::Result;
use super::path_reader::{PathReader, ReaderError}; use super::path_reader::{PathReader, ReaderError};
pub const ABSOLUTE: &str = "$";
pub const DOT: &str = ".";
pub const AT: &str = "@";
pub const OPEN_ARRAY: &str = "[";
pub const CLOSE_ARRAY: &str = "]";
pub const ASTERISK: &str = "*";
pub const QUESTION: &str = "?";
pub const COMMA: &str = ",";
pub const SPLIT: &str = ":";
pub const OPEN_PARENTHESIS: &str = "(";
pub const CLOSE_PARENTHESIS: &str = ")";
pub const KEY: &str = "Key";
pub const DOUBLE_QUOTE: &str = "\"";
pub const SINGLE_QUOTE: &str = "'";
pub const EQUAL: &str = "==";
pub const GREATER_OR_EQUAL: &str = ">=";
pub const GREATER: &str = ">";
pub const LITTLE: &str = "<";
pub const LITTLE_OR_EQUAL: &str = "<=";
pub const NOT_EQUAL: &str = "!=";
pub const AND: &str = "&&";
pub const OR: &str = "||";
pub const WHITESPACE: &str = " ";
const CH_DOLLA: char = '$'; const CH_DOLLA: char = '$';
const CH_DOT: char = '.'; const CH_DOT: char = '.';
const CH_ASTERISK: char = '*'; const CH_ASTERISK: char = '*';
@ -86,61 +62,104 @@ pub enum Token {
} }
impl Token { impl Token {
pub fn partial_eq(&self, other: Token) -> bool { pub fn is_match_token_type(&self, other: Token) -> bool {
self.to_simple() == other.to_simple()
}
pub fn simple_eq(&self, str_token: &str) -> bool {
self.to_simple() == str_token
}
#[cfg_attr(tarpaulin, skip)]
fn to_simple(&self) -> &'static str {
match self { match self {
Token::Absolute(_) => ABSOLUTE, Token::Absolute(_) => match other {
Token::Dot(_) => DOT, Token::Absolute(_) => true,
Token::At(_) => AT, _ => false,
Token::OpenArray(_) => OPEN_ARRAY, },
Token::CloseArray(_) => CLOSE_ARRAY, Token::Dot(_) => match other {
Token::Asterisk(_) => ASTERISK, Token::Dot(_) => true,
Token::Question(_) => QUESTION, _ => false,
Token::Comma(_) => COMMA, },
Token::Split(_) => SPLIT, Token::At(_) => match other {
Token::OpenParenthesis(_) => OPEN_PARENTHESIS, Token::At(_) => true,
Token::CloseParenthesis(_) => CLOSE_PARENTHESIS, _ => false,
Token::Key(_, _) => KEY, },
Token::DoubleQuoted(_, _) => DOUBLE_QUOTE, Token::OpenArray(_) => match other {
Token::SingleQuoted(_, _) => SINGLE_QUOTE, Token::OpenArray(_) => true,
Token::Equal(_) => EQUAL, _ => false,
Token::GreaterOrEqual(_) => GREATER_OR_EQUAL, },
Token::Greater(_) => GREATER, Token::CloseArray(_) => match other {
Token::Little(_) => LITTLE, Token::CloseArray(_) => true,
Token::LittleOrEqual(_) => LITTLE_OR_EQUAL, _ => false,
Token::NotEqual(_) => NOT_EQUAL, },
Token::And(_) => AND, Token::Asterisk(_) => match other {
Token::Or(_) => OR, Token::Asterisk(_) => true,
Token::Whitespace(_, _) => WHITESPACE, _ => false,
},
Token::Question(_) => match other {
Token::Question(_) => true,
_ => false,
},
Token::Comma(_) => match other {
Token::Comma(_) => true,
_ => false,
},
Token::Split(_) => match other {
Token::Split(_) => true,
_ => false,
},
Token::OpenParenthesis(_) => match other {
Token::OpenParenthesis(_) => true,
_ => false,
},
Token::CloseParenthesis(_) => match other {
Token::CloseParenthesis(_) => true,
_ => false,
},
Token::Key(_, _) => match other {
Token::Key(_, _) => true,
_ => false,
},
Token::DoubleQuoted(_, _) => match other {
Token::DoubleQuoted(_, _) => true,
_ => false,
},
Token::SingleQuoted(_, _) => match other {
Token::SingleQuoted(_, _) => true,
_ => false,
},
Token::Equal(_) => match other {
Token::Equal(_) => true,
_ => false,
},
Token::GreaterOrEqual(_) => match other {
Token::GreaterOrEqual(_) => true,
_ => false,
},
Token::Greater(_) => match other {
Token::Greater(_) => true,
_ => false,
},
Token::Little(_) => match other {
Token::Little(_) => true,
_ => false,
},
Token::LittleOrEqual(_) => match other {
Token::LittleOrEqual(_) => true,
_ => false,
},
Token::NotEqual(_) => match other {
Token::NotEqual(_) => true,
_ => false,
},
Token::And(_) => match other {
Token::And(_) => true,
_ => false,
},
Token::Or(_) => match other {
Token::Or(_) => true,
_ => false,
},
Token::Whitespace(_, _) => match other {
Token::Whitespace(_, _) => true,
_ => false,
},
} }
} }
} }
fn simple_matched_token(ch: char, pos: usize) -> Option<Token> {
match ch {
CH_DOLLA => Some(Token::Absolute(pos)),
CH_DOT => Some(Token::Dot(pos)),
CH_ASTERISK => Some(Token::Asterisk(pos)),
CH_LARRAY => Some(Token::OpenArray(pos)),
CH_RARRAY => Some(Token::CloseArray(pos)),
CH_LPAREN => Some(Token::OpenParenthesis(pos)),
CH_RPAREN => Some(Token::CloseParenthesis(pos)),
CH_AT => Some(Token::At(pos)),
CH_QUESTION => Some(Token::Question(pos)),
CH_COMMA => Some(Token::Comma(pos)),
CH_SEMICOLON => Some(Token::Split(pos)),
_ => None,
}
}
pub struct Tokenizer<'a> { pub struct Tokenizer<'a> {
input: PathReader<'a>, input: PathReader<'a>,
} }
@ -153,6 +172,23 @@ impl<'a> Tokenizer<'a> {
} }
} }
fn dolla(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> {
let fun = |c: &char| match c {
&CH_DOT | &CH_ASTERISK | &CH_LARRAY | &CH_RARRAY | &CH_LPAREN | &CH_RPAREN | &CH_AT
| &CH_QUESTION | &CH_COMMA | &CH_SEMICOLON | &CH_LITTLE | &CH_GREATER | &CH_EQUAL
| &CH_AMPERSAND | &CH_PIPE | &CH_EXCLAMATION => false,
_ => !c.is_whitespace(),
};
let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?;
vec.insert(0, ch);
if vec.len() == 1 {
Ok(Token::Absolute(pos))
} else {
Ok(Token::Key(pos, vec))
}
}
fn quote(&mut self, ch: char) -> Result<String, TokenError> { fn quote(&mut self, ch: char) -> Result<String, TokenError> {
let (_, mut val) = self let (_, mut val) = self
.input .input
@ -261,17 +297,10 @@ impl<'a> Tokenizer<'a> {
} }
fn other(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> { fn other(&mut self, pos: usize, ch: char) -> Result<Token, TokenError> {
let fun = |c: &char| match simple_matched_token(*c, pos) { let fun = |c: &char| match c {
Some(_) => false, &CH_DOLLA | &CH_DOT | &CH_ASTERISK | &CH_LARRAY | &CH_RARRAY | &CH_LPAREN
_ if c == &CH_LITTLE | &CH_RPAREN | &CH_AT | &CH_QUESTION | &CH_COMMA | &CH_SEMICOLON | &CH_LITTLE
|| c == &CH_GREATER | &CH_GREATER | &CH_EQUAL | &CH_AMPERSAND | &CH_PIPE | &CH_EXCLAMATION => false,
|| c == &CH_EQUAL
|| c == &CH_AMPERSAND
|| c == &CH_PIPE
|| c == &CH_EXCLAMATION =>
{
false
}
_ => !c.is_whitespace(), _ => !c.is_whitespace(),
}; };
let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?; let (_, mut vec) = self.input.take_while(fun).map_err(to_token_error)?;
@ -281,20 +310,28 @@ impl<'a> Tokenizer<'a> {
pub fn next_token(&mut self) -> Result<Token, TokenError> { pub fn next_token(&mut self) -> Result<Token, TokenError> {
let (pos, ch) = self.input.next_char().map_err(to_token_error)?; let (pos, ch) = self.input.next_char().map_err(to_token_error)?;
match simple_matched_token(ch, pos) { match ch {
Some(t) => Ok(t), CH_DOLLA => self.dolla(pos, ch),
None => match ch { CH_DOT => Ok(Token::Dot(pos)),
CH_SINGLE_QUOTE => self.single_quote(pos, ch), CH_ASTERISK => Ok(Token::Asterisk(pos)),
CH_DOUBLE_QUOTE => self.double_quote(pos, ch), CH_LARRAY => Ok(Token::OpenArray(pos)),
CH_EQUAL => self.equal(pos, ch), CH_RARRAY => Ok(Token::CloseArray(pos)),
CH_GREATER => self.greater(pos, ch), CH_LPAREN => Ok(Token::OpenParenthesis(pos)),
CH_LITTLE => self.little(pos, ch), CH_RPAREN => Ok(Token::CloseParenthesis(pos)),
CH_AMPERSAND => self.and(pos, ch), CH_AT => Ok(Token::At(pos)),
CH_PIPE => self.or(pos, ch), CH_QUESTION => Ok(Token::Question(pos)),
CH_EXCLAMATION => self.not_equal(pos, ch), CH_COMMA => Ok(Token::Comma(pos)),
_ if ch.is_whitespace() => self.whitespace(pos, ch), CH_SEMICOLON => Ok(Token::Split(pos)),
_ => self.other(pos, ch), CH_SINGLE_QUOTE => self.single_quote(pos, ch),
}, CH_DOUBLE_QUOTE => self.double_quote(pos, ch),
CH_EQUAL => self.equal(pos, ch),
CH_GREATER => self.greater(pos, ch),
CH_LITTLE => self.little(pos, ch),
CH_AMPERSAND => self.and(pos, ch),
CH_PIPE => self.or(pos, ch),
CH_EXCLAMATION => self.not_equal(pos, ch),
_ if ch.is_whitespace() => self.whitespace(pos, ch),
_ => self.other(pos, ch),
} }
} }
@ -333,13 +370,6 @@ impl<'a> TokenReader<'a> {
} }
} }
pub fn peek_is(&self, simple_token: &str) -> bool {
match self.peek_token() {
Ok(t) => t.simple_eq(simple_token),
_ => false,
}
}
pub fn peek_token(&self) -> Result<&Token, TokenError> { pub fn peek_token(&self) -> Result<&Token, TokenError> {
match self.tokens.last() { match self.tokens.last() {
Some((_, t)) => { Some((_, t)) => {

334
src/select/cmp.rs Normal file
View File

@ -0,0 +1,334 @@
use array_tool::vec::{Intersect, Union};
use serde_json::Value;
pub(super) trait Cmp {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool;
fn cmp_f64(&self, v1: f64, v2: f64) -> bool;
fn cmp_string(&self, v1: &str, v2: &str) -> bool;
fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value>;
fn default(&self) -> bool {
false
}
}
pub(super) struct CmpEq;
impl Cmp for CmpEq {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 == v2
}
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
(v1 - v2).abs() == 0_f64
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
v1 == v2
}
fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
v1.to_vec().intersect(v2.to_vec())
}
}
pub(super) struct CmpNe;
impl Cmp for CmpNe {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 != v2
}
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
(v1 - v2).abs() != 0_f64
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
v1 != v2
}
fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
v1.to_vec().intersect_if(v2.to_vec(), |a, b| a != b)
}
}
pub(super) struct CmpGt;
impl Cmp for CmpGt {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 & !v2
}
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
v1 > v2
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
v1 > v2
}
fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
Vec::new()
}
}
pub(super) struct CmpGe;
impl Cmp for CmpGe {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 >= v2
}
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
v1 >= v2
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
v1 >= v2
}
fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
Vec::new()
}
}
pub(super) struct CmpLt;
impl Cmp for CmpLt {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
!v1 & v2
}
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
v1 < v2
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
v1 < v2
}
fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
Vec::new()
}
}
pub(super) struct CmpLe;
impl Cmp for CmpLe {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 <= v2
}
fn cmp_f64(&self, v1: f64, v2: f64) -> bool {
v1 <= v2
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
v1 <= v2
}
fn cmp_json<'a>(&self, _: &[&'a Value], _: &[&'a Value]) -> Vec<&'a Value> {
Vec::new()
}
}
pub(super) struct CmpAnd;
impl Cmp for CmpAnd {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 && v2
}
fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
true
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
!v1.is_empty() && !v2.is_empty()
}
fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
v1.to_vec().intersect(v2.to_vec())
}
}
pub(super) struct CmpOr;
impl Cmp for CmpOr {
fn cmp_bool(&self, v1: bool, v2: bool) -> bool {
v1 || v2
}
fn cmp_f64(&self, _v1: f64, _v2: f64) -> bool {
true
}
fn cmp_string(&self, v1: &str, v2: &str) -> bool {
!v1.is_empty() || !v2.is_empty()
}
fn cmp_json<'a>(&self, v1: &[&'a Value], v2: &[&'a Value]) -> Vec<&'a Value> {
v1.to_vec().union(v2.to_vec())
}
}
#[cfg(test)]
mod cmp_inner_tests {
use serde_json::Value;
use select::cmp::*;
#[test]
fn cmp_eq() {
let cmp_fn = CmpEq;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), false);
assert_eq!(cmp_fn.cmp_bool(true, true), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
assert_eq!(cmp_fn.cmp_string("1", "1"), true);
assert_eq!(cmp_fn.cmp_string("1", "2"), false);
}
#[test]
fn cmp_ne() {
let cmp_fn = CmpNe;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), true);
assert_eq!(cmp_fn.cmp_bool(true, true), false);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
assert_eq!(cmp_fn.cmp_string("1", "1"), false);
assert_eq!(cmp_fn.cmp_string("1", "2"), true);
}
#[test]
fn cmp_gt() {
let cmp_fn = CmpGt;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), true);
assert_eq!(cmp_fn.cmp_bool(true, true), false);
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
assert_eq!(cmp_fn.cmp_string("a", "a"), false);
assert_eq!(cmp_fn.cmp_string("b", "a"), true);
assert_eq!(cmp_fn.cmp_string("1", "2"), false);
}
#[test]
fn cmp_ge() {
let cmp_fn = CmpGe;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), true);
assert_eq!(cmp_fn.cmp_bool(true, true), true);
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), false);
assert_eq!(cmp_fn.cmp_string("1", "1"), true);
assert_eq!(cmp_fn.cmp_string("ab", "a"), true);
assert_eq!(cmp_fn.cmp_string("1", "2"), false);
}
#[test]
fn cmp_lt() {
let cmp_fn = CmpLt;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), false);
assert_eq!(cmp_fn.cmp_bool(false, true), true);
assert_eq!(cmp_fn.cmp_bool(true, true), false);
assert_eq!(cmp_fn.cmp_bool(false, false), false);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), false);
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
assert_eq!(cmp_fn.cmp_string("a", "a"), false);
assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
assert_eq!(cmp_fn.cmp_string("1", "2"), true);
}
#[test]
fn cmp_le() {
let cmp_fn = CmpLe;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), false);
assert_eq!(cmp_fn.cmp_bool(false, true), true);
assert_eq!(cmp_fn.cmp_bool(true, true), true);
assert_eq!(cmp_fn.cmp_bool(false, false), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.2), true);
assert_eq!(cmp_fn.cmp_f64(0.1, 0.1), true);
assert_eq!(cmp_fn.cmp_f64(0.2, 0.1), false);
assert_eq!(cmp_fn.cmp_string("a", "a"), true);
assert_eq!(cmp_fn.cmp_string("ab", "b"), true);
assert_eq!(cmp_fn.cmp_string("abd", "abc"), false);
assert_eq!(cmp_fn.cmp_string("1", "2"), true);
}
#[test]
fn cmp_and() {
let cmp_fn = CmpAnd;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), false);
assert_eq!(cmp_fn.cmp_bool(false, true), false);
assert_eq!(cmp_fn.cmp_bool(true, true), true);
assert_eq!(cmp_fn.cmp_bool(false, false), false);
assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
assert_eq!(cmp_fn.cmp_string("a", "a"), true);
}
#[test]
fn cmp_or() {
let cmp_fn = CmpOr;
assert_eq!(cmp_fn.default(), false);
assert_eq!(cmp_fn.cmp_bool(true, false), true);
assert_eq!(cmp_fn.cmp_bool(false, true), true);
assert_eq!(cmp_fn.cmp_bool(true, true), true);
assert_eq!(cmp_fn.cmp_bool(false, false), false);
assert_eq!(cmp_fn.cmp_f64(0.0, 0.0), true);
assert_eq!(cmp_fn.cmp_string("a", "a"), true);
}
#[test]
fn cmp_json() {
let v1 = Value::Bool(true);
let v2 = Value::String("1".to_string());
let left = [&v1, &v2];
let right = [&v1, &v2];
let empty: Vec<&Value> = Vec::new();
assert_eq!(CmpEq.cmp_json(&left, &right), left.to_vec());
assert_eq!(CmpNe.cmp_json(&left, &right), left.to_vec());
assert_eq!(CmpGt.cmp_json(&left, &right), empty);
assert_eq!(CmpGe.cmp_json(&left, &right), empty);
assert_eq!(CmpLt.cmp_json(&left, &right), empty);
assert_eq!(CmpLe.cmp_json(&left, &right), empty);
assert_eq!(CmpAnd.cmp_json(&left, &right), left.to_vec());
assert_eq!(CmpOr.cmp_json(&left, &right), left.to_vec());
assert_eq!(
CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
vec![&Value::Bool(true)]
);
assert_eq!(
CmpEq.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
empty
);
assert_eq!(
CmpNe.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
empty
);
assert_eq!(
CmpNe.cmp_json(&[&Value::Bool(false)], &[&Value::Bool(true)]),
vec![&Value::Bool(false)]
);
assert_eq!(
CmpAnd.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(true)]),
vec![&Value::Bool(true)]
);
assert_eq!(
CmpOr.cmp_json(&[&Value::Bool(true)], &[&Value::Bool(false)]),
vec![&Value::Bool(true), &Value::Bool(false)]
);
}
}

228
src/select/expr_term.rs Normal file
View File

@ -0,0 +1,228 @@
use select::cmp::*;
use select::{to_f64, FilterKey};
use serde_json::{Number, Value};
// Parsed form of a json path.
#[derive(Debug, PartialEq)]
pub(super) enum ExprTerm<'a> {
String(String),
Number(Number),
Bool(bool),
Json(Option<Vec<&'a Value>>, Option<FilterKey>, Vec<&'a Value>),
}
impl<'a> ExprTerm<'a> {
// tries to match current json path with provided
fn cmp<C1: Cmp, C2: Cmp>(
&self,
other: &Self,
cmp_fn: &C1,
reverse_cmp_fn: &C2,
) -> ExprTerm<'a> {
match &self {
ExprTerm::String(s1) => match &other {
ExprTerm::String(s2) => ExprTerm::Bool(cmp_fn.cmp_string(s1, s2)),
ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
_ => ExprTerm::Bool(cmp_fn.default()),
},
ExprTerm::Number(n1) => match &other {
ExprTerm::Number(n2) => ExprTerm::Bool(cmp_fn.cmp_f64(to_f64(n1), to_f64(n2))),
ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
_ => ExprTerm::Bool(cmp_fn.default()),
},
ExprTerm::Bool(b1) => match &other {
ExprTerm::Bool(b2) => ExprTerm::Bool(cmp_fn.cmp_bool(*b1, *b2)),
ExprTerm::Json(_, _, _) => other.cmp(&self, reverse_cmp_fn, cmp_fn),
_ => ExprTerm::Bool(cmp_fn.default()),
},
ExprTerm::Json(rel, fk1, vec1) => {
let ret: Vec<&Value> = match &other {
ExprTerm::String(s2) => vec1
.iter()
.filter(|v1| match v1 {
Value::String(s1) => cmp_fn.cmp_string(s1, s2),
Value::Object(map1) => {
if let Some(FilterKey::String(k)) = fk1 {
if let Some(Value::String(s1)) = map1.get(k) {
return cmp_fn.cmp_string(s1, s2);
}
}
cmp_fn.default()
}
_ => cmp_fn.default(),
})
.cloned()
.collect(),
ExprTerm::Number(n2) => vec1
.iter()
.filter(|v1| match v1 {
Value::Number(n1) => cmp_fn.cmp_f64(to_f64(n1), to_f64(n2)),
Value::Object(map1) => {
if let Some(FilterKey::String(k)) = fk1 {
if let Some(Value::Number(n1)) = map1.get(k) {
return cmp_fn.cmp_f64(to_f64(n1), to_f64(n2));
}
}
cmp_fn.default()
}
_ => cmp_fn.default(),
})
.cloned()
.collect(),
ExprTerm::Bool(b2) => vec1
.iter()
.filter(|v1| match v1 {
Value::Bool(b1) => cmp_fn.cmp_bool(*b1, *b2),
Value::Object(map1) => {
if let Some(FilterKey::String(k)) = fk1 {
if let Some(Value::Bool(b1)) = map1.get(k) {
return cmp_fn.cmp_bool(*b1, *b2);
}
}
cmp_fn.default()
}
_ => cmp_fn.default(),
})
.cloned()
.collect(),
ExprTerm::Json(parent, _, vec2) => {
if let Some(vec1) = rel {
cmp_fn.cmp_json(vec1, vec2)
} else if let Some(vec2) = parent {
cmp_fn.cmp_json(vec1, vec2)
} else {
cmp_fn.cmp_json(vec1, vec2)
}
}
};
if ret.is_empty() {
ExprTerm::Bool(cmp_fn.default())
} else if let Some(rel) = rel {
if let ExprTerm::Json(_, _, _) = &other {
ExprTerm::Json(Some(rel.to_vec()), None, ret)
} else {
let mut tmp = Vec::new();
for rel_value in rel {
if let Value::Object(map) = rel_value {
for map_value in map.values() {
for result_value in &ret {
if map_value.eq(*result_value) {
tmp.push(*rel_value);
}
}
}
}
}
ExprTerm::Json(Some(tmp), None, ret)
}
} else {
ExprTerm::Json(None, None, ret)
}
}
}
}
pub fn eq(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("eq - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpEq, &CmpEq);
debug!("eq = {:?}", tmp);
*ret = Some(tmp);
}
pub fn ne(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("ne - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpNe, &CmpNe);
debug!("ne = {:?}", tmp);
*ret = Some(tmp);
}
pub fn gt(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("gt - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpGt, &CmpLt);
debug!("gt = {:?}", tmp);
*ret = Some(tmp);
}
pub fn ge(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("ge - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpGe, &CmpLe);
debug!("ge = {:?}", tmp);
*ret = Some(tmp);
}
pub fn lt(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("lt - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpLt, &CmpGt);
debug!("lt = {:?}", tmp);
*ret = Some(tmp);
}
pub fn le(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("le - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpLe, &CmpGe);
debug!("le = {:?}", tmp);
*ret = Some(tmp);
}
pub fn and(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("and - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpAnd, &CmpAnd);
debug!("and = {:?}", tmp);
*ret = Some(tmp);
}
pub fn or(&self, other: &Self, ret: &mut Option<ExprTerm<'a>>) {
debug!("or - {:?} : {:?}", &self, &other);
let _ = ret.take();
let tmp = self.cmp(other, &CmpOr, &CmpOr);
debug!("or = {:?}", tmp);
*ret = Some(tmp);
}
}
impl<'a> Into<ExprTerm<'a>> for &Vec<&'a Value> {
fn into(self) -> ExprTerm<'a> {
if self.len() == 1 {
match &self[0] {
Value::Number(v) => return ExprTerm::Number(v.clone()),
Value::String(v) => return ExprTerm::String(v.clone()),
Value::Bool(v) => return ExprTerm::Bool(*v),
_ => {}
}
}
ExprTerm::Json(None, None, self.to_vec())
}
}
#[cfg(test)]
mod expr_term_inner_tests {
use select::expr_term::ExprTerm;
use serde_json::{Number, Value};
#[test]
fn value_vec_into() {
let v = Value::Bool(true);
let vec = &vec![&v];
let term: ExprTerm = vec.into();
assert_eq!(term, ExprTerm::Bool(true));
let v = Value::String("a".to_string());
let vec = &vec![&v];
let term: ExprTerm = vec.into();
assert_eq!(term, ExprTerm::String("a".to_string()));
let v = serde_json::from_str("1.0").unwrap();
let vec = &vec![&v];
let term: ExprTerm = vec.into();
assert_eq!(term, ExprTerm::Number(Number::from_f64(1.0).unwrap()));
}
}

File diff suppressed because it is too large Load Diff

108
src/select/value_walker.rs Normal file
View File

@ -0,0 +1,108 @@
use serde_json::Value;
use std::collections::HashSet;
pub(super) struct JValueWalker;
impl<'a> JValueWalker {
pub fn all_with_num(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, index: f64) {
Self::walk(vec, tmp, &|v| {
if v.is_array() {
if let Some(item) = v.get(index as usize) {
Some(vec![item])
} else {
None
}
} else {
None
}
});
}
pub fn all_with_str(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) {
if is_filter {
Self::walk(vec, tmp, &|v| match v {
Value::Object(map) if map.contains_key(key) => Some(vec![v]),
_ => None,
});
} else {
Self::walk(vec, tmp, &|v| match v {
Value::Object(map) => match map.get(key) {
Some(v) => Some(vec![v]),
_ => None,
},
_ => None,
});
}
}
pub fn all(vec: &[&'a Value], tmp: &mut Vec<&'a Value>) {
Self::walk(vec, tmp, &|v| match v {
Value::Array(vec) => Some(vec.iter().collect()),
Value::Object(map) => {
let mut tmp = Vec::new();
for (_, v) in map {
tmp.push(v);
}
Some(tmp)
}
_ => None,
});
}
fn walk<F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F)
where
F: Fn(&Value) -> Option<Vec<&Value>>,
{
for v in vec {
Self::_walk(v, tmp, fun);
}
}
fn _walk<F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F)
where
F: Fn(&Value) -> Option<Vec<&Value>>,
{
if let Some(mut ret) = fun(v) {
tmp.append(&mut ret);
}
match v {
Value::Array(vec) => {
for v in vec {
Self::_walk(v, tmp, fun);
}
}
Value::Object(map) => {
for (_, v) in map {
Self::_walk(&v, tmp, fun);
}
}
_ => {}
}
}
pub fn walk_dedup(
v: &'a Value,
tmp: &mut Vec<&'a Value>,
key: &str,
visited: &mut HashSet<*const Value>,
) {
match v {
Value::Object(map) => {
if map.contains_key(key) {
let ptr = v as *const Value;
if !visited.contains(&ptr) {
visited.insert(ptr);
tmp.push(v)
}
}
}
Value::Array(vec) => {
for v in vec {
Self::walk_dedup(v, tmp, key, visited);
}
}
_ => {}
}
}
}

253
tests/array_filter.rs Normal file
View File

@ -0,0 +1,253 @@
#[macro_use]
extern crate serde_json;
use common::{read_json, select_and_then_compare, setup};
mod common;
#[test]
fn array_range_default() {
setup();
select_and_then_compare(
"$.school.friends[1, 2]",
read_json("./benchmark/data_obj.json"),
json!([
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]),
);
}
#[test]
fn array_range_all() {
setup();
select_and_then_compare(
"$[ : ]",
json!(["first", "second"]),
json!(["first", "second"]),
);
}
#[test]
fn array_range_step_all() {
setup();
select_and_then_compare(
"$[::]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "second", "third", "forth", "fifth"]),
);
}
#[test]
fn array_range_step_only_step_value() {
setup();
select_and_then_compare(
"$[::2]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "third", "fifth"]),
);
}
#[test]
fn array_range_step_only_start_index() {
setup();
select_and_then_compare(
"$[1::]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["second", "third", "forth", "fifth"]),
);
}
#[test]
fn array_range_step_empty_step_value() {
setup();
select_and_then_compare(
"$[1:2:]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["second"]),
);
}
#[test]
fn array_range_step_empty_end_index() {
setup();
select_and_then_compare(
"$[1::2]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["second", "forth"]),
);
}
#[test]
fn array_range_step_by_1() {
setup();
select_and_then_compare(
"$[0:3:1]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "second", "third"]),
);
}
#[test]
fn array_range_step_by_2() {
setup();
select_and_then_compare(
"$[0:3:2]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "third"]),
);
}
#[test]
fn array_range_only_negative_index() {
setup();
select_and_then_compare(
"$[-4:]",
json!(["first", "second", "third"]),
json!(["first", "second", "third"]),
);
}
#[test]
fn array_range_only_end_index() {
setup();
select_and_then_compare(
"$[:4]",
json!(["first", "second", "third"]),
json!(["first", "second", "third"]),
);
}
#[test]
fn array_range_only_from_index() {
setup();
select_and_then_compare(
"$.school.friends[1: ]",
read_json("./benchmark/data_obj.json"),
json!([
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]),
);
}
#[test]
fn array_range_only_nagative_end_index() {
setup();
select_and_then_compare(
"$.school.friends[:-2]",
read_json("./benchmark/data_obj.json"),
json!([
{"id": 0, "name": "Millicent Norman"}
]),
);
}
#[test]
fn array_index() {
setup();
select_and_then_compare(
"$..friends[2].name",
read_json("./benchmark/data_obj.json"),
json!(["Gray Berry", "Gray Berry"]),
);
}
#[test]
fn array_all_index() {
setup();
select_and_then_compare(
"$..friends[*].name",
read_json("./benchmark/data_obj.json"),
json!([
"Vincent Cannon",
"Gray Berry",
"Millicent Norman",
"Vincent Cannon",
"Gray Berry"
]),
);
}
#[test]
fn array_all_and_then_key() {
setup();
select_and_then_compare(
"$['school']['friends'][*].['name']",
read_json("./benchmark/data_obj.json"),
json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]),
);
}
#[test]
fn array_index_and_then_key() {
setup();
select_and_then_compare(
"$['school']['friends'][0].['name']",
read_json("./benchmark/data_obj.json"),
json!(["Millicent Norman"]),
);
}
#[test]
fn array_multiple_key() {
setup();
select_and_then_compare(
r#"$.["eyeColor", "name"]"#,
read_json("./benchmark/data_obj.json"),
json!(["blue", "Leonor Herman"]),
);
}
#[test]
fn bugs40_bracket_notation_after_recursive_descent() {
setup();
select_and_then_compare(
"$..[0]",
json!([
"first",
{
"key": [
"first nested",
{
"more": [
{"nested": ["deepest", "second"]},
["more", "values"]
]
}
]
}
]),
json!([
"first",
"first nested",
{
"nested" : [
"deepest",
"second"
]
},
"deepest",
"more"
]),
);
}

View File

@ -1,609 +1,10 @@
#[macro_use] #[macro_use]
extern crate serde_json; extern crate serde_json;
use serde_json::Value;
use common::{read_json, select_and_then_compare, setup}; use common::{read_json, select_and_then_compare, setup};
mod common; mod common;
#[test]
fn array() {
setup();
select_and_then_compare(
"$.school.friends[1, 2]",
read_json("./benchmark/data_obj.json"),
json!([
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]),
);
select_and_then_compare(
"$.school.friends[1: ]",
read_json("./benchmark/data_obj.json"),
json!([
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]),
);
select_and_then_compare(
"$.school.friends[:-2]",
read_json("./benchmark/data_obj.json"),
json!([
{"id": 0, "name": "Millicent Norman"}
]),
);
select_and_then_compare(
"$..friends[2].name",
read_json("./benchmark/data_obj.json"),
json!(["Gray Berry", "Gray Berry"]),
);
select_and_then_compare(
"$..friends[*].name",
read_json("./benchmark/data_obj.json"),
json!([
"Vincent Cannon",
"Gray Berry",
"Millicent Norman",
"Vincent Cannon",
"Gray Berry"
]),
);
select_and_then_compare(
"$['school']['friends'][*].['name']",
read_json("./benchmark/data_obj.json"),
json!(["Millicent Norman", "Vincent Cannon", "Gray Berry"]),
);
select_and_then_compare(
"$['school']['friends'][0].['name']",
read_json("./benchmark/data_obj.json"),
json!(["Millicent Norman"]),
);
select_and_then_compare(
r#"$.["eyeColor", "name"]"#,
read_json("./benchmark/data_obj.json"),
json!(["blue", "Leonor Herman"]),
);
}
#[test]
fn return_type() {
setup();
select_and_then_compare(
"$.school",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
select_and_then_compare(
"$.school[?(@.friends[0])]",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
select_and_then_compare(
"$.school[?(@.friends[10])]",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
select_and_then_compare(
"$.school[?(1==1)]",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
select_and_then_compare(
"$.school.friends[?(1==1)]",
read_json("./benchmark/data_obj.json"),
json!([[
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]]),
);
}
#[test]
fn op_default() {
setup();
// select_and_then_compare(
// "$.school[?(@.friends == @.friends)]",
// read_json("./benchmark/data_obj.json"),
// json!([{
// "friends": [
// {"id": 0, "name": "Millicent Norman"},
// {"id": 1, "name": "Vincent Cannon" },
// {"id": 2, "name": "Gray Berry"}
// ]
// }]),
// );
//
// select_and_then_compare(
// "$.friends[?(@.name)]",
// read_json("./benchmark/data_obj.json"),
// json!([
// { "id" : 1, "name" : "Vincent Cannon" },
// { "id" : 2, "name" : "Gray Berry" }
// ]),
// );
//
// select_and_then_compare(
// "$.friends[?(@.id >= 2)]",
// read_json("./benchmark/data_obj.json"),
// json!([
// { "id" : 2, "name" : "Gray Berry" }
// ]),
// );
//
// select_and_then_compare(
// "$.friends[?(@.id >= 2 || @.id == 1)]",
// read_json("./benchmark/data_obj.json"),
// json!([
// { "id" : 2, "name" : "Gray Berry" },
// { "id" : 1, "name" : "Vincent Cannon" }
// ]),
// );
//
// select_and_then_compare(
// "$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]",
// read_json("./benchmark/data_obj.json"),
// json!([Value::Null]),
// );
//
// select_and_then_compare(
// "$..friends[?(@.id == $.index)].id",
// read_json("./benchmark/data_obj.json"),
// json!([0, 0]),
// );
//
// select_and_then_compare(
// "$..book[?($.store.bicycle.price < @.price)].price",
// read_json("./benchmark/example.json"),
// json!([22.99]),
// );
//
// select_and_then_compare(
// "$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price",
// read_json("./benchmark/example.json"),
// json!([12.99]),
// );
//
// select_and_then_compare(
// "$..[?(@.age > 40)]",
// json!([
// { "name": "이름1", "age": 40, "phone": "+33 12341234" },
// { "name": "이름2", "age": 42, "phone": "++44 12341234" }
// ]),
// json!([
// { "name" : "이름2", "age" : 42, "phone" : "++44 12341234" }
// ]),
// );
select_and_then_compare(
"$..[?(@.age >= 30)]",
json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]}),
json!([
{ "name" : "친구3", "age" : 30 }
]),
);
}
#[test]
fn op_number() {
setup();
select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_string() {
setup();
select_and_then_compare(
r#"$.[?(@.a == "b")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
select_and_then_compare(
r#"$.[?(@.a != "c")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
select_and_then_compare(
r#"$.[?(@.a < "b")]"#,
json!({ "a": "b" }),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a <= "b")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
select_and_then_compare(
r#"$.[?(@.a > "b")]"#,
json!({ "a": "b" }),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a >= "b")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
}
#[test]
fn op_object() {
setup();
select_and_then_compare(
r#"$.[?(@.a == @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}]),
);
select_and_then_compare(
r#"$.[?(@.a != @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a < @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a <= @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a > @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a >= @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([Value::Null]),
);
}
#[test]
fn op_complex() {
setup();
select_and_then_compare(
r#"$.[?(1 == @.a)]"#,
json!({ "a": { "b": 1 } }),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?("1" != @.a)]"#,
json!({ "a": { "b": 1 } }),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a <= 1)]"#,
json!({ "a": { "b": 1 } }),
json!([Value::Null]),
);
select_and_then_compare(
r#"$.[?(@.a > "1")]"#,
json!({ "a": { "b": 1 } }),
json!([Value::Null]),
);
}
#[test]
fn op_compare() {
setup();
for path in [
r#"$[?("1" == 1)]"#,
r#"$[?(1 == "1")]"#,
r#"$[?(true == 1)]"#,
r#"$[?(@ == 1)]"#,
]
.iter()
{
select_and_then_compare(path, json!({}), json!([Value::Null]));
}
}
#[test]
fn example() {
setup();
select_and_then_compare(
r#"$.store.book[*].author"#,
read_json("./benchmark/example.json"),
json!([
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
]),
);
select_and_then_compare(
r#"$..author"#,
read_json("./benchmark/example.json"),
json!([
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
]),
);
select_and_then_compare(
r#"$.store.*"#,
read_json("./benchmark/example.json"),
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},
{"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}
],
{"color" : "red","price" : 19.95},
]),
);
select_and_then_compare(
r#"$.store..price"#,
read_json("./benchmark/example.json"),
json!([8.95, 12.99, 8.99, 22.99, 19.95]),
);
select_and_then_compare(
r#"$..book[2]"#,
read_json("./benchmark/example.json"),
json!([
{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
}
]),
);
select_and_then_compare(
r#"$..book[-2]"#,
read_json("./benchmark/example.json"),
json!([
{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
}
]),
);
select_and_then_compare(
r#"$..book[0, 1]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
select_and_then_compare(
r#"$..book[:2]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
select_and_then_compare(
r#"$..book[2:]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
select_and_then_compare(
r#"$..book[?(@.isbn)]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
select_and_then_compare(
r#"$.store.book[?(@.price < 10)]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
select_and_then_compare(
r#"$..*"#,
read_json("./benchmark/example.json"),
read_json("./benchmark/giveme_every_thing_result.json"),
);
}
#[test]
fn filer_same_obj() {
setup();
select_and_then_compare(
r#"$..[?(@.a == 1)]"#,
json!({
"a": 1,
"b" : {"a": 1},
"c" : {"a": 1}
}),
json!([
{"a": 1},
{"a": 1}
]),
);
}
#[test]
fn range() {
setup();
select_and_then_compare(
"$[ : ]",
json!(["first", "second"]),
json!(["first", "second"]),
);
select_and_then_compare(
"$[::]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "second", "third", "forth", "fifth"]),
);
select_and_then_compare(
"$[::2]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "third", "fifth"]),
);
select_and_then_compare(
"$[1::]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["second", "third", "forth", "fifth"]),
);
select_and_then_compare(
"$[1:2:]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["second"]),
);
select_and_then_compare(
"$[1::2]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["second", "forth"]),
);
select_and_then_compare(
"$[0:3:1]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "second", "third"]),
);
select_and_then_compare(
"$[0:3:2]",
json!(["first", "second", "third", "forth", "fifth"]),
json!(["first", "third"]),
);
}
#[test] #[test]
fn quote() { fn quote() {
setup(); setup();
@ -621,7 +22,7 @@ fn quote() {
} }
#[test] #[test]
fn all_filter() { fn filter_next_all() {
setup(); setup();
for path in &[r#"$.*"#, r#"$[*]"#] { for path in &[r#"$.*"#, r#"$[*]"#] {
@ -631,6 +32,11 @@ fn all_filter() {
json!(["string", 42, { "key": "value" }, [0, 1]]), json!(["string", 42, { "key": "value" }, [0, 1]]),
); );
} }
}
#[test]
fn filter_all() {
setup();
for path in &[r#"$..*"#, r#"$..[*]"#] { for path in &[r#"$..*"#, r#"$..[*]"#] {
select_and_then_compare( select_and_then_compare(
@ -639,6 +45,11 @@ fn all_filter() {
json!([ "string", 42, { "key" : "value" }, [ 0, 1 ], "value", 0, 1 ]), json!([ "string", 42, { "key" : "value" }, [ 0, 1 ], "value", 0, 1 ]),
); );
} }
}
#[test]
fn filter_array_next_all() {
setup();
for path in &[r#"$.*.*"#, r#"$[*].*"#, r#"$.*[*]"#, r#"$[*][*]"#] { for path in &[r#"$.*.*"#, r#"$[*].*"#, r#"$.*[*]"#, r#"$[*][*]"#] {
select_and_then_compare( select_and_then_compare(
@ -647,6 +58,11 @@ fn all_filter() {
json!(["value", 0, 1]), json!(["value", 0, 1]),
); );
} }
}
#[test]
fn filter_all_complex() {
setup();
for path in &[r#"$..friends.*"#, r#"$[*].friends.*"#] { for path in &[r#"$..friends.*"#, r#"$[*].friends.*"#] {
select_and_then_compare( select_and_then_compare(
@ -665,8 +81,9 @@ fn all_filter() {
} }
#[test] #[test]
fn current_path() { fn filter_parent_with_matched_child() {
setup(); setup();
select_and_then_compare( select_and_then_compare(
"$.a[?(@.b.c == 1)]", "$.a[?(@.b.c == 1)]",
json!({ json!({
@ -684,6 +101,11 @@ fn current_path() {
} }
]), ]),
); );
}
#[test]
fn filter_parent_exist_child() {
setup();
select_and_then_compare( select_and_then_compare(
"$.a[?(@.b.c)]", "$.a[?(@.b.c)]",
@ -705,21 +127,37 @@ fn current_path() {
} }
#[test] #[test]
fn bugs33() { fn filter_parent_paths() {
setup();
select_and_then_compare(
"$[?(@.key.subKey == 'subKey2')]",
json!([
{"key": {"seq": 1, "subKey": "subKey1"}},
{"key": {"seq": 2, "subKey": "subKey2"}},
{"key": 42},
{"some": "value"}
]),
json!([{"key": {"seq": 2, "subKey": "subKey2"}}]),
);
}
#[test]
fn bugs33_exist_in_all() {
setup(); setup();
select_and_then_compare( select_and_then_compare(
"$..[?(@.first.second)]", "$..[?(@.first.second)]",
json!({ json!({
"foo": { "foo": {
"first": { "second": "value" } "first": { "second": "value" }
}, },
"foo2": { "foo2": {
"first": {} "first": {}
}, },
"foo3": { "foo3": {
} }
}), }),
json!([ json!([
{ {
"first": { "first": {
@ -728,19 +166,24 @@ fn bugs33() {
} }
]), ]),
); );
}
#[test]
fn bugs33_exist_left_in_all_with_and_condition() {
setup();
select_and_then_compare( select_and_then_compare(
"$..[?(@.first && @.first.second)]", "$..[?(@.first && @.first.second)]",
json!({ json!({
"foo": { "foo": {
"first": { "second": "value" } "first": { "second": "value" }
}, },
"foo2": { "foo2": {
"first": {} "first": {}
}, },
"foo3": { "foo3": {
} }
}), }),
json!([ json!([
{ {
"first": { "first": {
@ -749,6 +192,11 @@ fn bugs33() {
} }
]), ]),
); );
}
#[test]
fn bugs33_exist_right_in_all_with_and_condition() {
setup();
select_and_then_compare( select_and_then_compare(
"$..[?(@.b.c.d && @.b)]", "$..[?(@.b.c.d && @.b)]",
@ -776,3 +224,57 @@ fn bugs33() {
]), ]),
); );
} }
#[test]
fn bugs38_array_notation_in_filter() {
setup();
select_and_then_compare(
"$[?(@['key']==42)]",
json!([
{"key": 0},
{"key": 42},
{"key": -1},
{"key": 41},
{"key": 43},
{"key": 42.0001},
{"key": 41.9999},
{"key": 100},
{"some": "value"}
]),
json!([{"key": 42}]),
);
select_and_then_compare(
"$[?(@['key'].subKey == 'subKey2')]",
json!([
{"key": {"seq": 1, "subKey": "subKey1"}},
{"key": {"seq": 2, "subKey": "subKey2"}},
{"key": 42},
{"some": "value"}
]),
json!([{"key": {"seq": 2, "subKey": "subKey2"}}]),
);
select_and_then_compare(
"$[?(@['key']['subKey'] == 'subKey2')]",
json!([
{"key": {"seq": 1, "subKey": "subKey1"}},
{"key": {"seq": 2, "subKey": "subKey2"}},
{"key": 42},
{"some": "value"}
]),
json!([{"key": {"seq": 2, "subKey": "subKey2"}}]),
);
select_and_then_compare(
"$..key[?(@['subKey'] == 'subKey2')]",
json!([
{"key": {"seq": 1, "subKey": "subKey1"}},
{"key": {"seq": 2, "subKey": "subKey2"}},
{"key": 42},
{"some": "value"}
]),
json!([{"seq": 2, "subKey": "subKey2"}]),
);
}

242
tests/jsonpath_examples.rs Normal file
View File

@ -0,0 +1,242 @@
#[macro_use]
extern crate serde_json;
use common::{read_json, select_and_then_compare, setup};
mod common;
#[test]
fn example_authros_of_all_books() {
setup();
select_and_then_compare(
r#"$.store.book[*].author"#,
read_json("./benchmark/example.json"),
json!([
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
]),
);
}
#[test]
fn all_authors() {
setup();
select_and_then_compare(
r#"$..author"#,
read_json("./benchmark/example.json"),
json!([
"Nigel Rees",
"Evelyn Waugh",
"Herman Melville",
"J. R. R. Tolkien"
]),
);
}
#[test]
fn all_things_both_books_and_bicycles() {
setup();
select_and_then_compare(
r#"$.store.*"#,
read_json("./benchmark/example.json"),
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},
{"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}
],
{"color" : "red","price" : 19.95},
]),
);
}
#[test]
fn the_price_of_everything() {
setup();
select_and_then_compare(
r#"$.store..price"#,
read_json("./benchmark/example.json"),
json!([8.95, 12.99, 8.99, 22.99, 19.95]),
);
}
#[test]
fn the_third_book() {
setup();
select_and_then_compare(
r#"$..book[2]"#,
read_json("./benchmark/example.json"),
json!([
{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
}
]),
);
}
#[test]
fn the_second_to_last_book() {
setup();
select_and_then_compare(
r#"$..book[-2]"#,
read_json("./benchmark/example.json"),
json!([
{
"category" : "fiction",
"author" : "Herman Melville",
"title" : "Moby Dick",
"isbn" : "0-553-21311-3",
"price" : 8.99
}
]),
);
}
#[test]
fn the_first_two_books() {
setup();
select_and_then_compare(
r#"$..book[0, 1]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
}
#[test]
fn all_books_from_index_0_inclusive_until_index_2_exclusive() {
setup();
select_and_then_compare(
r#"$..book[:2]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
}
#[test]
fn all_books_from_index_1_inclusive_until_index_2_exclusive() {
setup();
select_and_then_compare(
r#"$..book[2:]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
}
#[test]
fn all_books_with_an_isbn_number() {
setup();
select_and_then_compare(
r#"$..book[?(@.isbn)]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
}
#[test]
fn all_books_in_store_cheaper_than_10() {
setup();
select_and_then_compare(
r#"$.store.book[?(@.price < 10)]"#,
read_json("./benchmark/example.json"),
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
}
]),
);
}
#[test]
fn give_me_every_thing() {
setup();
select_and_then_compare(
r#"$..*"#,
read_json("./benchmark/example.json"),
read_json("./benchmark/giveme_every_thing_result.json"),
);
}

View File

@ -57,7 +57,7 @@ fn selector() {
{ {
let json = selector(path).unwrap(); let json = selector(path).unwrap();
compare_result(json, target); compare_result(json, target);
}; }
let json_obj = read_json("./benchmark/data_obj.json"); let json_obj = read_json("./benchmark/data_obj.json");
let mut selector = jsonpath::selector(&json_obj); let mut selector = jsonpath::selector(&json_obj);
@ -94,7 +94,7 @@ fn selector_as() {
{ {
let json = selector(path).unwrap(); let json = selector(path).unwrap();
assert_eq!(json, target); assert_eq!(json, target);
}; }
let json_obj = read_json("./benchmark/data_obj.json"); let json_obj = read_json("./benchmark/data_obj.json");
let mut selector = jsonpath::selector_as::<Friend>(&json_obj); let mut selector = jsonpath::selector_as::<Friend>(&json_obj);

365
tests/op.rs Normal file
View File

@ -0,0 +1,365 @@
#[macro_use]
extern crate serde_json;
use common::{read_json, select_and_then_compare, setup};
mod common;
#[test]
fn op_object_eq() {
setup();
select_and_then_compare(
"$.school[?(@.friends == @.friends)]",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
}
#[test]
fn op_object_ge() {
setup();
select_and_then_compare(
"$.friends[?(@.id >= 2)]",
read_json("./benchmark/data_obj.json"),
json!([
{ "id" : 2, "name" : "Gray Berry" }
]),
);
}
#[test]
fn op_object_or_default() {
setup();
select_and_then_compare(
"$.friends[?(@.id >= 2 || @.id == 1)]",
read_json("./benchmark/data_obj.json"),
json!([
{ "id" : 2, "name" : "Gray Berry" },
{ "id" : 1, "name" : "Vincent Cannon" }
]),
);
}
#[test]
fn op_object_and_or() {
setup();
select_and_then_compare(
"$.friends[?( (@.id >= 2 || @.id == 1) && @.id == 0)]",
read_json("./benchmark/data_obj.json"),
json!([]),
);
}
#[test]
fn op_result_type() {
setup();
select_and_then_compare(
"$..friends[?(@.id == $.index)].id",
read_json("./benchmark/data_obj.json"),
json!([0, 0]),
);
}
#[test]
fn op_absolute_path_result_type() {
setup();
select_and_then_compare(
"$..book[?($.store.bicycle.price < @.price)].price",
read_json("./benchmark/example.json"),
json!([22.99]),
);
}
#[test]
fn op_complicated() {
setup();
select_and_then_compare(
"$..book[?( (@.price == 12.99 || @.category == 'reference') && @.price > 10)].price",
read_json("./benchmark/example.json"),
json!([12.99]),
);
}
#[test]
fn op_gt() {
setup();
select_and_then_compare(
"$..[?(@.age > 40)]",
json!([
{ "name": "이름1", "age": 40, "phone": "+33 12341234" },
{ "name": "이름2", "age": 42, "phone": "++44 12341234" }
]),
json!([
{ "name" : "이름2", "age" : 42, "phone" : "++44 12341234" }
]),
);
}
#[test]
fn op_ge() {
setup();
select_and_then_compare(
"$..[?(@.age >= 30)]",
json!({
"school": {
"friends": [
{"name": "친구1", "age": 20},
{"name": "친구2", "age": 20}
]
},
"friends": [
{"name": "친구3", "age": 30},
{"name": "친구4"}
]}),
json!([
{ "name" : "친구3", "age" : 30 }
]),
);
}
#[test]
fn op_eq_for_number() {
setup();
select_and_then_compare("$.[?(@.a == 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_ne_for_number() {
setup();
select_and_then_compare("$.[?(@.a != 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_lt_for_number() {
setup();
select_and_then_compare("$.[?(@.a < 2)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_le_for_number() {
setup();
select_and_then_compare("$.[?(@.a <= 1)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_gt_for_number() {
setup();
select_and_then_compare("$.[?(@.a > 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_ge_for_number() {
setup();
select_and_then_compare("$.[?(@.a >= 0)]", json!({ "a": 1 }), json!([{ "a": 1 }]));
}
#[test]
fn op_eq_for_string_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a == "b")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
}
#[test]
fn op_ne_for_string_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a != "c")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
}
#[test]
fn op_lt_for_string_value() {
setup();
select_and_then_compare(r#"$.[?(@.a < "b")]"#, json!({ "a": "b" }), json!([]));
}
#[test]
fn op_le_for_string_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a <= "b")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
}
#[test]
fn op_gt_for_string_value() {
setup();
select_and_then_compare(r#"$.[?(@.a > "b")]"#, json!({ "a": "b" }), json!([]));
}
#[test]
fn op_ge_for_string_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a >= "b")]"#,
json!({ "a": "b" }),
json!([{ "a": "b" }]),
);
}
#[test]
fn op_eq_for_object_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a == @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([{"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}]),
);
}
#[test]
fn op_ne_for_object_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a != @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([]),
);
}
#[test]
fn op_lt_for_object_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a < @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([]),
);
}
#[test]
fn op_le_for_object_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a <= @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([]),
);
}
#[test]
fn op_gt_for_object_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a > @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([]),
);
}
#[test]
fn op_ge_for_object_value() {
setup();
select_and_then_compare(
r#"$.[?(@.a >= @.c)]"#,
json!({"a": { "1": 1 }, "b": { "2": 2 }, "c": { "1": 1 }}),
json!([]),
);
}
#[test]
fn op_eq_for_complex_value() {
setup();
select_and_then_compare(r#"$.[?(1 == @.a)]"#, json!({ "a": { "b": 1 } }), json!([]));
}
#[test]
fn op_ne_for_complex_value() {
setup();
select_and_then_compare(
r#"$.[?("1" != @.a)]"#,
json!({ "a": { "b": 1 } }),
json!([]),
);
}
#[test]
fn op_le_for_complex_value() {
setup();
select_and_then_compare(r#"$.[?(@.a <= 1)]"#, json!({ "a": { "b": 1 } }), json!([]));
}
#[test]
fn op_gt_for_complex_value() {
setup();
select_and_then_compare(r#"$.[?(@.a > "1")]"#, json!({ "a": { "b": 1 } }), json!([]));
}
#[test]
fn op_compare_different_types() {
setup();
for path in [
r#"$[?("1" == 1)]"#,
r#"$[?(1 == "1")]"#,
r#"$[?(true == 1)]"#,
r#"$[?(@ == 1)]"#,
]
.iter()
{
select_and_then_compare(path, json!({}), json!([]));
}
}
#[test]
fn op_for_same_type() {
setup();
select_and_then_compare(
r#"$..[?(@.a == 1)]"#,
json!({
"a": 1,
"b" : {"a": 1},
"c" : {"a": 1}
}),
json!([
{"a": 1},
{"a": 1}
]),
);
}

115
tests/paths.rs Normal file
View File

@ -0,0 +1,115 @@
#[macro_use]
extern crate serde_json;
use common::{select_and_then_compare, setup};
mod common;
#[test]
fn dolla_token_in_path() {
setup();
select_and_then_compare(
"$..$ref",
json!({
"Junk1": "This is a test to illustrate use of '$' in the attr for the expression $..['$ref'] ",
"$ref": "Match Root",
"Subset1":[
{"Junk2": "Data...",
"$ref": "Match Subset1"
}
],
"hierachy1":{
"hierachy2.1":{
"hierachy2.1.1":{ "$ref":"Match 2.1.1"},
"hierachy2.1.2":{ "ref":"Match 2.1.2"},
"hierachy2.1.3":{ "ref":"No Match 2.1.3"},
"hierachy2.1.4":{ "$ref":"Match 2.1.4"},
"hierachy2.1.5":{ "ref":"No Match 2.1.5"}
},
"hierachy2.2":{
"hierachy2.2.1":{ "ref":"No Match 2.2.1"},
"hierachy2.2.2":{ "$ref":"Match 2.2.2"},
"hierachy2.2.3":{ "ref":"No Match 2.2.3"},
"hierachy2.2.4":{ "ref":"No Match 2.2.5"},
"hierachy2.2.5":{ "$ref":"Match 2.2.5"}
},
"hierachy2.3":{
"hierachy2.3.1":{ "ref":"No Match 2.3.1"},
"hierachy2.3.2":{ "ref":"No Match 2.3.2"},
"hierachy2.3.3":{ "ref":"No Match 2.3.3"},
"hierachy2.3.4":{ "ref":"No Match 2.3.4"},
"hierachy2.3.5":{ "ref":"No Match 2.3.5"},
"hierachy2.3.6":{
"hierachy2.3.6.1":{ "$ref":"Match 2.3.6.1"},
"hierachy2.3.6.2":{ "ref":"No Match 2.3.6.2"},
"hierachy2.3.6.3":{ "ref":"No Match 2.3.6.3"},
"hierachy2.3.6.4":{ "ref":"No Match 2.3.6.4"},
"hierachy2.3.6.5":{ "ref":"No Match 2.3.6.5"}
}
}
}
}),
json!([
"Match Root",
"Match Subset1",
"Match 2.1.1",
"Match 2.1.4",
"Match 2.2.2",
"Match 2.2.5",
"Match 2.3.6.1"
]),
);
select_and_then_compare(
"$..['$ref']",
json!({
"Junk1": "This is a test to illustrate use of '$' in the attr for the expression $..['$ref'] ",
"$ref": "Match Root",
"Subset1":[
{"Junk2": "Data...",
"$ref": "Match Subset1"
}
],
"hierachy1":{
"hierachy2.1":{
"hierachy2.1.1":{ "$ref":"Match 2.1.1"},
"hierachy2.1.2":{ "ref":"Match 2.1.2"},
"hierachy2.1.3":{ "ref":"No Match 2.1.3"},
"hierachy2.1.4":{ "$ref":"Match 2.1.4"},
"hierachy2.1.5":{ "ref":"No Match 2.1.5"}
},
"hierachy2.2":{
"hierachy2.2.1":{ "ref":"No Match 2.2.1"},
"hierachy2.2.2":{ "$ref":"Match 2.2.2"},
"hierachy2.2.3":{ "ref":"No Match 2.2.3"},
"hierachy2.2.4":{ "ref":"No Match 2.2.5"},
"hierachy2.2.5":{ "$ref":"Match 2.2.5"}
},
"hierachy2.3":{
"hierachy2.3.1":{ "ref":"No Match 2.3.1"},
"hierachy2.3.2":{ "ref":"No Match 2.3.2"},
"hierachy2.3.3":{ "ref":"No Match 2.3.3"},
"hierachy2.3.4":{ "ref":"No Match 2.3.4"},
"hierachy2.3.5":{ "ref":"No Match 2.3.5"},
"hierachy2.3.6":{
"hierachy2.3.6.1":{ "$ref":"Match 2.3.6.1"},
"hierachy2.3.6.2":{ "ref":"No Match 2.3.6.2"},
"hierachy2.3.6.3":{ "ref":"No Match 2.3.6.3"},
"hierachy2.3.6.4":{ "ref":"No Match 2.3.6.4"},
"hierachy2.3.6.5":{ "ref":"No Match 2.3.6.5"}
}
}
}
}),
json!([
"Match Root",
"Match Subset1",
"Match 2.1.1",
"Match 2.1.4",
"Match 2.2.2",
"Match 2.2.5",
"Match 2.3.6.1"
]),
);
}

105
tests/return_type.rs Normal file
View File

@ -0,0 +1,105 @@
#[macro_use]
extern crate serde_json;
use common::{read_json, select_and_then_compare, setup};
mod common;
#[test]
fn return_type_for_single_object() {
setup();
select_and_then_compare(
"$.school",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
}
#[test]
fn return_type_for_single_object_key_matched() {
setup();
select_and_then_compare(
"$.friends[?(@.name)]",
read_json("./benchmark/data_obj.json"),
json!([
{ "id" : 1, "name" : "Vincent Cannon" },
{ "id" : 2, "name" : "Gray Berry" }
]),
);
}
#[test]
fn return_type_for_child_object_matched() {
setup();
select_and_then_compare(
"$.school[?(@.friends[0])]",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
}
#[test]
#[ignore]
fn return_type_for_child_object_not_matched() {
setup();
select_and_then_compare(
"$.school[?(@.friends[10])]",
read_json("./benchmark/data_obj.json"),
json!([]),
);
}
#[test]
fn return_type_for_object_filter_true() {
setup();
select_and_then_compare(
"$.school[?(1==1)]",
read_json("./benchmark/data_obj.json"),
json!([{
"friends": [
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]
}]),
);
}
#[test]
fn return_type_for_array_filter_true() {
setup();
select_and_then_compare(
"$.school.friends[?(1==1)]",
read_json("./benchmark/data_obj.json"),
json!([[
{"id": 0, "name": "Millicent Norman"},
{"id": 1, "name": "Vincent Cannon" },
{"id": 2, "name": "Gray Berry"}
]]),
);
}
#[test]
fn return_type_empty() {
setup();
select_and_then_compare("$[?(@.key==43)]", json!([{"key": 42}]), json!([]));
}

View File

@ -120,12 +120,81 @@ fn selector_remove() {
.select() .select()
.unwrap(); .unwrap();
assert_eq!( assert_eq!(result, vec![&json!(8.95), &json!(12.99), &json!(8.99)]);
result, }
vec![
&json!(8.95), #[test]
&json!(12.99), fn iter_test() {
&json!(8.99) use std::rc::Rc;
]
); struct T {
pub value: Rc<Value>,
pub tt: i32,
}
let t = Value::Array(vec![
Value::String(String::from("vv")),
Value::Array(vec![]),
]);
let t1 = T {
value: Rc::new(t.clone()),
tt: 1,
};
let t2 = T {
value: Rc::new(t.clone()),
tt: 1,
};
let values = vec![t1, t2];
let mut selector = Selector::default();
let path = "$.[0]";
let result = selector
.str_path(path)
.unwrap()
.values_iter(values.iter().map(|v| v.value.as_ref()))
.select()
.unwrap();
assert_eq!(result, vec![&json!(["vv", []])]);
let result = jsonpath::select_with_iter(values.iter().map(|v| v.value.as_ref()), path).unwrap();
assert_eq!(result.0, vec![&json!(["vv", []])]);
assert_eq!(result.1, vec![0]);
let values = vec![json!([1, 2, 3, 4]), json!([2, 2]), json!(3)];
let mut selector = Selector::default();
let result = selector
.str_path(path)
.unwrap()
.values_iter(values.iter())
.select()
.unwrap();
assert_eq!(result, vec![&json!([1, 2, 3, 4])]);
}
#[test]
fn test_not_found_by_index() {
let array = vec![1, 2, 3, 4, 5];
let haystack = json!(array);
let result = jsonpath::select(&haystack, "$.[4]").unwrap();
assert_eq!(result, vec![5]);
let result = jsonpath::select(&haystack, "$.[5]");
assert!(result.is_err());
}
#[test]
fn test_not_found_by_key() {
let haystack = json!({"asd": 1});
let result = jsonpath::select(&haystack, "$.asd").unwrap();
assert_eq!(result, vec![1]);
let result = jsonpath::select(&haystack, "$.aaa");
assert!(result.is_err());
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "jsonpath-wasm" name = "jsonpath-wasm"
version = "0.2.4" version = "0.2.5"
authors = ["Changseok Han <freestrings@gmail.com>"] authors = ["Changseok Han <freestrings@gmail.com>"]
description = "It is Webassembly version of jsonpath_lib that is JsonPath engine written in Rust - Demo: https://freestrings.github.io/jsonpath" description = "It is Webassembly version of jsonpath_lib that is JsonPath engine written in Rust - Demo: https://freestrings.github.io/jsonpath"
keywords = ["jsonpath", "json", "webassembly", "parsing", "rust"] keywords = ["jsonpath", "json", "webassembly", "parsing", "rust"]

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +0,0 @@
{
"name": "jsonpath-wasm-nodejs-example",
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"jsonpath-wasm": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/jsonpath-wasm/-/jsonpath-wasm-0.2.4.tgz",
"integrity": "sha512-sxvPEFMpAoNjxUQOkJmVyE3dKX7v4ebX5TkWKguyHteZpHJKlMQbgPKFYL0X3SIU7wAstpOl6hVODLThVmJf1w=="
}
}
}

View File

@ -0,0 +1,15 @@
events { }
http {
include mime.types;
types {
application/wasm wasm;
}
server {
listen 80;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html =404;
}
}
}

6
wasm/nginx_conf/run.sh Executable file
View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
docker run -it --rm -p 8000:80 \
-v $(pwd)/../../docs:/usr/share/nginx/html \
-v $(pwd)/nginx.conf:/etc/nginx/nginx.conf \
nginx

View File

@ -85,22 +85,44 @@
} }
}, },
"cliui": { "cliui": {
"version": "4.1.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true, "dev": true,
"requires": { "requires": {
"string-width": "^2.1.1", "string-width": "^3.1.0",
"strip-ansi": "^4.0.0", "strip-ansi": "^5.2.0",
"wrap-ansi": "^2.0.0" "wrap-ansi": "^5.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
}
} }
}, },
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
"dev": true
},
"color-convert": { "color-convert": {
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@ -122,19 +144,6 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true "dev": true
}, },
"cross-spawn": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"dev": true,
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"debug": { "debug": {
"version": "3.2.6", "version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
@ -171,33 +180,29 @@
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true "dev": true
}, },
"end-of-stream": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
"integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
"dev": true,
"requires": {
"once": "^1.4.0"
}
},
"es-abstract": { "es-abstract": {
"version": "1.13.0", "version": "1.17.5",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
"dev": true, "dev": true,
"requires": { "requires": {
"es-to-primitive": "^1.2.0", "es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"has": "^1.0.3", "has": "^1.0.3",
"is-callable": "^1.1.4", "has-symbols": "^1.0.1",
"is-regex": "^1.0.4", "is-callable": "^1.1.5",
"object-keys": "^1.0.12" "is-regex": "^1.0.5",
"object-inspect": "^1.7.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.0",
"string.prototype.trimleft": "^2.1.1",
"string.prototype.trimright": "^2.1.1"
} }
}, },
"es-to-primitive": { "es-to-primitive": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"dev": true, "dev": true,
"requires": { "requires": {
"is-callable": "^1.1.4", "is-callable": "^1.1.4",
@ -217,21 +222,6 @@
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true "dev": true
}, },
"execa": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
"dev": true,
"requires": {
"cross-spawn": "^6.0.0",
"get-stream": "^4.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
}
},
"find-up": { "find-up": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
@ -268,15 +258,6 @@
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true "dev": true
}, },
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"dev": true,
"requires": {
"pump": "^3.0.0"
}
},
"glob": { "glob": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
@ -313,9 +294,9 @@
"dev": true "dev": true
}, },
"has-symbols": { "has-symbols": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
"dev": true "dev": true
}, },
"he": { "he": {
@ -335,33 +316,27 @@
} }
}, },
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"invert-kv": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
"dev": true "dev": true
}, },
"is-buffer": { "is-buffer": {
"version": "2.0.3", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz",
"integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==",
"dev": true "dev": true
}, },
"is-callable": { "is-callable": {
"version": "1.1.4", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==",
"dev": true "dev": true
}, },
"is-date-object": { "is-date-object": {
"version": "1.0.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
"dev": true "dev": true
}, },
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
@ -371,27 +346,21 @@
"dev": true "dev": true
}, },
"is-regex": { "is-regex": {
"version": "1.0.4", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"has": "^1.0.1" "has": "^1.0.3"
} }
}, },
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
"dev": true
},
"is-symbol": { "is-symbol": {
"version": "1.0.2", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"has-symbols": "^1.0.0" "has-symbols": "^1.0.1"
} }
}, },
"isexe": { "isexe": {
@ -411,20 +380,9 @@
} }
}, },
"jsonpath-wasm": { "jsonpath-wasm": {
"version": "0.1.3", "version": "file:../nodejs_pkg",
"resolved": "https://registry.npmjs.org/jsonpath-wasm/-/jsonpath-wasm-0.1.3.tgz",
"integrity": "sha512-c9A8bxQSzHWu52KPDSWjW9MxdhVOZ8J8Gpi3TjD5H4XMcpiGtDNi6Pm9gYb+TgcRynA6hHD5YTmRfaN6vTiSLg==",
"dev": true "dev": true
}, },
"lcid": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
"dev": true,
"requires": {
"invert-kv": "^2.0.0"
}
},
"locate-path": { "locate-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
@ -436,9 +394,9 @@
} }
}, },
"lodash": { "lodash": {
"version": "4.17.14", "version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==", "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true "dev": true
}, },
"log-symbols": { "log-symbols": {
@ -450,32 +408,6 @@
"chalk": "^2.0.1" "chalk": "^2.0.1"
} }
}, },
"map-age-cleaner": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
"dev": true,
"requires": {
"p-defer": "^1.0.0"
}
},
"mem": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
"integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
"dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^2.0.0",
"p-is-promise": "^2.0.0"
}
},
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@ -486,24 +418,24 @@
} }
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true "dev": true
}, },
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"dev": true, "dev": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "^1.2.5"
} }
}, },
"mocha": { "mocha": {
"version": "6.1.4", "version": "6.2.3",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.3.tgz",
"integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", "integrity": "sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-colors": "3.2.3", "ansi-colors": "3.2.3",
@ -518,7 +450,7 @@
"js-yaml": "3.13.1", "js-yaml": "3.13.1",
"log-symbols": "2.2.0", "log-symbols": "2.2.0",
"minimatch": "3.0.4", "minimatch": "3.0.4",
"mkdirp": "0.5.1", "mkdirp": "0.5.4",
"ms": "2.1.1", "ms": "2.1.1",
"node-environment-flags": "1.0.5", "node-environment-flags": "1.0.5",
"object.assign": "4.1.0", "object.assign": "4.1.0",
@ -526,9 +458,9 @@
"supports-color": "6.0.0", "supports-color": "6.0.0",
"which": "1.3.1", "which": "1.3.1",
"wide-align": "1.1.3", "wide-align": "1.1.3",
"yargs": "13.2.2", "yargs": "13.3.2",
"yargs-parser": "13.0.0", "yargs-parser": "13.1.2",
"yargs-unparser": "1.5.0" "yargs-unparser": "1.6.0"
} }
}, },
"ms": { "ms": {
@ -537,12 +469,6 @@
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true "dev": true
}, },
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node-environment-flags": { "node-environment-flags": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz",
@ -553,19 +479,10 @@
"semver": "^5.7.0" "semver": "^5.7.0"
} }
}, },
"npm-run-path": { "object-inspect": {
"version": "2.0.2", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==",
"dev": true,
"requires": {
"path-key": "^2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
"dev": true "dev": true
}, },
"object-keys": { "object-keys": {
@ -587,13 +504,13 @@
} }
}, },
"object.getownpropertydescriptors": { "object.getownpropertydescriptors": {
"version": "2.0.3", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
"dev": true, "dev": true,
"requires": { "requires": {
"define-properties": "^1.1.2", "define-properties": "^1.1.3",
"es-abstract": "^1.5.1" "es-abstract": "^1.17.0-next.1"
} }
}, },
"once": { "once": {
@ -605,39 +522,10 @@
"wrappy": "1" "wrappy": "1"
} }
}, },
"os-locale": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
"dev": true,
"requires": {
"execa": "^1.0.0",
"lcid": "^2.0.0",
"mem": "^4.0.0"
}
},
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
"dev": true
},
"p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
"dev": true
},
"p-is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
"integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
"dev": true
},
"p-limit": { "p-limit": {
"version": "2.2.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true, "dev": true,
"requires": { "requires": {
"p-try": "^2.0.0" "p-try": "^2.0.0"
@ -670,22 +558,6 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true "dev": true
}, },
"path-key": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
"dev": true
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dev": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"require-directory": { "require-directory": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@ -699,9 +571,9 @@
"dev": true "dev": true
}, },
"semver": { "semver": {
"version": "5.7.0", "version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true "dev": true
}, },
"set-blocking": { "set-blocking": {
@ -710,27 +582,6 @@
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true "dev": true
}, },
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
"dev": true,
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
"dev": true
},
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
"dev": true
},
"sprintf-js": { "sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -747,6 +598,48 @@
"strip-ansi": "^4.0.0" "strip-ansi": "^4.0.0"
} }
}, },
"string.prototype.trimend": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
}
},
"string.prototype.trimleft": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
"integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5",
"string.prototype.trimstart": "^1.0.0"
}
},
"string.prototype.trimright": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
"integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5",
"string.prototype.trimend": "^1.0.0"
}
},
"string.prototype.trimstart": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
"dev": true,
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
}
},
"strip-ansi": { "strip-ansi": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
@ -756,12 +649,6 @@
"ansi-regex": "^3.0.0" "ansi-regex": "^3.0.0"
} }
}, },
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"strip-json-comments": { "strip-json-comments": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
@ -802,48 +689,40 @@
} }
}, },
"wrap-ansi": { "wrap-ansi": {
"version": "2.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"string-width": "^1.0.1", "ansi-styles": "^3.2.0",
"strip-ansi": "^3.0.1" "string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}, },
"dependencies": { "dependencies": {
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true "dev": true
}, },
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"string-width": { "string-width": {
"version": "1.0.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true, "dev": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^3.0.0" "strip-ansi": "^5.1.0"
} }
}, },
"strip-ansi": { "strip-ansi": {
"version": "3.0.1", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^4.1.0"
} }
} }
} }
@ -861,22 +740,21 @@
"dev": true "dev": true
}, },
"yargs": { "yargs": {
"version": "13.2.2", "version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"dev": true, "dev": true,
"requires": { "requires": {
"cliui": "^4.0.0", "cliui": "^5.0.0",
"find-up": "^3.0.0", "find-up": "^3.0.0",
"get-caller-file": "^2.0.1", "get-caller-file": "^2.0.1",
"os-locale": "^3.1.0",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"require-main-filename": "^2.0.0", "require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0", "set-blocking": "^2.0.0",
"string-width": "^3.0.0", "string-width": "^3.0.0",
"which-module": "^2.0.0", "which-module": "^2.0.0",
"y18n": "^4.0.0", "y18n": "^4.0.0",
"yargs-parser": "^13.0.0" "yargs-parser": "^13.1.2"
}, },
"dependencies": { "dependencies": {
"ansi-regex": { "ansi-regex": {
@ -908,9 +786,9 @@
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "13.0.0", "version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true, "dev": true,
"requires": { "requires": {
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
@ -918,58 +796,14 @@
} }
}, },
"yargs-unparser": { "yargs-unparser": {
"version": "1.5.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz",
"integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==",
"dev": true, "dev": true,
"requires": { "requires": {
"flat": "^4.1.0", "flat": "^4.1.0",
"lodash": "^4.17.11", "lodash": "^4.17.15",
"yargs": "^12.0.5" "yargs": "^13.3.0"
},
"dependencies": {
"get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
"dev": true
},
"require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"yargs": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
"dev": true,
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.2.0",
"find-up": "^3.0.0",
"get-caller-file": "^1.0.1",
"os-locale": "^3.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1 || ^4.0.0",
"yargs-parser": "^11.1.1"
}
},
"yargs-parser": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
} }
} }
} }

View File

@ -8,7 +8,7 @@
"test": "mocha" "test": "mocha"
}, },
"devDependencies": { "devDependencies": {
"jsonpath-wasm": "*", "jsonpath-wasm": "file:../nodejs_pkg",
"mocha": "^6.1.4" "mocha": "^6.1.4"
} }
} }

View File

@ -935,4 +935,70 @@ describe('ISSUE test', () => {
done(); done();
}); });
it('Failure to match "$..[\'$ref\']", "$..[\'ref\']", but succeeds on "$..ref" #43', (done) => {
function select(json, expected, paths) {
for (var i = 0 ; i < paths.length ; i++) {
let result = jsonpath.select(json, paths[i]);
if (JSON.stringify(result) !== JSON.stringify(expected)) {
throw Error("Error: " + paths[i] + ", " + result);
}
}
}
select(
{
"Junk1": "This is a test to illustrate use of '$' in the attr for the expression $..['$ref'] ",
"$ref": "Match Root",
"Subset1":[
{"Junk2": "Data...",
"$ref": "Match Subset1"
}
],
"hierachy1":{
"hierachy2.1":{
"hierachy2.1.1":{ "$ref":"Match 2.1.1"},
"hierachy2.1.2":{ "ref":"Match 2.1.2"},
"hierachy2.1.3":{ "ref":"No Match 2.1.3"},
"hierachy2.1.4":{ "$ref":"Match 2.1.4"},
"hierachy2.1.5":{ "ref":"No Match 2.1.5"}
},
"hierachy2.2":{
"hierachy2.2.1":{ "ref":"No Match 2.2.1"},
"hierachy2.2.2":{ "$ref":"Match 2.2.2"},
"hierachy2.2.3":{ "ref":"No Match 2.2.3"},
"hierachy2.2.4":{ "ref":"No Match 2.2.5"},
"hierachy2.2.5":{ "$ref":"Match 2.2.5"}
},
"hierachy2.3":{
"hierachy2.3.1":{ "ref":"No Match 2.3.1"},
"hierachy2.3.2":{ "ref":"No Match 2.3.2"},
"hierachy2.3.3":{ "ref":"No Match 2.3.3"},
"hierachy2.3.4":{ "ref":"No Match 2.3.4"},
"hierachy2.3.5":{ "ref":"No Match 2.3.5"},
"hierachy2.3.6":{
"hierachy2.3.6.1":{ "$ref":"Match 2.3.6.1"},
"hierachy2.3.6.2":{ "ref":"No Match 2.3.6.2"},
"hierachy2.3.6.3":{ "ref":"No Match 2.3.6.3"},
"hierachy2.3.6.4":{ "ref":"No Match 2.3.6.4"},
"hierachy2.3.6.5":{ "ref":"No Match 2.3.6.5"}
}
}
}
},
[
"Match Root",
"Match Subset1",
"Match 2.1.1",
"Match 2.1.4",
"Match 2.2.2",
"Match 2.2.5",
"Match 2.3.6.1"
],
["$..$ref", "$..['$ref']"]
);
done();
});
}); });

View File

@ -53,9 +53,16 @@ function initEvent() {
} }
} }
function readPath() {
let query = location.href.substring(location.href.indexOf('#') + 1);
let path = decodeURIComponent(query);
getJsonpathInput().value = path;
forceClick(getReadBtn());
}
function readPathParam() { function readPathParam() {
if(location.href.indexOf('#') > -1) { if(location.href.indexOf('#') > -1) {
readPath() readPath();
} }
} }
@ -67,13 +74,6 @@ function forceClick(ctrl) {
ctrl.dispatchEvent(event, true); ctrl.dispatchEvent(event, true);
} }
function readPath() {
let query = location.href.substring(location.href.indexOf('#') + 1);
let path = decodeURIComponent(query);
getJsonpathInput().value = path;
forceClick(getReadBtn());
}
window.onpopstate = readPath; window.onpopstate = readPath;
initData('data/example.json').then(initEvent).then(readPathParam); initData('data/example.json').then(initEvent).then(readPathParam);

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
{ {
"name": "jsonpath-wasm-evaluator", "name": "jsonpath-wasm-evaluator",
"version": "0.2.0", "version": "0.1.0",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "webpack --config webpack.config.js", "build": "webpack --config webpack.config.js",
"start": "webpack-dev-server" "start": "webpack-dev-server"
}, },
"devDependencies": { "devDependencies": {
"copy-webpack-plugin": "^5.0.1", "copy-webpack-plugin": "^5.1.1",
"webpack": "^4.29.6", "webpack": "^4.29.6",
"webpack-cli": "^3.3.0", "webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.2.1" "webpack-dev-server": "^3.2.1"

View File

@ -1,6 +1,13 @@
import * as jpw from "jsonpath-wasm"; import * as jpw from "jsonpath-wasm";
import * as jp from "jsonpath/jsonpath.js"; import * as jp from "jsonpath/jsonpath.js";
function msg(msg) {
console.log(msg);
let div = document.createElement("div");
div.innerText = msg;
document.body.appendChild(div);
}
function run(message, iter, cb) { function run(message, iter, cb) {
return new Promise(function(resolve, _reject) { return new Promise(function(resolve, _reject) {
let d = Date.now(); let d = Date.now();
@ -9,14 +16,7 @@ function run(message, iter, cb) {
} }
msg([message, Date.now() - d].join(", ")); msg([message, Date.now() - d].join(", "));
setTimeout(resolve, 0); setTimeout(resolve, 0);
}) });
}
function msg(msg) {
console.log(msg);
let div = document.createElement("div");
div.innerText = msg;
document.body.appendChild(div);
} }
let json = { let json = {
@ -65,12 +65,12 @@ let iterCount = 2000;
run('jsonpath', iterCount, function() { jp.query(json, path) }) run('jsonpath', iterCount, function() { jp.query(json, path) })
.then(function() { .then(function() {
return run('jsonpath-wasm- selector', iterCount, function() { selector(path) }); return run('jsonpath-wasm- selector', iterCount, function() { selector(path); });
}) })
.then(function() { .then(function() {
return run('jsonpath-wasm- compile', iterCount, function() { template(json) }); return run('jsonpath-wasm- compile', iterCount, function() { template(json); });
}) })
.then(function() { .then(function() {
return run('jsonpath-wasm- select', iterCount, function() { jpw.select(json, path) }); return run('jsonpath-wasm- select', iterCount, function() { jpw.select(json, path); });
}) })
.finally(function() {}); .finally(function() {});

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "jsonpath-wasm-bench", "name": "jsonpath-wasm-bench",
"version": "0.2.0", "version": "0.1.0",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "webpack --config webpack.config.js", "build": "webpack --config webpack.config.js",