diff --git a/.gitignore b/.gitignore index 9d6fbaf..1a59e85 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,7 @@ .* *~ +1*k.*.json +test.* + !.gitignore diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 7b2e393..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,816 +0,0 @@ -[[package]] -name = "aho-corasick" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "argon2rs" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "arrayvec" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ascii-canvas" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "backtrace" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bit-set" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bit-vec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cc" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "diff" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "digest" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "dirs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "docopt" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ena" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fixedbitset" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "generic-array" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "itertools" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lalrpop" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ascii-canvas 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lalrpop-util" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.55" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "log" -version = "0.4.6" -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)", -] - -[[package]] -name = "memchr" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "new_debug_unreachable" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "opaque-debug" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ordermap" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "parser" -version = "0.1.0" -dependencies = [ - "lalrpop 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "petgraph" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_generator" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_users" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sha2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "string_cache" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache_codegen" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (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.12 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "string_cache_shared" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "strsim" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.15.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "term" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "termion" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typenum" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "ucd-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "utf8-ranges" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" -"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum ascii-canvas 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8eb72df928aafb99fe5d37b383f2fe25bd2a765e3e5f7c365916b6f2463a29" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "70af6de4789ac39587f100176ac7f704531e9e534b0f8676f658b3d909ce9a94" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum bit-set 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e84c238982c4b1e1ee668d136c510c67a13465279c0cb367ea6baf6310620a80" -"checksum bit-vec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" -"checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" -"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" -"checksum lalrpop 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b7f2d14eb07d819e961e5169f61d67de76a7cdbc6778b62192bcfe27c5af019" -"checksum lalrpop-util 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9768f55211206d3c17181108d8facb80bdffc1f1e674a67b1dddb2743529ca19" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" -"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" -"checksum new_debug_unreachable 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f40f005c60db6e03bae699e414c58bf9aa7ea02a2d0b9bfbcf19286cc4c82b30" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" -"checksum opaque-debug 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "93f5bb2e8e8dec81642920ccff6b61f1eb94fa3020c5a325c9851ff604152409" -"checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" -"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" -"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -"checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828" -"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" -"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" -"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" -"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" -"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" -"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da" -"checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" -"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6" -"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum term 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "edd106a334b7657c10b7c540a0106114feadeb4dc314513e97df481d5d966f42" -"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"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-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 6301b11..7257ad4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,23 @@ [package] -name = "parser" +name = "mercator_parser" version = "0.1.0" -authors = ["Lionel Sambuc "] +authors = ["EPFL-DIAS", "Lionel Sambuc "] + edition = "2018" + +description = "Query Parser for Mercator's own DSL." +#homepage = "https://crates.io/crates/mercator_parser" +repository = "https://github.com/epfl-dias/mercator_parser" +readme = "README.md" + +keywords = [] +categories = ["database-implementations", "parser-implementations"] + +license = "MIT" +#license-file = "LICENSE" + +include = ["Cargo.toml", "README.md", "LICENSE", "ACKNOWLEDGEMENTS", "src/**/*.rs"] + build = "build.rs" # LALRPOP preprocessing [lib] @@ -14,15 +29,18 @@ name = "parser-driver" path = "src/main.rs" [dependencies] -lalrpop-util = "0.17.0" -regex = "0.2.1" -measure_time = "0.6" # To mesure parsing time, only required by binary -lazy_static = "1.3.0" # for space.rs, might be removed once the full data model is provided by the use of the crate +mercator_db = "^0.1" + +lalrpop-util = "^0.17" +regex = "^1.2" + +measure_time = "^0.6" # To mesure parsing time, only required by binary # Logging macros API -log = { version = "0.4", features = ["max_level_trace", "release_max_level_debug"] } -pretty_env_logger = "0.3" # Logger implementation +log = { version = "^0.4", features = ["max_level_trace", "release_max_level_info"] } +#log = { version = "^0.4", features = ["max_level_trace", "release_max_level_trace"] } +pretty_env_logger = "^0.3" # Logger implementation [build-dependencies] -lalrpop = "0.17.0" +lalrpop = "^0.17.1" diff --git a/Grammars/filters.g4 b/Grammars/filters.g4 index bc18eee..45597d4 100644 --- a/Grammars/filters.g4 +++ b/Grammars/filters.g4 @@ -19,9 +19,6 @@ bag_expression // Spatial Operators | inside | outside - // When used directly here, the inside() operation on the shape is - // implied. - | shapes ; /**********************************************************************/ @@ -58,7 +55,6 @@ predicate | greater | equal | str_cmp - | str_cmp_icase | not | and | or diff --git a/README.md b/README.md new file mode 100644 index 0000000..d84283e --- /dev/null +++ b/README.md @@ -0,0 +1,74 @@ +# Mercator Parser + +Query parser for Mercator. + +## Mercator: Spatial Index + +**Mercator** is a spatial *volumetric* index for the [Human Brain Project](http://www.humanbrainproject.eu). It is a component of the [Knowledge Graph](http://www.humanbrainproject.eu/en/explore-the-brain/search/) service, which provides the spatial anchoring for the metadata registered as well as processes the volumetric queries. + +It is build on top of the Iron Sea database toolkit. + +## Iron Sea: Database Toolkit + +**Iron Sea** provides a set of database engine bricks, which can be combined and applied on arbitrary data structures. + +Unlike a traditional database, it does not assume a specific physical structure for the tables nor the records, but relies on the developper to provide a set of extractor functions which are used by the specific indices provided. + +This enables the index implementations to be agnostic from the underlying data structure, and re-used. + +## Requirements + +### Software + + * Rust: https://www.rust-lang.org + +## Quick start + +## Building from sources + +To build this project, you will need to run the following: + +```sh +cargo build --release +``` + +### Installation + +To install the software on the system you can use: + +```sh +cargo install --release +``` + +### Usage + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vehicula pretium +quam sit amet facilisis. Class aptent taciti sociosqu ad litora torquent per +conubia nostra, per inceptos himenaeos. Curabitur metus sapien, rhoncus vitae +eleifend nec, convallis vel nunc. Nulla metus mauris, porta eu porta eu, +vulputate et est. Suspendisse lacinia leo vel auctor aliquet. Maecenas non arcu +libero. Nulla ut eleifend dui. Cras bibendum pharetra facilisis. Proin mattis +libero non pharetra tristique. Nam massa nulla, ultrices pharetra quam a, +fermentum placerat dolor. Nullam mollis libero et neque lobortis, id dignissim +lectus dignissim. Maecenas ligula enim, congue in ornare vel, volutpat ut ante. + +```sh +cargo run --release +``` + +## Documentation + +For more information, please refer to the [documentation](https://epfl-dias.github.io/mercator_parser/). + +If you want to build the documentation and access it locally, you can use: + +```sh +cargo doc --open +``` + +## Acknowledgements + +This open source software code was developed in part or in whole in the +Human Brain Project, funded from the European Union’s Horizon 2020 +Framework Programme for Research and Innovation under the Specific Grant +Agreement No. 785907 (Human Brain Project SGA2). diff --git a/src/database/mod.rs b/src/database/mod.rs deleted file mode 100644 index 9bd9a97..0000000 --- a/src/database/mod.rs +++ /dev/null @@ -1,57 +0,0 @@ -use crate::executors::ResultSet; -use crate::symbols::*; - -//use ironsea_index::*; - -pub fn get_all(_space_id: &String) -> ResultSet { - //space::get_all(space_id) - Err("not yet implemented".to_string()) -} - -pub fn get_by_bounding_box(_space_id: &String, _bounding_box: &Vec) -> ResultSet { - Err("not yet implemented".to_string()) -} - -pub fn get_by_position(_space_id: &String, _position: &LiteralPosition) -> ResultSet { - Err("not yet implemented".to_string()) -} - -pub fn get(_point: &Object, _fields: &Vec) -> Result { - Err("not yet implemented".to_string()) -} - -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -pub struct Object { - id: u32, -} - -impl Object { - pub fn length(&self) -> f64 { - 0.0 - } - - pub fn eval(&self, _predicate: &Predicate) -> bool { - false - } -} - -impl Position { - pub fn eval(&self, point: &Object) -> LiteralPosition { - match self { - Position::StrCmpICase(_selector, _string) => LiteralPosition(vec![]), //TODO - Position::StrCmp(_selector, _string) => LiteralPosition(vec![]), //TODO - Position::Selector(selector) => selector.eval(point), - Position::Literal(position) => position.clone(), - } - } -} - -impl LiteralSelector { - pub fn eval(&self, point: &Object) -> LiteralPosition { - let LiteralSelector(fields) = self; - match get(point, fields) { - Err(_) => LiteralPosition(vec![]), - Ok(p @ LiteralPosition(_)) => p, - } - } -} diff --git a/src/database/space.rs b/src/database/space.rs deleted file mode 100644 index 4ce8080..0000000 --- a/src/database/space.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::collections::HashMap; - -use crate::types::LiteralTypes; - -//FIXME: Improve, as this should not be static, but coming from DB. -lazy_static! { - static ref UNIVERSE: String = "Universe".to_string(); - static ref SPACES: HashMap<&'static str, Space> = { - let mut m = HashMap::new(); - m.insert( - "Universe", - Space { - space_type: LiteralTypes::Vector(vec![ - LiteralTypes::Float, - LiteralTypes::Float, - LiteralTypes::Float, - ]), - bounding_box: vec![ - vec![0, 0, 0], - vec![ - std::u32::MAX as i64, - std::u32::MAX as i64, - std::u32::MAX as i64, - ], - ], - }, - ); - - m - }; -} - -struct Space { - space_type: LiteralTypes, - bounding_box: Vec>, -} - -impl Space { - pub fn max_volume(&self) -> f64 { - let mut volume = 1.0; - for max in &self.bounding_box[1] { - volume *= *max as f64; - } - - volume - } -} - -pub fn name() -> &'static String { - lazy_static! { - static ref UNIVERSE: String = "Universe".to_string(); - }; - - &UNIVERSE -} - -#[inline] -pub fn get_type(space_id: &String) -> &LiteralTypes { - lazy_static! { - static ref EMPTY_TYPE: LiteralTypes = LiteralTypes::Vector(Vec::new()); - }; - - match SPACES.get(space_id.as_str()) { - None => &EMPTY_TYPE, - Some(space) => &space.space_type, - } -} - -#[inline] -pub fn bounding_box(space_id: &String) -> &Vec> { - lazy_static! { - static ref EMPTY_BOX: Vec> = Vec::new(); - }; - match SPACES.get(space_id.as_str()) { - None => &EMPTY_BOX, - Some(space) => &space.bounding_box, - } -} - -#[inline] -pub fn max_volume(space_id: &String) -> f64 { - match SPACES.get(space_id.as_str()) { - None => 0.0, - Some(space) => space.max_volume(), - } -} diff --git a/src/evaluators.rs b/src/evaluators.rs new file mode 100644 index 0000000..5bfdb25 --- /dev/null +++ b/src/evaluators.rs @@ -0,0 +1,17 @@ +use mercator_db::SpaceObject; + +use super::expressions::*; +use super::symbols::*; + +impl Evaluator for Predicate { + fn eval(&self, object: &SpaceObject) -> bool { + match self { + Predicate::Not(predicate) => !predicate.eval(object), + Predicate::And(lh, rh) => lh.eval(object) && rh.eval(object), + Predicate::Or(lh, rh) => lh.eval(object) || rh.eval(object), + Predicate::Less(selector, literal) => &selector.value(object) < literal, + Predicate::Greater(selector, literal) => &selector.value(object) > literal, + Predicate::Equal(selector, literal) => &selector.value(object) == literal, + } + } +} diff --git a/src/executors.rs b/src/executors.rs index cba48ac..6658823 100644 --- a/src/executors.rs +++ b/src/executors.rs @@ -1,314 +1,384 @@ use std::collections::HashSet; -use super::database; -use super::expression::*; +use mercator_db::space; +use mercator_db::Core; +use mercator_db::DataBase; +use mercator_db::SpaceObject; + +use super::expressions::*; use super::symbols::*; -pub type ResultSet = Result, String>; +impl From<&LiteralPosition> for space::Position { + fn from(literal: &LiteralPosition) -> Self { + let v: Vec = literal.into(); + v.into() + } +} + +impl From<&LiteralNumber> for space::Coordinate { + fn from(literal: &LiteralNumber) -> Self { + match literal { + LiteralNumber::Float(f) => (*f).into(), + LiteralNumber::Int(i) => (*i as u64).into(), + } + } +} + +fn complement_helper( + db: &DataBase, + core: &Core, + space_id: &str, + inside: Vec, + output_space: Option<&str>, + threshold: f64, +) -> mercator_db::ResultSet { + let (low, high) = db.space(space_id)?.bounding_box(); + match core.get_by_shape( + db, + &space::Shape::BoundingBox(low, high), + space_id, + output_space, + threshold, + ) { + e @ Err(_) => e, + Ok(points) => Ok(points + .into_iter() + .filter(|o| !inside.contains(&o)) + .collect::>()), + } +} + +fn distinct( + db: &DataBase, + core_id: &str, + bag: &Bag, + output_space: Option<&str>, + threshold_volume: Option, +) -> mercator_db::ResultSet { + match bag.execute(db, core_id, output_space, threshold_volume) { + e @ Err(_) => e, + Ok(mut v) => { + let set: HashSet<_> = v.drain(..).collect(); // dedup + v.extend(set.into_iter()); + + Ok(v) + } + } +} + +fn filter( + db: &DataBase, + core_id: &str, + predicate: &Option, + bag: &Bag, + output_space: Option<&str>, + threshold_volume: Option, +) -> mercator_db::ResultSet { + match predicate { + None => bag.execute(db, core_id, output_space, threshold_volume), + Some(predicate) => match bag.execute(db, core_id, output_space, threshold_volume) { + e @ Err(_) => e, + Ok(results) => Ok(results + .into_iter() + .filter(|o| predicate.eval(&o)) + .collect::>()), + }, + } +} + +fn complement( + db: &DataBase, + core_id: &str, + core: &Core, + bag: &Bag, + output_space: Option<&str>, + threshold: f64, + threshold_volume: Option, +) -> mercator_db::ResultSet { + match bag.execute(db, core_id, output_space, threshold_volume) { + // FIXME: The complement of a set is computed within its definition space. + e @ Err(_) => e, + Ok(inside) => complement_helper( + db, + core, + mercator_db::space::Space::universe().name(), + inside, + output_space, + threshold, + ), + } +} + +fn intersection( + db: &DataBase, + core_id: &str, + rh: &Bag, + lh: &Bag, + output_space: Option<&str>, + threshold_volume: Option, +) -> mercator_db::ResultSet { + let l = lh.execute(db, core_id, output_space, threshold_volume); + if let Ok(l) = l { + let r = rh.execute(db, core_id, output_space, threshold_volume); + if let Ok(r) = r { + let mut v = vec![]; + + if rh.predict(db) < lh.predict(db) { + for o in r { + if l.contains(&o) { + v.push(o); + } + } + } else { + for o in l { + if r.contains(&o) { + v.push(o); + } + } + } + Ok(v) + } else { + r + } + } else { + l + } +} + +fn union( + db: &DataBase, + core_id: &str, + rh: &Bag, + lh: &Bag, + output_space: Option<&str>, + threshold_volume: Option, +) -> mercator_db::ResultSet { + let l = lh.execute(db, core_id, output_space, threshold_volume); + if let Ok(mut l) = l { + let r = rh.execute(db, core_id, output_space, threshold_volume); + if let Ok(mut r) = r { + if rh.predict(db) < lh.predict(db) { + l.append(&mut r); + Ok(l) + } else { + r.append(&mut l); + Ok(r) + } + } else { + r + } + } else { + l + } +} + +fn bag( + db: &DataBase, + core_id: &str, + bags: &[Bag], + output_space: Option<&str>, + threshold_volume: Option, +) -> mercator_db::ResultSet { + let mut v = vec![]; + for bag in bags { + let b = bag.execute(db, core_id, output_space, threshold_volume); + match b { + e @ Err(_) => { + return e; + } + Ok(mut b) => { + v.append(&mut b); + } + } + } + + Ok(v) +} + +fn inside( + db: &DataBase, + core: &Core, + shape: &Shape, + output_space: Option<&str>, + threshold: f64, +) -> mercator_db::ResultSet { + let parameters = match shape { + Shape::Point(space_id, position) => { + let space = db.space(space_id)?; + let position: Vec = position.into(); + let position = space.encode(&position)?; + Ok((space_id, space::Shape::Point(position))) + } + Shape::HyperRectangle(space_id, bounding_box) => { + if bounding_box.len() != 2 { + Err("The number of position is different from 2, which is unsupported.".to_string()) + } else { + let space = db.space(space_id)?; + let low: Vec = (&bounding_box[0]).into(); + let high: Vec = (&bounding_box[1]).into(); + let low = space.encode(&low)?; + let high = space.encode(&high)?; + + Ok((space_id, space::Shape::BoundingBox(low, high))) + } + } + Shape::HyperSphere(space_id, position, radius) => { + let space = db.space(space_id)?; + let position: Vec = position.into(); + let position = space.encode(&position)?; + let mut r = vec![]; + for _ in 0..position.dimensions() { + r.push(radius.into()); + } + let radius = space.encode(&r)?[0]; + + //FIXME: RADIUS IS A LENGTH, HOW TO ENCODE IT INTO THE SPACE? + Ok((space_id, space::Shape::HyperSphere(position, radius))) + } + Shape::Nifti(_space_id) => Err("Inside-Nifti: not yet implemented".to_string()), + }; + + match parameters { + Ok((space_id, shape)) => core.get_by_shape(db, &shape, space_id, output_space, threshold), + Err(e) => Err(e), + } +} + +fn outside( + db: &DataBase, + core: &Core, + shape: &Shape, + output_space: Option<&str>, + threshold: f64, +) -> mercator_db::ResultSet { + match shape { + Shape::Point(space_id, position) => { + let position: Vec = position.into(); + match core.get_by_positions(db, &[position.into()], space_id, output_space, threshold) { + e @ Err(_) => e, + Ok(inside) => { + complement_helper(db, core, space_id, inside, output_space, threshold) + } + } + } + Shape::HyperRectangle(space_id, bounding_box) => { + // We need to adapt the bounding_box to ensure the + // surface will not hit as part of the inside set, so we + // compute the biggest bounding box contained within the + // given box. + + // Smallest increment possible + let mut increment = Vec::with_capacity(bounding_box[0].dimensions()); + for _ in 0..bounding_box[0].dimensions() { + increment.push(std::f64::EPSILON); + } + + // Add it to the lower bound + let mut low: space::Position = (&bounding_box[0]).into(); + low += increment.clone().into(); + + // Substract it from the upper bound + let mut high: space::Position = (&bounding_box[1]).into(); + high -= increment.into(); + + match core.get_by_shape( + db, + &space::Shape::BoundingBox(low, high), + space_id, + output_space, + threshold, + ) { + e @ Err(_) => e, + Ok(inside) => { + complement_helper(db, core, space_id, inside, output_space, threshold) + } + } + } + Shape::HyperSphere(space_id, center, radius) => { + // Smallest decrement possible, to exclude the surface + let mut radius: f64 = radius.into(); + radius -= std::f64::EPSILON; + let center: space::Position = center.into(); + + match core.get_by_shape( + db, + &space::Shape::HyperSphere(center, radius.into()), + space_id, + output_space, + threshold, + ) { + e @ Err(_) => e, + Ok(inside) => { + complement_helper(db, core, space_id, inside, output_space, threshold) + } + } + } + Shape::Nifti(_space_id) => Err("Outside-nifti: not yet implemented".to_string()), + } +} impl Executor for Projection { - type ResultSet = self::ResultSet; + type ResultSet = mercator_db::ResultSet; - fn execute(&self) -> ResultSet { + fn execute( + &self, + db: &DataBase, + core_id: &str, + output_space: Option<&str>, + threshold_volume: Option, + ) -> Self::ResultSet { match self { - Projection::Nifti(_, _, _bag) => Err("not yet implemented".to_string()), - Projection::JSON(_, _format, bag) => bag.execute(), // FIXME: Add projections here + Projection::Nifti(_, _, _bag) => Err("Proj-Nifti: not yet implemented".to_string()), + Projection::JSON(_, _format, bag) => { + bag.execute(db, core_id, output_space, threshold_volume) + // FIXME: Add projections here + } } } } impl Executor for Bag { - type ResultSet = self::ResultSet; + type ResultSet = mercator_db::ResultSet; - fn execute(&self) -> ResultSet { - fn get_bounding_box( - position: &LiteralPosition, - radius: &LiteralNumber, - ) -> Result, String> { - let LiteralPosition(position) = position; - let mut low = vec![]; - let mut high = vec![]; - match radius { - LiteralNumber::Int(r) => { - for x in position { - match x { - LiteralNumber::Int(x) => { - low.push(LiteralNumber::Int(x - r)); - high.push(LiteralNumber::Int(x + r)); - } - LiteralNumber::Float(x) => { - low.push(LiteralNumber::Float(x - (*r as f64))); - high.push(LiteralNumber::Float(x + (*r as f64))); - } - }; - } - } - LiteralNumber::Float(r) => { - for x in position { - match x { - LiteralNumber::Int(_) => { - return Err(format!("The radius provided is a floating point value, which is incompatible with integer coordinates components: radius {:?}, coordinates {:?}", radius, position)); - } - LiteralNumber::Float(x) => { - low.push(LiteralNumber::Float(x - r)); - high.push(LiteralNumber::Float(x + r)); - } - }; - } - } - } - - Ok(vec![LiteralPosition(low), LiteralPosition(high)]) + fn execute( + &self, + db: &DataBase, + core_id: &str, + output_space: Option<&str>, + threshold_volume: Option, + ) -> Self::ResultSet { + let threshold = match threshold_volume { + None => 0.0, + Some(v) => v, }; + let core = db.core(core_id)?; match self { - Bag::Distinct(bag) => match bag.execute() { - e @ Err(_) => e, - Ok(mut v) => { - let set: HashSet<_> = v.drain(..).collect(); // dedup - v.extend(set.into_iter()); - - Ok(v) - } - }, - Bag::Filter(predicate, bag) => match predicate { - None => bag.execute(), - Some(predicate) => match bag.execute() { - e @ Err(_) => e, - Ok(source) => { - let mut filtered = Vec::new(); - - for point in source { - if point.eval(predicate) { - filtered.push(point); - } - } - - Ok(filtered) - } - }, - }, - Bag::Complement(bag) => match bag.execute() { - // The complement of a set is computed within its definition space. - e @ Err(_) => e, - Ok(inside) => { - let mut outside = Vec::new(); - match database::get_all(bag.space()) { - e @ Err(_) => e, - Ok(points) => { - for point in points { - if !inside.contains(&point) { - outside.push(point) - } - } - - Ok(outside) - } - } - } - }, + Bag::Distinct(bag) => distinct(db, core_id, bag, output_space, threshold_volume), + Bag::Filter(predicate, bag) => { + filter(db, core_id, predicate, bag, output_space, threshold_volume) + } + Bag::Complement(bag) => complement( + db, + core_id, + core, + bag, + output_space, + threshold, + threshold_volume, + ), Bag::Intersection(lh, rh) => { - let l = lh.execute(); - if let Ok(l) = l { - let r = rh.execute(); - if let Ok(r) = r { - let mut v = vec![]; - - if rh.predict() < lh.predict() { - for o in r { - if l.contains(&o) { - v.push(o); - } - } - } else { - for o in l { - if r.contains(&o) { - v.push(o); - } - } - } - Ok(v) - } else { - r - } - } else { - l - } + intersection(db, core_id, rh, lh, output_space, threshold_volume) } - Bag::Union(lh, rh) => { - let l = lh.execute(); - if let Ok(mut l) = l { - let r = rh.execute(); - if let Ok(mut r) = r { - if rh.predict() < lh.predict() { - l.append(&mut r); - Ok(l) - } else { - r.append(&mut l); - Ok(r) - } - } else { - r - } - } else { - l - } - } - Bag::Bag(bags) => { - let mut v = vec![]; - for bag in bags { - let b = bag.execute(); - match b { - e @ Err(_) => { - return e; - } - Ok(mut b) => { - //TODO: SPACE CONVERSIONS IF NOT THE SAME SPACES? - v.append(&mut b); - } - } - } - - Ok(v) - } - Bag::Inside(shape) => match shape { - Shape::Point(space_id, position) => database::get_by_position(space_id, position), - Shape::HyperRectangle(space_id, bounding_box) => { - database::get_by_bounding_box(space_id, bounding_box) - } - Shape::HyperSphere(space_id, position, radius) => { - let length = match radius { - LiteralNumber::Int(x) => *x as f64, - LiteralNumber::Float(x) => *x, - }; - - match get_bounding_box(position, radius) { - Err(e) => Err(e), - Ok(inside) => match database::get_by_bounding_box(space_id, &inside) { - e @ Err(_) => e, - Ok(source) => { - let mut filtered = vec![]; - - for point in source { - // Include the surface of the sphere - if point.length() <= length { - filtered.push(point); - } - } - Ok(filtered) - } - }, - } - } - Shape::Nifti(_space_id) => Err("not yet implemented".to_string()), - }, + Bag::Union(lh, rh) => union(db, core_id, rh, lh, output_space, threshold_volume), + Bag::Bag(list) => bag(db, core_id, list, output_space, threshold_volume), + Bag::Inside(shape) => inside(db, core, shape, output_space, threshold), Bag::Outside(shape) => { - fn outside_set(space_id: &String, inside: Vec) -> ResultSet { - let mut outside = Vec::new(); - match database::get_all(space_id) { - e @ Err(_) => e, - Ok(points) => { - for point in points { - if !inside.contains(&point) { - outside.push(point) - } - } - - Ok(outside) - } - } - } - - match shape { - Shape::Point(space_id, position) => { - match database::get_by_position(space_id, position) { - e @ Err(_) => e, - Ok(inside) => outside_set(space_id, inside), - } - } - Shape::HyperRectangle(space_id, bounding_box) => { - // We need to adapt the bounding_box to ensure the - // surface will not hit as part of the inside set, so we - // compute the biggest bounding box contained within the - // given box. - - // Smallest increment possible - let mut low: Vec = vec![]; - let LiteralPosition(coordinates) = &bounding_box[0]; - for coordinate in coordinates { - match coordinate { - LiteralNumber::Int(x) => low.push(LiteralNumber::Int(x + 1)), - LiteralNumber::Float(x) => { - low.push(LiteralNumber::Float(x + std::f64::EPSILON)) - } - }; - } - let low = LiteralPosition(low); - - // Smallest decrement possible - let mut high: Vec = vec![]; - let LiteralPosition(coordinates) = &bounding_box[1]; - for coordinate in coordinates { - match coordinate { - LiteralNumber::Int(x) => high.push(LiteralNumber::Int(x - 1)), - LiteralNumber::Float(x) => { - high.push(LiteralNumber::Float(x - std::f64::EPSILON)) - } - }; - } - let high = LiteralPosition(high); - - match database::get_by_bounding_box(space_id, &vec![low, high]) { - e @ Err(_) => e, - Ok(inside) => outside_set(space_id, inside), - } - } - Shape::HyperSphere(space_id, position, radius) => { - let length = match radius { - LiteralNumber::Int(x) => *x as f64, - LiteralNumber::Float(x) => *x, - }; - - match get_bounding_box(position, radius) { - Err(e) => Err(e), - Ok(inside) => match database::get_by_bounding_box(space_id, &inside) { - Err(e) => Err(e), - Ok(source) => { - let mut filtered = vec![]; - - for point in source { - // Exclude the surface of the sphere, so - // that it is included in the - // complement. - if point.length() < length { - filtered.push(point); - } - } - - outside_set(space_id, filtered) - } - }, - } - } - Shape::Nifti(_space_id) => Err("not yet implemented".to_string()), - } + //FIXME: This is currently computed as the complement of the values within the shape, except its surface. + // Should this be instead a list of positions within the shape? + //FIXME: Should we use the Shape's Space to get the maximum bounds or the output Space requested? + outside(db, core, shape, output_space, threshold) } } } } - -impl Predicate { - pub fn eval(&self, point: &database::Object) -> bool { - match self { - Predicate::Not(predicate) => !predicate.eval(point), - Predicate::And(lh, rh) => lh.eval(point) && rh.eval(point), - Predicate::Or(lh, rh) => lh.eval(point) || rh.eval(point), - // I don't know how to evaluate these at this point, so let the DB object take care of that. - // Predicate::Less(selector, literal) => &selector.eval(point) < literal, - // Predicate::Greater(selector, literal) => &selector.eval(point) > literal, - // Predicate::Equal(selector, literal) => &selector.eval(point) == literal, - // Redirect to the DB Objet the evaluation of the remaining predicate operators - predicate => point.eval(predicate), - } - } -} diff --git a/src/expression.rs b/src/expression.rs deleted file mode 100644 index d92ed18..0000000 --- a/src/expression.rs +++ /dev/null @@ -1,15 +0,0 @@ -pub trait Validator { - type ValidationResult; - - fn validate(&self) -> Self::ValidationResult; -} - -pub trait Predictor { - fn predict(&self) -> f64; -} - -pub trait Executor { - type ResultSet; - - fn execute(&self) -> Self::ResultSet; -} diff --git a/src/expressions.rs b/src/expressions.rs new file mode 100644 index 0000000..ee4d4d6 --- /dev/null +++ b/src/expressions.rs @@ -0,0 +1,28 @@ +use mercator_db::DataBase; +use mercator_db::SpaceObject; + +pub trait Validator { + type ValidationResult; + + fn validate(&self) -> Self::ValidationResult; +} + +pub trait Predictor { + fn predict(&self, db: &DataBase) -> Result; +} + +pub trait Executor { + type ResultSet; + + fn execute( + &self, + db: &DataBase, + core_id: &str, + output_space: Option<&str>, + threshold_volume: Option, + ) -> Self::ResultSet; +} + +pub trait Evaluator { + fn eval(&self, object: &SpaceObject) -> bool; +} diff --git a/src/lib.rs b/src/lib.rs index 867c4ff..f05be48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,25 +1,23 @@ -#[macro_use] -extern crate lazy_static; - #[macro_use] extern crate lalrpop_util; -lalrpop_mod!(pub queries); // synthesized by LALRPOP +lalrpop_mod!(#[allow(clippy::all)] pub queries); // synthesized by LALRPOP -mod database; +mod evaluators; mod executors; -mod expression; +mod expressions; mod predictors; mod validators; mod symbols; mod types; -pub use expression::Executor; -pub use expression::Predictor; -pub use expression::Validator; +pub use expressions::Executor; +pub use expressions::Predictor; +pub use expressions::Validator; pub use queries::FiltersParser; pub use queries::QueryParser; +pub use validators::ValidationResult; #[cfg(test)] mod tests; diff --git a/src/main.rs b/src/main.rs index 01a9d9a..d0b3f91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,16 @@ #[macro_use] extern crate measure_time; -extern crate parser; - -use parser::QueryParser; -use parser::{Executor, Predictor, Validator}; - use std::io; +use std::process::exit; + +use mercator_db::json::storage; +use mercator_db::DataBase; +use parser::Executor; +use parser::FiltersParser; +use parser::Predictor; +use parser::QueryParser; +use parser::Validator; fn main() { // If RUST_LOG is unset, set it to INFO, otherwise keep it as-is. @@ -15,8 +19,41 @@ fn main() { } pretty_env_logger::init(); - //let parser = queries::FiltersParser::new(); + let import; + + if std::env::var("MERCATOR_IMPORT_DATA").is_err() { + std::env::set_var("MERCATOR_IMPORT_DATA", "test"); + } + + match std::env::var("MERCATOR_IMPORT_DATA") { + Ok(val) => import = val, + Err(val) => { + error!("Could not fetch {} : `{}`", "MERCATOR_IMPORT_DATA", val); + exit(1); + } + }; + + // Convert to binary the JSON data: + if true { + info_time!("Converting to binary JSON data"); + storage::convert(&import); + } + + // Build a Database Index: + if true { + info_time!("Building database index"); + storage::build(&import); + } + + // Load a Database: + let db; + { + info_time!("Loading database index"); + db = DataBase::load(import).unwrap(); + } + let parser = QueryParser::new(); + let parser = FiltersParser::new(); loop { println!(); @@ -27,49 +64,59 @@ fn main() { Ok(0) => break, // Catch ^D Ok(1) => continue, // Catch \n Err(_) => continue, - Ok(_) => (), - } + Ok(_) => { + if input.trim().eq_ignore_ascii_case("quit") { + break; + } - if input.trim().eq_ignore_ascii_case("quit") { - break; - } + info_time!("Interpretation"); + let mut parse; + { + info_time!("Parsing"); + parse = parser.parse(&input); + } - let input = input.as_str(); - { - debug_time!("Interpretation"); - let mut parse; - { - trace_time!("Parsing"); - parse = parser.parse(input); - } - trace!("Tree: \n{:?}", parse); + if let Err(e) = &parse { + warn!("Parsing failed: \n{:?}", e); + } else { + trace!("Tree: \n{:?}", parse); + } - match parse { - Ok(Some(t)) => { + // QueryParser + //if let Ok(Some(t)) = parse { + + // FiltersParser + if let Ok(t) = parse { let validate; { - trace_time!("Type check"); + info_time!("Type check"); validate = t.validate(); } info!("Type: \n{:?}", validate); - if let Ok(_) = validate { + if validate.is_ok() { let predict; { - trace_time!("Prediction"); - predict = t.predict(); + info_time!("Prediction"); + predict = t.predict(&db); } info!("Predict: \n{:?}", predict); let execute; { - trace_time!("Exectution"); - execute = t.execute(); + info_time!("Execution"); + execute = t.execute(&db, "test", None, None); + } + + if let Ok(r) = execute { + //let r = model::to_spatial_objects(&db, r); + info!("Execution: \n{:#?}", r); + info!("NB results: {:?}", r.len()); + } else { + info!("Execution: \n{:?}", execute); } - info!("Execution: \n{:?}", execute); } } - _ => (), } } } diff --git a/src/predictors.rs b/src/predictors.rs index d72e3c8..706e890 100644 --- a/src/predictors.rs +++ b/src/predictors.rs @@ -1,48 +1,48 @@ -use super::expression::Predictor; +use mercator_db::DataBase; + +use super::expressions::Predictor; use super::symbols::*; -use super::database::space; - impl Predictor for Projection { - fn predict(&self) -> f64 { + fn predict(&self, db: &DataBase) -> Result { match self { - Projection::Nifti(_, _, bag) => bag.predict(), - Projection::JSON(_, _, bag) => bag.predict(), + Projection::Nifti(_, _, bag) => bag.predict(db), + Projection::JSON(_, _, bag) => bag.predict(db), } } } impl Predictor for Bag { - fn predict(&self) -> f64 { + fn predict(&self, db: &DataBase) -> Result { match self { - Bag::Distinct(bag) => bag.predict(), - Bag::Filter(_, bag) => bag.predict(), - Bag::Complement(bag) => space::max_volume(bag.space()) - bag.predict(), + Bag::Distinct(bag) => bag.predict(db), + Bag::Filter(_, bag) => bag.predict(db), + Bag::Complement(bag) => Ok(db.space(bag.space())?.volume() - bag.predict(db)?), Bag::Intersection(lh, rh) => { - let l = lh.predict(); - let r = rh.predict(); + let l = lh.predict(db)?; + let r = rh.predict(db)?; if l < r { - l + Ok(l) } else { - r + Ok(r) } } - Bag::Union(lh, rh) => lh.predict() + rh.predict(), + Bag::Union(lh, rh) => Ok(lh.predict(db)? + rh.predict(db)?), Bag::Bag(bags) => { let mut s = 0.0; for bag in bags { - s += bag.predict(); + s += bag.predict(db)?; } - s + Ok(s) } - Bag::Inside(shape) => shape.predict(), - Bag::Outside(shape) => space::max_volume(shape.space()) - shape.predict(), + Bag::Inside(shape) => shape.predict(db), + Bag::Outside(shape) => Ok(db.space(shape.space())?.volume() - shape.predict(db)?), } } } impl Predictor for Shape { - fn predict(&self) -> f64 { - self.volume() + fn predict(&self, _db: &DataBase) -> Result { + Ok(self.volume()) } } diff --git a/src/queries.lalrpop b/src/queries.lalrpop index 5334f24..9c42795 100644 --- a/src/queries.lalrpop +++ b/src/queries.lalrpop @@ -1,7 +1,8 @@ use std::str::FromStr; +use mercator_db::space::Space; + use crate::symbols; -use crate::database::space; grammar; @@ -27,7 +28,7 @@ NiftiOperator: symbols::Projection = { ")" => { let space_id = match rs { Some(id) => id, - None => space::name().clone(), + None => Space::universe().name().clone(), }; if let Some((sel, _)) = s { @@ -47,7 +48,7 @@ JsonOperator: symbols::Projection = { ")" => { let space_id = match rs { Some(id) => id, - None => space::name().clone(), + None => Space::universe().name().clone(), }; symbols::Projection::JSON(space_id, f, b) @@ -148,9 +149,6 @@ Bags: symbols::Bag = { // Spatial Operators Inside, Outside, - // When used directly here, the inside() operation on the shape is - // implied. - Shapes => symbols::Bag::Inside(<>) }; //*********************************************************************/ @@ -186,26 +184,8 @@ Filter: symbols::Bag = { // "filter" "(" "," ")" => "filter" "(" ")" => symbols::Bag::Filter(None, Box::new(b)), - "filter" "(" )?> ")" => match b { - Some(b) => symbols::Bag::Filter(Some(p), Box::new(b)), - None => { - let v = space::bounding_box(space::name()); - let mut positions = Vec::new(); - for point in v { - let mut position = Vec::new(); - for c in point { - position.push(symbols::LiteralNumber::Int(*c)) - } - positions.push(symbols::LiteralPosition(position)); - } - let bb = symbols::Shape::HyperRectangle( - space::name().clone(), - positions - ); - - symbols::Bag::Filter(Some(p), Box::new(symbols::Bag::Inside(bb))) - } - } + "filter" "(" )?> ")" => + symbols::get_filter(p, b) }; Predicates: symbols::Predicate = { @@ -311,7 +291,7 @@ HyperRectangle: symbols::Shape = { "}" => { let space_id = match rs { Some(id) => id, - None => space::name().clone(), + None => Space::universe().name().clone(), }; let mut pos = vec![l, h]; for (_, lh, _, rh) in list.iter() { @@ -331,7 +311,7 @@ HyperSphere: symbols::Shape = { "}" => { let space_id = match rs { Some(id) => id, - None => space::name().clone(), + None => Space::universe().name().clone(), }; symbols::Shape::HyperSphere(space_id, c, r) @@ -342,7 +322,7 @@ Point: symbols::Shape = { "point" "{" )?> "}" => { let space_id = match rs { Some(id) => id, - None => space::name().clone(), + None => Space::universe().name().clone(), }; symbols::Shape::Point(space_id, pos) @@ -365,7 +345,7 @@ Nifti: symbols::Shape = { "}" => { let space_id = match rs { Some(id) => id, - None => space::name().clone(), + None => Space::universe().name().clone(), }; symbols::Shape::Nifti(space_id) } @@ -383,7 +363,6 @@ ByteProvider = { "uri" "(" String ")" }; // Always returns a vector of numbers, a.k.a a position (a scalar will // be represented as a vector of one element) Positions: symbols::Position = { - StrCmpICase, StrCmp, Selector => symbols::Position::Selector(<>), Position => symbols::Position::Literal(<>) @@ -399,13 +378,6 @@ StrCmp: symbols::Position = { } }; -// Same, but case insensitive. -StrCmpICase: symbols::Position = { - "str_cmp_ignore_case" "(" "," ")" => { - symbols::Position::StrCmpICase(s, v) - } -}; - // FIXME: FIELDS are expected to be exisiting in the data model. Root Object is assumed to be the type of the ressource on which the POST call was done. Selector: symbols::LiteralSelector = { ( )+ => symbols::LiteralSelector(<>) diff --git a/src/symbols.rs b/src/symbols.rs index 3ea0cbe..a7d91f4 100644 --- a/src/symbols.rs +++ b/src/symbols.rs @@ -1,6 +1,8 @@ use std::cmp::Ordering; -use super::database::space; +use mercator_db::space; +use mercator_db::SpaceObject; + pub use super::types::*; /**********************************************************************/ @@ -63,6 +65,8 @@ pub enum Bag { Bag(Vec), Inside(Shape), Outside(Shape), + //FIXME: ADD A SHAPE VARIANT WHICH JUST RETURNS ALL THE POSITIONS OF THAT SHAPE + //Shape(Shape), } impl Bag { @@ -84,7 +88,7 @@ impl Bag { Bag::Bag(_) => { // Bags can be defined in different spaces, thus the output is // always in the universe space. - space::name() + space::Space::universe().name() } Bag::Inside(shape) => shape.space(), Bag::Outside(shape) => shape.space(), @@ -163,12 +167,12 @@ impl Shape { volume } - Shape::HyperSphere(_space, pos, r) => { + Shape::HyperSphere(_space, pos, radius) => { // Formula from https://en.wikipedia.org/wiki/N-sphere#/media/File:N_SpheresVolumeAndSurfaceArea.png - let LiteralPosition(p) = pos; - let k = p.len(); // Number of dimensions. + let LiteralPosition(position) = pos; + let k = position.len(); // Number of dimensions. - let r = match *r { + let radius = match *radius { LiteralNumber::Int(x) => x as f64, LiteralNumber::Float(x) => x, }; @@ -178,12 +182,12 @@ impl Shape { // Set starting values for the coefficient let mut a = 2.0; - let mut i = 1; - - if (k % 2) == 0 { + let mut i = if (k % 2) == 0 { a = pi; - i = 2; - } + 2 + } else { + 1 + }; while i < k { i += 2; @@ -191,7 +195,7 @@ impl Shape { a /= i as f64; } - a * r.powi(i as i32) + a * radius.powi(i as i32) } Shape::Nifti(_) => unimplemented!(), } @@ -203,12 +207,28 @@ impl Shape { /**********************************************************************/ #[derive(Clone, Debug)] pub enum Position { - StrCmpICase(LiteralSelector, String), StrCmp(LiteralSelector, String), Selector(LiteralSelector), Literal(LiteralPosition), } +impl Position { + pub fn value(&self, object: &SpaceObject) -> LiteralPosition { + match self { + Position::Literal(literal) => literal.clone(), + Position::Selector(selector) => selector.position(object), + Position::StrCmp(selector, literal) => { + let x = match (selector.str(object)).cmp(literal) { + Ordering::Equal => 0, + Ordering::Greater => 1, + Ordering::Less => -1, + }; + LiteralPosition(vec![LiteralNumber::Int(x)]) + } + } + } +} + /**********************************************************************/ /* Literals / TOKENS */ /**********************************************************************/ @@ -222,6 +242,17 @@ pub enum LiteralNumber { Float(f64), } +impl From<&LiteralNumber> for Vec { + fn from(l: &LiteralNumber) -> Self { + let r = match l { + LiteralNumber::Int(x) => (*x) as f64, + LiteralNumber::Float(x) => *x, + }; + + vec![r] + } +} + impl PartialEq for LiteralNumber { fn eq(&self, other: &LiteralNumber) -> bool { match self { @@ -270,6 +301,36 @@ impl LiteralPosition { a } + + pub fn dimensions(&self) -> usize { + self.0.len() + } +} + +impl From<&LiteralNumber> for f64 { + fn from(l: &LiteralNumber) -> Self { + match l { + LiteralNumber::Int(x) => (*x) as f64, + LiteralNumber::Float(x) => *x, + } + } +} + +impl From<&LiteralPosition> for Vec { + fn from(l: &LiteralPosition) -> Self { + let LiteralPosition(v) = l; + let mut r = Vec::with_capacity(v.len()); + + for x in v { + let x = match x { + LiteralNumber::Int(x) => (*x) as f64, + LiteralNumber::Float(x) => *x, + }; + r.push(x); + } + + r + } } impl PartialOrd for LiteralPosition { @@ -316,4 +377,69 @@ impl LiteralSelector { // FIXME: Pretend for now that everything is a number, needs to be actually looked up in data model. LiteralTypes::Int } + + // FIXME: THIS IS SOOO WRONG + pub fn position(&self, object: &SpaceObject) -> LiteralPosition { + println!("LiteralSelector.position(): {:?}", self); + let v: Vec = object.position.clone().into(); + + LiteralPosition(v.into_iter().map(LiteralNumber::Float).collect::>()) + } + + // FIXME: THIS IS SOOO WRONG + pub fn str(&self, object: &SpaceObject) -> String { + let LiteralSelector(v) = self; + let last = v.last(); + if let Some(Field(name, _)) = last { + if name == "id" { + return object.value.id().clone(); + } else if name == "type" { + return object.value.type_name(); + } else if name == "reference_space" { + return object.space_id.clone(); + } + } + + println!("LiteralSelector.str(): {:?}", self); + unimplemented!(); + } +} + +// The logic was getting a bit too complex to be embedded directly into the +// grammar definition. +pub fn get_filter(p: Predicate, b: Option) -> Bag { + match b { + Some(b) => Bag::Filter(Some(p), Box::new(b)), + None => { + let (low, high) = space::Space::universe().bounding_box(); + let low: Vec<_> = low.into(); + let high: Vec<_> = high.into(); + let bb = Shape::HyperRectangle( + space::Space::universe().name().clone(), + vec![ + LiteralPosition( + low.into_iter() + .map(LiteralNumber::Float) + .collect::>(), + ), + LiteralPosition( + high.into_iter() + .map(LiteralNumber::Float) + .collect::>(), + ), + ], + ); + + Bag::Filter(Some(p), Box::new(Bag::Inside(bb))) + } + } +} + +//FIXME: HACK FOR NOW; NEED PROPER TYPE CHECKING! +pub fn get_type() -> LiteralTypes { + LiteralTypes::Vector(vec![ + LiteralTypes::Float, + LiteralTypes::Float, + LiteralTypes::Float, + ]) } diff --git a/src/validators.rs b/src/validators.rs index f15ae0a..69cfcc1 100644 --- a/src/validators.rs +++ b/src/validators.rs @@ -1,5 +1,4 @@ -use super::database::space; -use super::expression::Validator; +use super::expressions::Validator; use super::symbols::*; pub type ValidationResult = Result; @@ -24,7 +23,7 @@ impl Validator for Bag { type ValidationResult = self::ValidationResult; fn validate(&self) -> ValidationResult { - fn compare_bag_types(lh: &Box, rh: &Box) -> ValidationResult { + fn compare_bag_types(lh: &Bag, rh: &Bag) -> ValidationResult { if lh.space().cmp(rh.space()) != std::cmp::Ordering::Equal { return Err(format!( "left and right sets are defined in different reference spaces: '{}' vs '{}'.", @@ -68,7 +67,7 @@ impl Validator for Bag { } } - Ok(space::get_type(space::name()).clone()) + Ok(get_type()) } Bag::Inside(shape) => shape.validate(), Bag::Outside(shape) => shape.validate(),