mirror of
https://github.com/JockeTF/fimfareader.git
synced 2024-11-23 13:58:00 +01:00
Add query module for searching
This commit is contained in:
parent
aa619e862d
commit
36f182620b
6 changed files with 419 additions and 22 deletions
129
Cargo.lock
generated
129
Cargo.lock
generated
|
@ -10,11 +10,6 @@ name = "autocfg"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
|
@ -28,7 +23,7 @@ dependencies = [
|
||||||
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -46,7 +41,8 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"zip 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"zip 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
@ -61,6 +57,18 @@ name = "itoa"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lexical-core"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.60"
|
version = "0.2.60"
|
||||||
|
@ -68,16 +76,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libflate"
|
name = "libflate"
|
||||||
version = "0.1.25"
|
version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "5.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"lexical-core 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.41"
|
version = "0.1.41"
|
||||||
|
@ -126,27 +148,48 @@ name = "rle-decode-fast"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "semver"
|
||||||
version = "1.0.97"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
|
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver-parser"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.97"
|
version = "1.0.98"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syn 0.15.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -156,12 +199,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "stackvector"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "0.15.40"
|
version = "0.15.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -189,6 +246,24 @@ name = "unicode-xid"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unreachable"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "void"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -214,21 +289,23 @@ version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libflate 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libflate 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
|
"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c"
|
||||||
"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b"
|
"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b"
|
||||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
|
||||||
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
|
||||||
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
|
"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe"
|
||||||
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||||
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
|
||||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||||
|
"checksum lexical-core 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b0f90c979adde96d19eb10eb6431ba0c441e2f9e9bdff868b2f6f5114ff519"
|
||||||
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb"
|
||||||
"checksum libflate 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "90c6f86f4b0caa347206f916f8b687b51d77c6ef8ff18d52dd007491fd580529"
|
"checksum libflate 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "45c97cf62125b79dcac52d506acdc4799f21a198597806947fd5f40dc7b93412"
|
||||||
|
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||||
|
"checksum nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9761d859320e381010a4f7f8ed425f2c924de33ad121ace447367c713ad561b"
|
||||||
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||||
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
|
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
|
||||||
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
|
"checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd"
|
||||||
|
@ -236,14 +313,22 @@ dependencies = [
|
||||||
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||||
"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
|
||||||
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
|
||||||
"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72"
|
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||||
"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f"
|
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
|
"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113"
|
||||||
|
"checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c"
|
||||||
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
|
||||||
"checksum syn 0.15.40 (registry+https://github.com/rust-lang/crates.io-index)" = "bc945221ccf4a7e8c31222b9d1fc77aefdd6638eb901a6ce457a3dc29d4c31e8"
|
"checksum stackvector 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4725650978235083241fab0fdc8e694c3de37821524e7534a1a9061d1068af"
|
||||||
|
"checksum static_assertions 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4f8de36da215253eb5f24020bfaa0646613b48bf7ebe36cdfa37c3b3b33b241"
|
||||||
|
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||||
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
|
"checksum take_mut 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
|
||||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||||
|
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||||
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
|
||||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
|
@ -14,6 +14,9 @@ features = ["serde"]
|
||||||
[dependencies.hex]
|
[dependencies.hex]
|
||||||
version = "*"
|
version = "*"
|
||||||
|
|
||||||
|
[dependencies.nom]
|
||||||
|
version = "5"
|
||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "*"
|
version = "*"
|
||||||
features = ["derive"]
|
features = ["derive"]
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
pub mod archive;
|
pub mod archive;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
pub mod query;
|
||||||
|
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
6
src/query/mod.rs
Normal file
6
src/query/mod.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
//! Query module.
|
||||||
|
|
||||||
|
mod optimizer;
|
||||||
|
mod parser;
|
||||||
|
|
||||||
|
pub use self::parser::parse;
|
87
src/query/optimizer.rs
Normal file
87
src/query/optimizer.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
//! Query optimizer.
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use chrono::prelude::*;
|
||||||
|
|
||||||
|
use super::parser::{Operator, Source};
|
||||||
|
use crate::archive::Story;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
|
||||||
|
use Operator::*;
|
||||||
|
use Source::*;
|
||||||
|
|
||||||
|
type Filter = Box<dyn Fn(&Story) -> bool + Sync>;
|
||||||
|
|
||||||
|
type IntFn = Box<dyn Fn(&Story) -> i64 + Sync>;
|
||||||
|
type StrFn = Box<dyn Fn(&Story) -> &str + Sync>;
|
||||||
|
type DtuFn = Box<dyn Fn(&Story) -> &Option<DateTime<Utc>> + Sync>;
|
||||||
|
|
||||||
|
macro_rules! ok {
|
||||||
|
($func:expr) => {
|
||||||
|
Ok(Box::new($func))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn optimize(src: Source, op: Operator, value: &str) -> Result<Filter> {
|
||||||
|
match src {
|
||||||
|
StrFn(f) => strfn(f, op, value),
|
||||||
|
IntFn(f) => intfn(f, op, value),
|
||||||
|
DtuFn(f) => dtufn(f, op, value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn strfn(f: StrFn, op: Operator, value: &str) -> Result<Filter> {
|
||||||
|
let value: String = match op {
|
||||||
|
Fuzzy => value.to_lowercase(),
|
||||||
|
_ => value.to_owned(),
|
||||||
|
};
|
||||||
|
|
||||||
|
match op {
|
||||||
|
Exact => ok!(move |s| f(s) == &value),
|
||||||
|
Fuzzy => ok!(move |s| f(s).to_lowercase().contains(&value)),
|
||||||
|
_ => Err(Error::query("Invalid operation for text type")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn intfn(f: IntFn, op: Operator, value: &str) -> Result<Filter> {
|
||||||
|
let value: i64 = value.parse().map_err(|e| match e {
|
||||||
|
_ => Error::query("Invalid value for number type"),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
match op {
|
||||||
|
Exact => ok!(move |s| f(s) == value),
|
||||||
|
Fuzzy => ok!(move |s| f(s) == value),
|
||||||
|
LessThan => ok!(move |s| f(s) < value),
|
||||||
|
MoreThan => ok!(move |s| f(s) > value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dtufn(f: DtuFn, op: Operator, value: &str) -> Result<Filter> {
|
||||||
|
let parsed = DateTime::from_str(value);
|
||||||
|
|
||||||
|
let value: DateTime<Utc> = parsed.map_err(|e| match e {
|
||||||
|
_ => Error::query("Invalid value for date type"),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let date = value.date();
|
||||||
|
|
||||||
|
match op {
|
||||||
|
Exact => ok!(move |s| match f(s) {
|
||||||
|
Some(dt) => dt == &value,
|
||||||
|
None => false,
|
||||||
|
}),
|
||||||
|
Fuzzy => ok!(move |s| match f(s) {
|
||||||
|
Some(dt) => dt.date() == date,
|
||||||
|
None => false,
|
||||||
|
}),
|
||||||
|
LessThan => ok!(move |s| match f(s) {
|
||||||
|
Some(dt) => dt < &value,
|
||||||
|
None => false,
|
||||||
|
}),
|
||||||
|
MoreThan => ok!(move |s| match f(s) {
|
||||||
|
Some(dt) => dt > &value,
|
||||||
|
None => false,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
215
src/query/parser.rs
Normal file
215
src/query/parser.rs
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
//! Query parser.
|
||||||
|
|
||||||
|
use chrono::prelude::*;
|
||||||
|
|
||||||
|
use nom::character::complete::*;
|
||||||
|
use nom::error::ErrorKind as NomErrorKind;
|
||||||
|
use nom::sequence::*;
|
||||||
|
use nom::*;
|
||||||
|
|
||||||
|
use super::optimizer::optimize;
|
||||||
|
use crate::archive::Story;
|
||||||
|
use crate::error::*;
|
||||||
|
|
||||||
|
type Filter = Box<dyn Fn(&Story) -> bool + Sync>;
|
||||||
|
|
||||||
|
pub enum Source {
|
||||||
|
IntFn(Box<dyn Fn(&Story) -> i64 + Sync>),
|
||||||
|
StrFn(Box<dyn Fn(&Story) -> &str + Sync>),
|
||||||
|
DtuFn(Box<dyn Fn(&Story) -> &Option<DateTime<Utc>> + Sync>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Operator {
|
||||||
|
Exact,
|
||||||
|
Fuzzy,
|
||||||
|
LessThan,
|
||||||
|
MoreThan,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! sfn {
|
||||||
|
($func:expr) => {
|
||||||
|
|_| Source::StrFn(Box::new($func))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! ifn {
|
||||||
|
($func:expr) => {
|
||||||
|
|_| Source::IntFn(Box::new($func))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! dfn {
|
||||||
|
($func:expr) => {
|
||||||
|
|_| Source::DtuFn(Box::new($func))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(source<&str, Source>, preceded!(space0, alt!(
|
||||||
|
tag!("id") => { ifn!(|s| s.id as i64) } |
|
||||||
|
|
||||||
|
tag!("story") => { sfn!(|s| &s.title) } |
|
||||||
|
tag!("title") => { sfn!(|s| &s.title) } |
|
||||||
|
|
||||||
|
tag!("description") => { sfn!(|s| &s.description_html) } |
|
||||||
|
tag!("short description") => { sfn!(|s| &s.short_description) } |
|
||||||
|
tag!("url") => { sfn!(|s| &s.url) } |
|
||||||
|
|
||||||
|
tag!("modified") => { dfn!(|s| &s.date_modified) } |
|
||||||
|
tag!("published") => { dfn!(|s| &s.date_published) } |
|
||||||
|
tag!("updated") => { dfn!(|s| &s.date_updated) } |
|
||||||
|
|
||||||
|
tag!("chapters") => { ifn!(|s| s.num_chapters as i64) } |
|
||||||
|
tag!("comments") => { ifn!(|s| s.num_comments as i64) } |
|
||||||
|
tag!("dislikes") => { ifn!(|s| s.num_dislikes as i64) } |
|
||||||
|
tag!("likes") => { ifn!(|s| s.num_likes as i64) } |
|
||||||
|
tag!("total views") => { ifn!(|s| s.total_num_views as i64) } |
|
||||||
|
tag!("views") => { ifn!(|s| s.num_views as i64) } |
|
||||||
|
tag!("words") => { ifn!(|s| s.num_words as i64) } |
|
||||||
|
|
||||||
|
tag!("author") => { sfn!(|s| &s.author.name) } |
|
||||||
|
tag!("author name") => { sfn!(|s| &s.author.name) } |
|
||||||
|
|
||||||
|
tag!("author id") => { ifn!(|s| s.author.id as i64) } |
|
||||||
|
tag!("author joined") => { dfn!(|s| &s.author.date_joined) } |
|
||||||
|
|
||||||
|
tag!("path") => { sfn!(|s| &s.archive.path) } |
|
||||||
|
tag!("archive") => { sfn!(|s| &s.archive.path) } |
|
||||||
|
tag!("archive path") => { sfn!(|s| &s.archive.path) } |
|
||||||
|
|
||||||
|
tag!("entry checked") => { dfn!(|s| &s.archive.date_checked) } |
|
||||||
|
tag!("entry created") => { dfn!(|s| &s.archive.date_created) } |
|
||||||
|
tag!("entry fetched") => { dfn!(|s| &s.archive.date_fetched) } |
|
||||||
|
tag!("entry updated") => { dfn!(|s| &s.archive.date_updated) }
|
||||||
|
)));
|
||||||
|
|
||||||
|
named!(operator<&str, Operator>, preceded!(space0, alt!(
|
||||||
|
tag!("=") => { |_| Operator::Exact } |
|
||||||
|
tag!(":") => { |_| Operator::Fuzzy } |
|
||||||
|
tag!("<") => { |_| Operator::LessThan } |
|
||||||
|
tag!(">") => { |_| Operator::MoreThan }
|
||||||
|
)));
|
||||||
|
|
||||||
|
fn unescape(input: &str) -> String {
|
||||||
|
input
|
||||||
|
.replace("\\)", ")")
|
||||||
|
.replace("\\,", ",")
|
||||||
|
.replace("\\|", "|")
|
||||||
|
.replace("\\\\", "\\")
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(value<&str, &str>,
|
||||||
|
escaped!(none_of!("),|\\"), '\\', one_of!("),|\\"))
|
||||||
|
);
|
||||||
|
|
||||||
|
named!(target<&str, String>, preceded!(space0,
|
||||||
|
map!(value, |value| unescape(value.trim()))
|
||||||
|
));
|
||||||
|
|
||||||
|
fn item(input: &str) -> IResult<&str, Filter> {
|
||||||
|
let result = tuple((source, operator, target))(input)?;
|
||||||
|
let (left, (src, op, value)) = result;
|
||||||
|
|
||||||
|
let filter = optimize(src, op, &value).map_err(|e| match e {
|
||||||
|
_ => Err::Failure((input, NomErrorKind::Permutation)),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok((left, filter))
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(parens<&str, Filter>, alt!(
|
||||||
|
delimited!(
|
||||||
|
preceded!(space0, tag!("(")),
|
||||||
|
preceded!(space0, call!(ofunc)),
|
||||||
|
preceded!(space0, tag!(")"))
|
||||||
|
) |
|
||||||
|
call!(item)
|
||||||
|
));
|
||||||
|
|
||||||
|
fn negate(input: &str) -> IResult<&str, Filter> {
|
||||||
|
let (left, filter) = parens(input)?;
|
||||||
|
|
||||||
|
Ok((left, Box::new(move |s| !filter(s))))
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(nlist<&str, Filter>, preceded!(space0, alt!(
|
||||||
|
preceded!(char('!'), call!(negate)) | call!(parens)
|
||||||
|
)));
|
||||||
|
|
||||||
|
named!(alist<&str, Vec<Filter>>, separated_nonempty_list!(
|
||||||
|
preceded!(space0, char(',')), call!(nlist)
|
||||||
|
));
|
||||||
|
|
||||||
|
fn afunc(input: &str) -> IResult<&str, Filter> {
|
||||||
|
let (left, mut filters) = alist(input)?;
|
||||||
|
|
||||||
|
if filters.len() == 1 {
|
||||||
|
return Ok((left, filters.remove(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let filter: Filter = Box::new(move |story| {
|
||||||
|
for filter in filters.iter() {
|
||||||
|
if !filter(story) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok((left, filter))
|
||||||
|
}
|
||||||
|
|
||||||
|
named!(olist<&str, Vec<Filter>>, separated_nonempty_list!(
|
||||||
|
preceded!(space0, char('|')), call!(afunc)
|
||||||
|
));
|
||||||
|
|
||||||
|
fn ofunc(input: &str) -> IResult<&str, Filter> {
|
||||||
|
let (left, mut filters) = olist(input)?;
|
||||||
|
|
||||||
|
if filters.len() == 1 {
|
||||||
|
return Ok((left, filters.remove(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
let filter: Filter = Box::new(move |story| {
|
||||||
|
for filter in filters.iter() {
|
||||||
|
if filter(story) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok((left, filter))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_error(query: &str, input: &str, error: NomErrorKind) -> String {
|
||||||
|
let description = error.description().to_lowercase();
|
||||||
|
let position = query.len() - input.len();
|
||||||
|
|
||||||
|
format!("Invalid {} at {}", description, position)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_error(query: &str, error: Err<(&str, NomErrorKind)>) -> Error {
|
||||||
|
let message = match error {
|
||||||
|
Err::Error((i, e)) => format_error(query, i, e),
|
||||||
|
Err::Failure((i, e)) => format_error(query, i, e),
|
||||||
|
Err::Incomplete(_) => String::from("Incomplete input"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Error::query(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn translate_incomplete(query: &str, input: &str) -> Error {
|
||||||
|
let position = query.len() - input.len();
|
||||||
|
|
||||||
|
Error::query(format!("Incomplete input at {}", position))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(query: &str) -> Result<Filter> {
|
||||||
|
match ofunc(query.trim()) {
|
||||||
|
Ok(("", filter)) => Ok(filter),
|
||||||
|
Ok((i, _)) => Err(translate_incomplete(query, i)),
|
||||||
|
Err(e) => Err(translate_error(query, e)),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue