diff --git a/packages/app/src/benchmarks.ts b/packages/app/src/benchmarks.ts index 29531e4e..c56a7415 100644 --- a/packages/app/src/benchmarks.ts +++ b/packages/app/src/benchmarks.ts @@ -34,7 +34,7 @@ const WasmQueryOptimizer = { const testExpand = (q: QueryOptimizer) => { q.expandFilter({ - kinds: [1, 6, 7, 6969], + kinds: [1,2,3], authors: randomPubkeys }); } diff --git a/packages/system-query/Cargo.lock b/packages/system-query/Cargo.lock index c1a9a84a..067a7bdd 100644 --- a/packages/system-query/Cargo.lock +++ b/packages/system-query/Cargo.lock @@ -2,18 +2,118 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +dependencies = [ + "memchr", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "bumpalo" version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ciborium" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" + +[[package]] +name = "ciborium-ll" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -24,12 +124,112 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "errno" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -41,6 +241,38 @@ dependencies = [ "wasi", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "hermit-abi" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" + +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.11.0" @@ -71,18 +303,92 @@ version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "linux-raw-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" + [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +[[package]] +name = "memchr" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num-traits" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "plotters" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" + +[[package]] +name = "plotters-svg" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -137,18 +443,97 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "regex" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rustix" +version = "0.38.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scoped-tls" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.188" @@ -206,7 +591,8 @@ dependencies = [ name = "system-query" version = "0.1.0" dependencies = [ - "itertools", + "criterion", + "itertools 0.11.0", "rand", "serde", "serde-wasm-bindgen", @@ -215,12 +601,32 @@ dependencies = [ "wasm-bindgen-test", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "walkdir" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -326,3 +732,100 @@ dependencies = [ "js-sys", "wasm-bindgen", ] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/packages/system-query/Cargo.toml b/packages/system-query/Cargo.toml index fb15f816..eb5f616d 100644 --- a/packages/system-query/Cargo.toml +++ b/packages/system-query/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] -crate-type = ["cdylib"] +crate-type = ["cdylib", "rlib"] [dependencies] itertools = "0.11.0" @@ -17,3 +17,8 @@ wasm-bindgen = "0.2.87" rand = "0.8.5" wasm-bindgen-test = "0.3.37" serde_json = "1.0.105" +criterion = { version = "0.5" } + +[[bench]] +name = "basic" +harness = false \ No newline at end of file diff --git a/packages/system-query/benches/basic.rs b/packages/system-query/benches/basic.rs new file mode 100644 index 00000000..1e48e6ab --- /dev/null +++ b/packages/system-query/benches/basic.rs @@ -0,0 +1,65 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use rand::prelude::*; +use std::collections::HashSet; +use system_query::diff::diff_filter; +use system_query::filter::{FlatReqFilter, ReqFilter}; + +fn random_pubkey(rng: &mut ThreadRng) -> String { + let mut bytes = [0u8; 32]; + rng.fill_bytes(&mut bytes); + bytes.iter().map(|byte| format!("{:02x}", byte)).collect() +} + +fn criterion_benchmark(c: &mut Criterion) { + let mut rng = thread_rng(); + let mut random_pubkeys = HashSet::new(); + for _ in 0..50 { + random_pubkeys.insert(random_pubkey(&mut rng)); + } + let input_authors = ReqFilter { + authors: Some(random_pubkeys.clone()), + kinds: Some(HashSet::from([1, 2, 3])), + ids: None, + p_tag: None, + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: None, + until: None, + limit: None, + e_tag: None, + }; + + let input_authors_diff = ReqFilter { + authors: Some(random_pubkeys.clone()), + kinds: Some(HashSet::from([1, 2, 3, 4, 5])), + ids: None, + p_tag: None, + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: None, + until: None, + limit: None, + e_tag: None, + }; + + + c.bench_function("expand", |b| { + b.iter(|| { + let _: Vec = (&input_authors).into(); + }) + }); + c.bench_function("diff", |b| { + b.iter(|| { + let prev: Vec = (&input_authors).into(); + let next: Vec = (&input_authors_diff).into(); + let _ = diff_filter(&prev, &next); + }) + }); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/packages/system-query/src/expand.rs b/packages/system-query/src/expand.rs deleted file mode 100644 index 4871a0fe..00000000 --- a/packages/system-query/src/expand.rs +++ /dev/null @@ -1,446 +0,0 @@ -use crate::{FlatReqFilter, ReqFilter}; -use itertools::Itertools; - -#[derive(Clone)] -enum StringOrNumberEntry<'a> { - String((&'static str, &'a String)), - Number((&'static str, &'a i32)), -} - -pub fn expand_filter(filter: &ReqFilter) -> Vec { - let mut ret: Vec = Vec::new(); - - let mut inputs: Vec> = vec![]; - if let Some(ids) = &filter.ids { - let t_ids = ids - .iter() - .map(|z| StringOrNumberEntry::String(("id", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(authors) = &filter.authors { - let t_ids = authors - .iter() - .map(|z| StringOrNumberEntry::String(("author", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(kinds) = &filter.kinds { - let t_ids = kinds - .iter() - .map(|z| StringOrNumberEntry::Number(("kind", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(e_tags) = &filter.e_tag { - let t_ids = e_tags - .iter() - .map(|z| StringOrNumberEntry::String(("e_tag", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(p_tags) = &filter.p_tag { - let t_ids = p_tags - .iter() - .map(|z| StringOrNumberEntry::String(("p_tag", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(d_tags) = &filter.d_tag { - let t_ids = d_tags - .iter() - .map(|z| StringOrNumberEntry::String(("d_tag", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(t_tags) = &filter.t_tag { - let t_ids = t_tags - .iter() - .map(|z| StringOrNumberEntry::String(("t_tag", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(r_tags) = &filter.r_tag { - let t_ids = r_tags - .iter() - .map(|z| StringOrNumberEntry::String(("r_tag", z))) - .collect_vec(); - inputs.push(t_ids); - } - if let Some(search) = &filter.search { - let t_ids = search - .iter() - .map(|z| StringOrNumberEntry::String(("search", z))) - .collect_vec(); - inputs.push(t_ids); - } - - for p in inputs.iter().multi_cartesian_product() { - ret.push(FlatReqFilter { - id: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("id") { - return Some((*v).to_string()); - } - } - None - }), - author: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("author") { - return Some((*v).to_string()); - } - } - None - }), - kind: p.iter().find_map(|q| { - if let StringOrNumberEntry::Number((k, v)) = q { - if (*k).eq("kind") { - return Some((*v).clone()); - } - } - None - }), - e_tag: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("e_tag") { - return Some((*v).to_string()); - } - } - None - }), - p_tag: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("p_tag") { - return Some((*v).to_string()); - } - } - None - }), - t_tag: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("t_tag") { - return Some((*v).to_string()); - } - } - None - }), - d_tag: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("d_tag") { - return Some((*v).to_string()); - } - } - None - }), - r_tag: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("r_tag") { - return Some((*v).to_string()); - } - } - None - }), - search: p.iter().find_map(|q| { - if let StringOrNumberEntry::String((k, v)) = q { - if (*k).eq("search") { - return Some((*v).to_string()); - } - } - None - }), - since: filter.since, - until: filter.until, - limit: filter.limit, - }) - } - ret -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::ReqFilter; - use std::collections::HashSet; - - #[test] - fn test_expand_filter() { - let input = ReqFilter { - authors: Some(HashSet::from([ - "a".to_owned(), - "b".to_owned(), - "c".to_owned(), - ])), - kinds: Some(HashSet::from([1, 2, 3])), - ids: Some(HashSet::from(["x".to_owned(), "y".to_owned()])), - p_tag: Some(HashSet::from(["a".to_owned()])), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }; - - let output = expand_filter(&input); - output.iter().take(5).for_each(|x| println!("{:?}", x)); - let expected = vec![ - FlatReqFilter { - author: Some("a".to_owned()), - kind: Some(1), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("a".to_owned()), - kind: Some(1), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("a".to_owned()), - kind: Some(2), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("a".to_owned()), - kind: Some(2), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("a".to_owned()), - kind: Some(3), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("a".to_owned()), - kind: Some(3), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("b".to_owned()), - kind: Some(1), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("b".to_owned()), - kind: Some(1), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("b".to_owned()), - kind: Some(2), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("b".to_owned()), - kind: Some(2), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("b".to_owned()), - kind: Some(3), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("b".to_owned()), - kind: Some(3), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("c".to_owned()), - kind: Some(1), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("c".to_owned()), - kind: Some(1), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("c".to_owned()), - kind: Some(2), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("c".to_owned()), - kind: Some(2), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("c".to_owned()), - kind: Some(3), - id: Some("x".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - FlatReqFilter { - author: Some("c".to_owned()), - kind: Some(3), - id: Some("y".to_owned()), - p_tag: Some("a".to_owned()), - t_tag: None, - d_tag: None, - r_tag: None, - search: None, - since: Some(99), - until: None, - limit: Some(10), - e_tag: None, - }, - ]; - assert_eq!(output.len(), expected.len()); - output.iter().for_each(|a| assert!(expected.contains(a))); - } -} diff --git a/packages/system-query/src/filter.rs b/packages/system-query/src/filter.rs index 43f812ef..333b2ee8 100644 --- a/packages/system-query/src/filter.rs +++ b/packages/system-query/src/filter.rs @@ -3,6 +3,13 @@ use std::collections::HashSet; #[cfg(test)] use std::fmt::Debug; use std::hash::Hash; +use itertools::Itertools; + +#[derive(Clone)] +enum StringOrNumberEntry<'a> { + String((&'static str, &'a String)), + Number((&'static str, &'a i32)), +} #[derive(PartialEq, Clone, Serialize, Deserialize)] pub struct ReqFilter { @@ -197,6 +204,157 @@ impl From> for ReqFilter { } } +impl Into> for &ReqFilter { + fn into(self) -> Vec { + let mut ret: Vec = Vec::new(); + + let mut inputs: Vec> = vec![]; + if let Some(ids) = &self.ids { + let t_ids = ids + .iter() + .map(|z| StringOrNumberEntry::String(("id", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(authors) = &self.authors { + let t_ids = authors + .iter() + .map(|z| StringOrNumberEntry::String(("author", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(kinds) = &self.kinds { + let t_ids = kinds + .iter() + .map(|z| StringOrNumberEntry::Number(("kind", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(e_tags) = &self.e_tag { + let t_ids = e_tags + .iter() + .map(|z| StringOrNumberEntry::String(("e_tag", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(p_tags) = &self.p_tag { + let t_ids = p_tags + .iter() + .map(|z| StringOrNumberEntry::String(("p_tag", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(d_tags) = &self.d_tag { + let t_ids = d_tags + .iter() + .map(|z| StringOrNumberEntry::String(("d_tag", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(t_tags) = &self.t_tag { + let t_ids = t_tags + .iter() + .map(|z| StringOrNumberEntry::String(("t_tag", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(r_tags) = &self.r_tag { + let t_ids = r_tags + .iter() + .map(|z| StringOrNumberEntry::String(("r_tag", z))) + .collect(); + inputs.push(t_ids); + } + if let Some(search) = &self.search { + let t_ids = search + .iter() + .map(|z| StringOrNumberEntry::String(("search", z))) + .collect(); + inputs.push(t_ids); + } + + for p in inputs.iter().multi_cartesian_product() { + ret.push(FlatReqFilter { + id: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("id") { + return Some((*v).to_string()); + } + } + None + }), + author: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("author") { + return Some((*v).to_string()); + } + } + None + }), + kind: p.iter().find_map(|q| { + if let StringOrNumberEntry::Number((k, v)) = q { + if (*k).eq("kind") { + return Some((*v).clone()); + } + } + None + }), + e_tag: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("e_tag") { + return Some((*v).to_string()); + } + } + None + }), + p_tag: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("p_tag") { + return Some((*v).to_string()); + } + } + None + }), + t_tag: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("t_tag") { + return Some((*v).to_string()); + } + } + None + }), + d_tag: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("d_tag") { + return Some((*v).to_string()); + } + } + None + }), + r_tag: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("r_tag") { + return Some((*v).to_string()); + } + } + None + }), + search: p.iter().find_map(|q| { + if let StringOrNumberEntry::String((k, v)) = q { + if (*k).eq("search") { + return Some((*v).to_string()); + } + } + None + }), + since: self.since, + until: self.until, + limit: self.limit, + }) + } + ret + } +} impl Distance for ReqFilter { fn distance(&self, b: &Self) -> u32 { let mut ret = 0u32; @@ -285,3 +443,290 @@ fn array_prop_append_vec( } } } + +#[cfg(test)] +mod tests { + use crate::ReqFilter; + use std::collections::HashSet; + use crate::filter::FlatReqFilter; + + #[test] + fn test_expand_filter() { + let input = ReqFilter { + authors: Some(HashSet::from([ + "a".to_owned(), + "b".to_owned(), + "c".to_owned(), + ])), + kinds: Some(HashSet::from([1, 2, 3])), + ids: Some(HashSet::from(["x".to_owned(), "y".to_owned()])), + p_tag: Some(HashSet::from(["a".to_owned()])), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }; + + let output : Vec = (&input).into(); + let expected = vec![ + FlatReqFilter { + author: Some("a".to_owned()), + kind: Some(1), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("a".to_owned()), + kind: Some(1), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("a".to_owned()), + kind: Some(2), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("a".to_owned()), + kind: Some(2), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("a".to_owned()), + kind: Some(3), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("a".to_owned()), + kind: Some(3), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("b".to_owned()), + kind: Some(1), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("b".to_owned()), + kind: Some(1), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("b".to_owned()), + kind: Some(2), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("b".to_owned()), + kind: Some(2), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("b".to_owned()), + kind: Some(3), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("b".to_owned()), + kind: Some(3), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("c".to_owned()), + kind: Some(1), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("c".to_owned()), + kind: Some(1), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("c".to_owned()), + kind: Some(2), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("c".to_owned()), + kind: Some(2), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("c".to_owned()), + kind: Some(3), + id: Some("x".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + FlatReqFilter { + author: Some("c".to_owned()), + kind: Some(3), + id: Some("y".to_owned()), + p_tag: Some("a".to_owned()), + t_tag: None, + d_tag: None, + r_tag: None, + search: None, + since: Some(99), + until: None, + limit: Some(10), + e_tag: None, + }, + ]; + assert_eq!(output.len(), expected.len()); + output.iter().for_each(|a| assert!(expected.contains(a))); + } +} diff --git a/packages/system-query/src/lib.rs b/packages/system-query/src/lib.rs index c5766353..001f2ecc 100644 --- a/packages/system-query/src/lib.rs +++ b/packages/system-query/src/lib.rs @@ -1,10 +1,9 @@ use crate::filter::{FlatReqFilter, ReqFilter}; use wasm_bindgen::prelude::*; -mod diff; -mod expand; -mod filter; -mod merge; +pub mod diff; +pub mod filter; +pub mod merge; #[wasm_bindgen] pub fn diff_filters(prev: JsValue, next: JsValue) -> Result { @@ -17,7 +16,7 @@ pub fn diff_filters(prev: JsValue, next: JsValue) -> Result { #[wasm_bindgen] pub fn expand_filter(val: JsValue) -> Result { let parsed: ReqFilter = serde_wasm_bindgen::from_value(val)?; - let result = expand::expand_filter(&parsed); + let result: Vec = (&parsed).into(); Ok(serde_wasm_bindgen::to_value(&result)?) } @@ -27,11 +26,17 @@ pub fn get_diff(prev: JsValue, next: JsValue) -> Result { let next_parsed: Vec = serde_wasm_bindgen::from_value(next)?; let expanded_prev: Vec = prev_parsed .iter() - .flat_map(|v| expand::expand_filter(v)) + .flat_map(|v| { + let vec: Vec = v.into(); + vec + }) .collect(); let expanded_next: Vec = next_parsed .iter() - .flat_map(|v| expand::expand_filter(v)) + .flat_map(|v| { + let vec: Vec = v.into(); + vec + }) .collect(); let result = diff::diff_filter(&expanded_prev, &expanded_next); Ok(serde_wasm_bindgen::to_value(&result)?) @@ -125,9 +130,12 @@ mod tests { }, ]; - let expanded = input + let expanded: Vec = input .iter() - .flat_map(|v| expand::expand_filter(v)) + .flat_map(|v| { + let r: Vec = v.into(); + r + }) .sorted_by(|_, _| { if rand::random() { Ordering::Less @@ -135,7 +143,7 @@ mod tests { Ordering::Greater } }) - .collect_vec(); + .collect(); let merged_expanded: Vec = merge::merge(expanded.iter().collect()); assert_eq!(merged_expanded.len(), input.len()); assert!(merged_expanded.iter().all(|v| input.contains(v))); diff --git a/packages/system-query/system-query.iml b/packages/system-query/system-query.iml index 2fecef3b..75504b26 100644 --- a/packages/system-query/system-query.iml +++ b/packages/system-query/system-query.iml @@ -3,6 +3,7 @@ +