diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 26bbeb7..deb7544 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,6 +6,8 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 5 groups: github-actions: patterns: @@ -25,6 +27,8 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 5 groups: rust-dependencies: patterns: @@ -43,6 +47,8 @@ updates: schedule: interval: "weekly" day: "monday" + cooldown: + default-days: 5 groups: frontend-dependencies: patterns: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fef3fb2..e3d3a00 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,7 +68,7 @@ jobs: uses: mozilla-actions/sccache-action@v0.0.10 - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@1.96.0 with: components: clippy, rustfmt diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 7877d3e..83990c0 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,7 +33,7 @@ jobs: - name: Install Rust if: matrix.language == 'rust' - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@1.96.0 - name: Autobuild uses: github/codeql-action/autobuild@v4 diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..01a3bee --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "1.96.0" +components = ["clippy", "rustfmt"] diff --git a/src/backend/Cargo.lock b/src/backend/Cargo.lock index 5257e61..aba1959 100644 --- a/src/backend/Cargo.lock +++ b/src/backend/Cargo.lock @@ -1501,7 +1501,7 @@ dependencies = [ [[package]] name = "consensus-config" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "fastcrypto", "mysten-network", @@ -1513,7 +1513,7 @@ dependencies = [ [[package]] name = "consensus-types" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "base64 0.21.7", "consensus-config", @@ -2361,7 +2361,7 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "enum-compat-util" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "serde_yaml", ] @@ -3804,7 +3804,7 @@ dependencies = [ [[package]] name = "jsonrpc" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "serde", "serde_json", @@ -4488,12 +4488,12 @@ dependencies = [ [[package]] name = "move-abstract-interpreter" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" [[package]] name = "move-abstract-interpreter-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-binary-format", ] @@ -4501,17 +4501,17 @@ dependencies = [ [[package]] name = "move-abstract-interpreter-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" [[package]] name = "move-abstract-stack" version = "0.0.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" [[package]] name = "move-binary-format" version = "0.0.3" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "enum-compat-util", @@ -4527,12 +4527,12 @@ dependencies = [ [[package]] name = "move-borrow-graph" version = "0.0.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" [[package]] name = "move-bytecode-source-map" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -4548,7 +4548,7 @@ dependencies = [ [[package]] name = "move-bytecode-utils" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "indexmap 2.13.0", @@ -4561,7 +4561,7 @@ dependencies = [ [[package]] name = "move-bytecode-verifier" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-interpreter", "move-abstract-stack", @@ -4578,7 +4578,7 @@ dependencies = [ [[package]] name = "move-bytecode-verifier-meter" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-binary-format", "move-core-types", @@ -4588,7 +4588,7 @@ dependencies = [ [[package]] name = "move-bytecode-verifier-v0" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-interpreter-v2", "move-abstract-stack", @@ -4603,7 +4603,7 @@ dependencies = [ [[package]] name = "move-bytecode-verifier-v1" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-interpreter-v2", "move-abstract-stack", @@ -4618,7 +4618,7 @@ dependencies = [ [[package]] name = "move-bytecode-verifier-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-interpreter-v2", "move-abstract-stack", @@ -4633,7 +4633,7 @@ dependencies = [ [[package]] name = "move-bytecode-verifier-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-interpreter", "move-abstract-stack", @@ -4650,7 +4650,7 @@ dependencies = [ [[package]] name = "move-command-line-common" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -4670,7 +4670,7 @@ dependencies = [ [[package]] name = "move-compiler" version = "0.0.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -4706,7 +4706,7 @@ dependencies = [ [[package]] name = "move-core-types" version = "0.0.4" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -4728,7 +4728,7 @@ dependencies = [ [[package]] name = "move-coverage" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -4754,7 +4754,7 @@ dependencies = [ [[package]] name = "move-disassembler" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "clap", @@ -4774,7 +4774,7 @@ dependencies = [ [[package]] name = "move-ir-to-bytecode" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "codespan-reporting", @@ -4792,7 +4792,7 @@ dependencies = [ [[package]] name = "move-ir-to-bytecode-syntax" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "hex", @@ -4805,7 +4805,7 @@ dependencies = [ [[package]] name = "move-ir-types" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "hex", "move-command-line-common", @@ -4817,7 +4817,7 @@ dependencies = [ [[package]] name = "move-proc-macros" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "enum-compat-util", "quote", @@ -4827,7 +4827,7 @@ dependencies = [ [[package]] name = "move-regex-borrow-graph" version = "0.0.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "indexmap 2.13.0", "move-binary-format", @@ -4839,7 +4839,7 @@ dependencies = [ [[package]] name = "move-stdlib-natives-v0" version = "0.1.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "hex", "move-binary-format", @@ -4854,7 +4854,7 @@ dependencies = [ [[package]] name = "move-stdlib-natives-v1" version = "0.1.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "hex", "move-binary-format", @@ -4869,7 +4869,7 @@ dependencies = [ [[package]] name = "move-stdlib-natives-v2" version = "0.1.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "hex", "move-binary-format", @@ -4884,7 +4884,7 @@ dependencies = [ [[package]] name = "move-stdlib-natives-v3" version = "0.1.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "hex", "move-binary-format", @@ -4899,7 +4899,7 @@ dependencies = [ [[package]] name = "move-symbol-pool" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "phf", "serde", @@ -4908,7 +4908,7 @@ dependencies = [ [[package]] name = "move-trace-format" version = "0.0.1" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-binary-format", "move-core-types", @@ -4920,7 +4920,7 @@ dependencies = [ [[package]] name = "move-vm-config" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-binary-format", ] @@ -4928,7 +4928,7 @@ dependencies = [ [[package]] name = "move-vm-profiler" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-trace-format", "move-vm-config", @@ -4940,7 +4940,7 @@ dependencies = [ [[package]] name = "move-vm-runtime" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -4970,7 +4970,7 @@ dependencies = [ [[package]] name = "move-vm-runtime-v0" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "better_any", "fail", @@ -4988,7 +4988,7 @@ dependencies = [ [[package]] name = "move-vm-runtime-v1" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "better_any", "fail", @@ -5006,7 +5006,7 @@ dependencies = [ [[package]] name = "move-vm-runtime-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "better_any", "fail", @@ -5024,7 +5024,7 @@ dependencies = [ [[package]] name = "move-vm-runtime-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "better_any", "fail", @@ -5042,7 +5042,7 @@ dependencies = [ [[package]] name = "move-vm-types-v0" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "move-binary-format", @@ -5054,7 +5054,7 @@ dependencies = [ [[package]] name = "move-vm-types-v1" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "move-binary-format", @@ -5066,7 +5066,7 @@ dependencies = [ [[package]] name = "move-vm-types-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "move-binary-format", @@ -5078,7 +5078,7 @@ dependencies = [ [[package]] name = "move-vm-types-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "move-binary-format", @@ -5090,7 +5090,7 @@ dependencies = [ [[package]] name = "msim-macros" version = "0.1.0" -source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=53016c1a9038154b1e47b96f0a314efa7e7d809b#53016c1a9038154b1e47b96f0a314efa7e7d809b" +source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=2c2ec3ffbc1e559c575dc7de1ff2498d1f6700f6#2c2ec3ffbc1e559c575dc7de1ff2498d1f6700f6" dependencies = [ "darling 0.14.4", "proc-macro2", @@ -5147,7 +5147,7 @@ checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" [[package]] name = "mysten-common" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "antithesis_sdk", "either", @@ -5155,10 +5155,12 @@ dependencies = [ "mysten-metrics", "once_cell", "parking_lot 0.12.5", + "prost-types", "rand 0.8.5", "serde_json", "sui-macros", "tempfile", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -5166,7 +5168,7 @@ dependencies = [ [[package]] name = "mysten-metrics" version = "0.7.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "async-trait", "axum", @@ -5187,7 +5189,7 @@ dependencies = [ [[package]] name = "mysten-network" version = "0.2.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anemo", "anemo-tower", @@ -6168,7 +6170,7 @@ dependencies = [ [[package]] name = "prometheus-closure-metric" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "prometheus", @@ -6808,7 +6810,7 @@ dependencies = [ "tokio-rustls", "tokio-util", "tower 0.5.3", - "tower-http 0.6.10", + "tower-http 0.6.11", "tower-service", "url", "wasm-bindgen", @@ -6853,7 +6855,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower 0.5.3", - "tower-http 0.6.10", + "tower-http 0.6.11", "tower-service", "url", "wasm-bindgen", @@ -6908,8 +6910,6 @@ dependencies = [ [[package]] name = "roaring" version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba9ce64a8f45d7fc86358410bb1a82e8c987504c0d4900e9141d69a9f26c885" dependencies = [ "bytemuck", "byteorder", @@ -7469,9 +7469,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "indexmap 2.13.0", "itoa", @@ -7629,7 +7629,7 @@ dependencies = [ [[package]] name = "shared-crypto" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "eyre", @@ -8215,7 +8215,7 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "sui-adapter-latest" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8250,7 +8250,7 @@ dependencies = [ [[package]] name = "sui-adapter-v0" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8278,7 +8278,7 @@ dependencies = [ [[package]] name = "sui-adapter-v1" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8305,7 +8305,7 @@ dependencies = [ [[package]] name = "sui-adapter-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8332,7 +8332,7 @@ dependencies = [ [[package]] name = "sui-adapter-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8367,7 +8367,7 @@ dependencies = [ [[package]] name = "sui-config" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anemo", "anyhow", @@ -8399,7 +8399,7 @@ dependencies = [ [[package]] name = "sui-crypto" version = "0.3.0" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd#f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=5b41bc701525f1b94f1fe63008d4841bc6fb1065#5b41bc701525f1b94f1fe63008d4841bc6fb1065" dependencies = [ "ark-bn254", "ark-ff", @@ -8407,6 +8407,7 @@ dependencies = [ "ark-snark", "ark-std", "base64ct", + "blst", "bnum", "ed25519-dalek", "itertools 0.14.0", @@ -8423,8 +8424,8 @@ dependencies = [ [[package]] name = "sui-display" -version = "1.73.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +version = "1.74.0" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "async-trait", @@ -8447,7 +8448,7 @@ dependencies = [ [[package]] name = "sui-enum-compat-util" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "serde_yaml", ] @@ -8455,7 +8456,7 @@ dependencies = [ [[package]] name = "sui-execution" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-interpreter", "move-abstract-interpreter-v2", @@ -8503,7 +8504,7 @@ dependencies = [ [[package]] name = "sui-http" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bytes", "http", @@ -8520,10 +8521,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "sui-inverted-index" +version = "1.74.0" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" +dependencies = [ + "anyhow", + "async-stream", + "bcs 0.1.6", + "futures", + "move-core-types", + "roaring", + "sui-types", + "thiserror 1.0.69", +] + [[package]] name = "sui-json" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8540,7 +8556,7 @@ dependencies = [ [[package]] name = "sui-json-rpc-api" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "fastcrypto", @@ -8560,7 +8576,7 @@ dependencies = [ [[package]] name = "sui-json-rpc-types" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "bcs 0.1.6", @@ -8595,7 +8611,7 @@ dependencies = [ [[package]] name = "sui-keys" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "async-trait", @@ -8623,7 +8639,7 @@ dependencies = [ [[package]] name = "sui-macros" version = "0.7.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "futures", "once_cell", @@ -8634,7 +8650,7 @@ dependencies = [ [[package]] name = "sui-move-natives-latest" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "better_any", @@ -8655,7 +8671,7 @@ dependencies = [ [[package]] name = "sui-move-natives-v0" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "better_any", @@ -8676,7 +8692,7 @@ dependencies = [ [[package]] name = "sui-move-natives-v1" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "better_any", @@ -8697,7 +8713,7 @@ dependencies = [ [[package]] name = "sui-move-natives-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "better_any", @@ -8718,7 +8734,7 @@ dependencies = [ [[package]] name = "sui-move-natives-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "better_any", @@ -8740,8 +8756,8 @@ dependencies = [ [[package]] name = "sui-name-service" -version = "1.73.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +version = "1.74.0" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "move-core-types", @@ -8752,8 +8768,8 @@ dependencies = [ [[package]] name = "sui-open-rpc" -version = "1.73.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +version = "1.74.0" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "bcs 0.1.6", "schemars 0.8.22", @@ -8765,7 +8781,7 @@ dependencies = [ [[package]] name = "sui-open-rpc-macros" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "derive-syn-parse", "itertools 0.13.0", @@ -8778,7 +8794,7 @@ dependencies = [ [[package]] name = "sui-package-resolver" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "async-trait", "bcs 0.1.6", @@ -8795,7 +8811,7 @@ dependencies = [ [[package]] name = "sui-proc-macros" version = "0.7.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "msim-macros", "proc-macro2", @@ -8807,7 +8823,7 @@ dependencies = [ [[package]] name = "sui-protocol-config" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "clap", "fastcrypto", @@ -8828,7 +8844,7 @@ dependencies = [ [[package]] name = "sui-protocol-config-macros" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "proc-macro2", "quote", @@ -8838,7 +8854,7 @@ dependencies = [ [[package]] name = "sui-rpc" version = "0.3.1" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd#f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=5b41bc701525f1b94f1fe63008d4841bc6fb1065#5b41bc701525f1b94f1fe63008d4841bc6fb1065" dependencies = [ "base64 0.22.1", "bcs 0.1.6", @@ -8850,6 +8866,7 @@ dependencies = [ "prost-types", "serde", "serde_json", + "sui-crypto", "sui-sdk-types", "tap", "tokio", @@ -8861,7 +8878,7 @@ dependencies = [ [[package]] name = "sui-rpc-api" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "async-stream", @@ -8882,11 +8899,13 @@ dependencies = [ "prost-types", "protox", "rand 0.8.5", + "roaring", "serde", "serde_json", "sui-config", "sui-crypto", "sui-display", + "sui-inverted-index", "sui-macros", "sui-name-service", "sui-package-resolver", @@ -8898,6 +8917,7 @@ dependencies = [ "sui-types", "tap", "tokio", + "tokio-util", "tonic", "tonic-health", "tonic-prost", @@ -8911,8 +8931,8 @@ dependencies = [ [[package]] name = "sui-sdk" -version = "1.73.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +version = "1.74.0" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "async-trait", @@ -8948,7 +8968,7 @@ dependencies = [ [[package]] name = "sui-sdk-types" version = "0.3.1" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd#f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=5b41bc701525f1b94f1fe63008d4841bc6fb1065#5b41bc701525f1b94f1fe63008d4841bc6fb1065" dependencies = [ "base64ct", "bcs 0.1.6", @@ -8969,7 +8989,7 @@ dependencies = [ [[package]] name = "sui-transaction-builder" version = "0.0.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anyhow", "async-trait", @@ -8985,7 +9005,7 @@ dependencies = [ [[package]] name = "sui-transaction-checks" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "fastcrypto-zkp", "sui-config", @@ -8999,7 +9019,7 @@ dependencies = [ [[package]] name = "sui-types" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "anemo", "anyhow", @@ -9074,7 +9094,7 @@ dependencies = [ [[package]] name = "sui-verifier-latest" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-stack", "move-binary-format", @@ -9091,7 +9111,7 @@ dependencies = [ [[package]] name = "sui-verifier-v0" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-stack", "move-binary-format", @@ -9107,7 +9127,7 @@ dependencies = [ [[package]] name = "sui-verifier-v1" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-stack", "move-binary-format", @@ -9122,7 +9142,7 @@ dependencies = [ [[package]] name = "sui-verifier-v2" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-stack", "move-binary-format", @@ -9138,7 +9158,7 @@ dependencies = [ [[package]] name = "sui-verifier-v3" version = "0.1.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "move-abstract-stack", "move-binary-format", @@ -9552,9 +9572,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum", @@ -9584,9 +9604,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27aac809edf60b741e2d7db6367214d078856b8a5bff0087e94ff330fb97b6fc" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -9596,9 +9616,9 @@ dependencies = [ [[package]] name = "tonic-health" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dbde2c702c4be12b9b2f6f7e6c824a84a7b7be177070cada8ee575a581af359" +checksum = "fcfab99db777fba2802f0dfa861d1628d1ae916fb199d29819941f139ae85082" dependencies = [ "prost", "tokio", @@ -9609,9 +9629,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c55a2d6a14174563de34409c9f92ff981d006f56da9c6ecd40d9d4a31500b0" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost", @@ -9620,9 +9640,9 @@ dependencies = [ [[package]] name = "tonic-prost-build" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4556786613791cfef4ed134aa670b61a85cfcacf71543ef33e8d801abae988f" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -9636,9 +9656,9 @@ dependencies = [ [[package]] name = "tonic-reflection" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "758112f988818866f38face806ebf8c8961ad2c087e2ba89ad30010ba5fd80c1" +checksum = "acccd136a4bf19810a1fde9c74edc6129b42a66b44d0c1c8aaa67aeb49a146a7" dependencies = [ "prost", "prost-types", @@ -9650,9 +9670,9 @@ dependencies = [ [[package]] name = "tonic-web" -version = "0.14.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d84e41438a9108d27d348e2139ce58cc85bf411aeffb0493f96f992e72a970" +checksum = "b5e6a1b6319ca4b61a4c0f0c94d439c8f3ed344cca56fe0df40e1fe4be11380b" dependencies = [ "base64 0.22.1", "bytes", @@ -9740,9 +9760,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68d6fdd9f81c2819c9a8b0e0cd91660e7746a8e6ea2ba7c6b2b057985f6bcb51" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ "bitflags 2.10.0", "bytes", @@ -9853,7 +9873,7 @@ dependencies = [ [[package]] name = "typed-store-error" version = "0.4.0" -source = "git+https://github.com/MystenLabs/sui#ca9d0e74251f5901ba29db89dcc71e79dd54fefd" +source = "git+https://github.com/MystenLabs/sui#818f8d78f222b9279cb966a5754fb0a2c21d58b1" dependencies = [ "serde", "thiserror 1.0.69", @@ -10151,7 +10171,7 @@ dependencies = [ "sqlx", "sui-sdk", "tokio", - "tower-http 0.6.10", + "tower-http 0.6.11", "tower_governor", "urlencoding", "utoipa", diff --git a/src/backend/Cargo.toml b/src/backend/Cargo.toml index bd3e903..5c0ac5f 100644 --- a/src/backend/Cargo.toml +++ b/src/backend/Cargo.toml @@ -2,19 +2,20 @@ name = "void-eid-backend" version = "0.1.1" edition = "2021" +rust-version = "1.96.0" default-run = "void-eid-backend" [dependencies] axum = "0.8.9" tokio = { version = "1.49.0", features = ["full"] } serde = { version = "1.0.203", features = ["derive"] } -serde_json = "1.0.117" +serde_json = "1.0.150" sqlx = { version = "0.8.6", features = [ "sqlite", "runtime-tokio-native-tls", "chrono", ] } -tower-http = { version = "0.6.10", features = ["cors"] } +tower-http = { version = "0.6.11", features = ["cors"] } tower_governor = "0.8.0" reqwest = { version = "0.13.3", features = ["json", "form", "multipart"] } dotenvy = "0.15.7" @@ -36,3 +37,6 @@ utoipa-swagger-ui = { version = "9.0.2", features = ["axum"] } bcrypt = "0.19.1" sha2 = "0.11.0" hex = "0.4.3" + +[patch.crates-io] +roaring = { path = "../../vendor/roaring" } diff --git a/src/backend/Dockerfile.dev b/src/backend/Dockerfile.dev index d6f3aa8..9782bf2 100644 --- a/src/backend/Dockerfile.dev +++ b/src/backend/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM docker.io/library/rust:latest AS development +FROM docker.io/library/rust:1.96.0 AS development WORKDIR /usr/src/app diff --git a/vendor/roaring/.cargo_vcs_info.json b/vendor/roaring/.cargo_vcs_info.json new file mode 100644 index 0000000..bd8dc02 --- /dev/null +++ b/vendor/roaring/.cargo_vcs_info.json @@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "6a4dda228b8d434b10fdc9306b412d2505b8e3d9" + }, + "path_in_vcs": "roaring" +} \ No newline at end of file diff --git a/vendor/roaring/Cargo.lock b/vendor/roaring/Cargo.lock new file mode 100644 index 0000000..b3ecb28 --- /dev/null +++ b/vendor/roaring/Cargo.lock @@ -0,0 +1,568 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bytemuck" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin", + "stable_deref_trait", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.162" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "postcard" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "heapless", + "serde", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14cae93065090804185d3b75f0bf93b8eeda30c7a9b4a33d3bdb3988d6229e50" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "roaring" +version = "0.11.3" +dependencies = [ + "bytemuck", + "byteorder", + "postcard", + "proptest", + "serde", + "serde_json", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.38.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "2.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/vendor/roaring/Cargo.toml b/vendor/roaring/Cargo.toml new file mode 100644 index 0000000..357f97d --- /dev/null +++ b/vendor/roaring/Cargo.toml @@ -0,0 +1,211 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +rust-version = "1.82.0" +name = "roaring" +version = "0.11.3" +authors = [ + "Wim Looman ", + "Kerollmops ", +] +build = false +autolib = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A better compressed bitset - pure Rust implementation" +documentation = "https://docs.rs/roaring" +readme = "README.md" +keywords = [ + "roaring", + "data-structure", + "bitmap", +] +categories = ["data-structures"] +license = "MIT OR Apache-2.0" +repository = "https://github.com/RoaringBitmap/roaring-rs" + +[features] +default = ["std"] +serde = [ + "dep:serde", + "std", +] +simd = [] +std = [ + "dep:bytemuck", + "dep:byteorder", +] + +[lib] +name = "roaring" +path = "src/lib.rs" + +[[test]] +name = "clone" +path = "tests/clone.rs" + +[[test]] +name = "difference_with" +path = "tests/difference_with.rs" + +[[test]] +name = "intersect_with" +path = "tests/intersect_with.rs" + +[[test]] +name = "is_disjoint" +path = "tests/is_disjoint.rs" + +[[test]] +name = "is_subset" +path = "tests/is_subset.rs" + +[[test]] +name = "iter" +path = "tests/iter.rs" + +[[test]] +name = "iter_advance_to" +path = "tests/iter_advance_to.rs" + +[[test]] +name = "iter_next_range" +path = "tests/iter_next_range.rs" + +[[test]] +name = "iter_range" +path = "tests/iter_range.rs" + +[[test]] +name = "lib" +path = "tests/lib.rs" + +[[test]] +name = "ops" +path = "tests/ops.rs" + +[[test]] +name = "push" +path = "tests/push.rs" + +[[test]] +name = "range_checks" +path = "tests/range_checks.rs" + +[[test]] +name = "rank" +path = "tests/rank.rs" + +[[test]] +name = "select" +path = "tests/select.rs" + +[[test]] +name = "serialization" +path = "tests/serialization.rs" + +[[test]] +name = "size_hint" +path = "tests/size_hint.rs" + +[[test]] +name = "symmetric_difference_with" +path = "tests/symmetric_difference_with.rs" + +[[test]] +name = "treemap_clone" +path = "tests/treemap_clone.rs" + +[[test]] +name = "treemap_difference_with" +path = "tests/treemap_difference_with.rs" + +[[test]] +name = "treemap_intersect_with" +path = "tests/treemap_intersect_with.rs" + +[[test]] +name = "treemap_is_disjoint" +path = "tests/treemap_is_disjoint.rs" + +[[test]] +name = "treemap_is_subset" +path = "tests/treemap_is_subset.rs" + +[[test]] +name = "treemap_iter" +path = "tests/treemap_iter.rs" + +[[test]] +name = "treemap_iter_advance_to" +path = "tests/treemap_iter_advance_to.rs" + +[[test]] +name = "treemap_lib" +path = "tests/treemap_lib.rs" + +[[test]] +name = "treemap_ops" +path = "tests/treemap_ops.rs" + +[[test]] +name = "treemap_rank" +path = "tests/treemap_rank.rs" + +[[test]] +name = "treemap_select" +path = "tests/treemap_select.rs" + +[[test]] +name = "treemap_serialization" +path = "tests/treemap_serialization.rs" + +[[test]] +name = "treemap_size_hint" +path = "tests/treemap_size_hint.rs" + +[[test]] +name = "treemap_symmetric_difference_with" +path = "tests/treemap_symmetric_difference_with.rs" + +[[test]] +name = "treemap_union_with" +path = "tests/treemap_union_with.rs" + +[[test]] +name = "union_with" +path = "tests/union_with.rs" + +[dependencies.bytemuck] +version = "1.21.0" +optional = true + +[dependencies.byteorder] +version = "1.5.0" +optional = true + +[dependencies.serde] +version = "1.0.217" +optional = true + +[dev-dependencies.postcard] +version = "1.1" +features = ["alloc"] + +[dev-dependencies.proptest] +version = "1.6.0" + +[dev-dependencies.serde_json] +version = "1.0.138" diff --git a/vendor/roaring/Cargo.toml.orig b/vendor/roaring/Cargo.toml.orig new file mode 100644 index 0000000..483864f --- /dev/null +++ b/vendor/roaring/Cargo.toml.orig @@ -0,0 +1,33 @@ +[package] +name = "roaring" +version = "0.11.3" +# When changing this value don't forget to change the MSRV test in `.github/workflows/test.yml`!! +rust-version = "1.82.0" +authors = ["Wim Looman ", "Kerollmops "] +description = "A better compressed bitset - pure Rust implementation" + +documentation = "https://docs.rs/roaring" +repository = "https://github.com/RoaringBitmap/roaring-rs" + +readme = "../README.md" +keywords = ["roaring", "data-structure", "bitmap"] +categories = ["data-structures"] +edition = "2021" + +license = "MIT OR Apache-2.0" + +[dependencies] +bytemuck = { workspace = true, optional = true } +byteorder = { workspace = true, optional = true } +serde = { workspace = true, optional = true } + +[features] +default = ["std"] +serde = ["dep:serde", "std"] +simd = [] +std = ["dep:bytemuck", "dep:byteorder"] + +[dev-dependencies] +proptest = { workspace = true } +serde_json = { workspace = true } +postcard = { workspace = true } diff --git a/vendor/roaring/LICENSE-APACHE b/vendor/roaring/LICENSE-APACHE new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/vendor/roaring/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/roaring/LICENSE-MIT b/vendor/roaring/LICENSE-MIT new file mode 100644 index 0000000..e600584 --- /dev/null +++ b/vendor/roaring/LICENSE-MIT @@ -0,0 +1,20 @@ +MIT License +Copyright (c) 2016 The roaring-rs developers. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/roaring/README.md b/vendor/roaring/README.md new file mode 100644 index 0000000..132733a --- /dev/null +++ b/vendor/roaring/README.md @@ -0,0 +1,74 @@ +# RoaringBitmap [![github-actions-badge][]][github-actions] [![release-badge][]][cargo] [![docs-badge][]][docs] [![rust-version-badge][]][rust-version] + +This is a [Rust][] port of the [Roaring bitmap][] data structure, initially +defined as a [Java library][roaring-java] and described in [_Better bitmap +performance with Roaring bitmaps_][roaring-paper]. + +## Rust version policy + +This crate only supports the current stable version of Rust, patch releases may +use new features at any time. + +## Developing + +This project uses [Clippy][], [rustfmt][], and denies warnings in CI builds. Available via +`rustup component add clippy rustfmt`. + +To ensure your changes will be accepted please check them with: +``` +cargo fmt -- --check +cargo clippy --all-targets -- -D warnings +``` + +In addition, ensure all tests are passing with `cargo test` + +### Benchmarking + +It is recommended to run the `cargo bench` command. +The [benchmarks directory](./benchmarks) contains a library that is dedicated to benchmarking the +Roaring library by using a set of [real-world datasets][]. It is also advised to run the benchmarks +on a bare-metal machine, running them on the base branch and then on the contribution PR +branch to better see the changes. + +Those benchmarks are designed on top of the Criterion library, +you can read more about it [on the user guide][]. + +## License + +Licensed under either of + + * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you shall be dual licensed as above, without any +additional terms or conditions. + +[github-actions-badge]: +https://github.com/RoaringBitmap/roaring-rs/actions/workflows/test.yml/badge.svg +[github-actions]: https://github.com/RoaringBitmap/roaring-rs/actions +[release-badge]: https://img.shields.io/github/release/RoaringBitmap/roaring-rs.svg?style=flat-square +[cargo]: https://crates.io/crates/roaring +[docs-badge]: https://img.shields.io/badge/API-docs-blue.svg?style=flat-square +[docs]: https://docs.rs/roaring +[rust-version-badge]: https://img.shields.io/badge/rust-latest%20stable-blue.svg?style=flat-square +[rust-version]: https://github.com/RoaringBitmap/roaring-rs#rust-version-policy + +[Rust]: https://www.rust-lang.org/ +[Roaring bitmap]: https://roaringbitmap.org/ +[roaring-java]: https://github.com/lemire/RoaringBitmap +[roaring-paper]: https://arxiv.org/pdf/1402.6407v4 +[Clippy]: https://github.com/rust-lang/rust-clippy +[rustfmt]: https://github.com/rust-lang/rustfmt + +[real-world datasets]: https://github.com/RoaringBitmap/real-roaring-datasets +[on the user guide]: https://bheisler.github.io/criterion.rs/book/user_guide/user_guide.html + +## Experimental features + +The `simd` feature is in active development. It has not been tested. If you would like to build with `simd` note that +`std::simd` is only available in Rust nightly. diff --git a/vendor/roaring/src/bitmap/arbitrary.rs b/vendor/roaring/src/bitmap/arbitrary.rs new file mode 100644 index 0000000..88eb7d5 --- /dev/null +++ b/vendor/roaring/src/bitmap/arbitrary.rs @@ -0,0 +1,211 @@ +#[cfg(test)] +mod test { + use crate::bitmap::container::{Container, RUN_MAX_SIZE}; + use crate::bitmap::store::{ArrayStore, BitmapStore, IntervalStore, Store}; + use crate::RoaringBitmap; + use core::fmt::{Debug, Formatter}; + use proptest::bits::{BitSetLike, SampledBitSetStrategy}; + use proptest::collection::{vec, SizeRange}; + use proptest::prelude::*; + + #[cfg(not(feature = "std"))] + use alloc::vec::Vec; + + impl Debug for BitmapStore { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + if self.len() < 16 { + write!(f, "BitmapStore<{:?}>", self.iter().collect::>()) + } else { + write!( + f, + "BitmapStore<{:?} values between {:?} and {:?}>", + self.len(), + self.min().unwrap(), + self.max().unwrap() + ) + } + } + } + + impl BitSetLike for BitmapStore { + fn new_bitset(max: usize) -> Self { + assert!(max <= BitmapStore::MAX + 1); + BitmapStore::new() + } + + fn len(&self) -> usize { + BitmapStore::MAX + 1 + } + + fn test(&self, bit: usize) -> bool { + assert!(bit <= BitmapStore::MAX); + self.contains(bit as u16) + } + + fn set(&mut self, bit: usize) { + assert!(bit <= BitmapStore::MAX); + self.insert(bit as u16); + } + + fn clear(&mut self, bit: usize) { + assert!(bit <= BitmapStore::MAX); + self.remove(bit as u16); + } + + fn count(&self) -> usize { + self.len() as usize + } + } + + impl BitmapStore { + const MAX: usize = u16::MAX as usize; + + pub fn sampled( + size: impl Into, + bits: impl Into, + ) -> SampledBitSetStrategy { + SampledBitSetStrategy::new(size.into(), bits.into()) + } + } + + impl BitSetLike for IntervalStore { + fn new_bitset(max: usize) -> Self { + assert!(max <= IntervalStore::MAX + 1); + IntervalStore::new() + } + + fn len(&self) -> usize { + IntervalStore::MAX + 1 + } + + fn test(&self, bit: usize) -> bool { + assert!(bit <= IntervalStore::MAX); + self.contains(bit as u16) + } + + fn set(&mut self, bit: usize) { + assert!(bit <= IntervalStore::MAX); + self.insert(bit as u16); + } + + fn clear(&mut self, bit: usize) { + assert!(bit <= IntervalStore::MAX); + self.remove(bit as u16); + } + + fn count(&self) -> usize { + self.len() as usize + } + } + + impl IntervalStore { + const MAX: usize = u16::MAX as usize; + + pub fn sampled( + size: impl Into, + bits: impl Into, + ) -> SampledBitSetStrategy { + SampledBitSetStrategy::new(size.into(), bits.into()) + } + } + + impl Debug for ArrayStore { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + if self.len() < 16 { + write!(f, "ArrayStore<{:?}>", self.as_slice()) + } else { + write!( + f, + "ArrayStore<{:?} values between {:?} and {:?}>", + self.len(), + self.min().unwrap(), + self.max().unwrap() + ) + } + } + } + + impl BitSetLike for ArrayStore { + fn new_bitset(max: usize) -> Self { + assert!(max <= ArrayStore::MAX + 1); + ArrayStore::new() + } + + fn len(&self) -> usize { + ArrayStore::MAX + 1 + } + + fn test(&self, bit: usize) -> bool { + assert!(bit <= ArrayStore::MAX); + self.contains(bit as u16) + } + + fn set(&mut self, bit: usize) { + assert!(bit <= ArrayStore::MAX); + self.insert(bit as u16); + } + + fn clear(&mut self, bit: usize) { + assert!(bit <= ArrayStore::MAX); + self.remove(bit as u16); + } + + fn count(&self) -> usize { + self.len() as usize + } + } + + impl ArrayStore { + const MAX: usize = u16::MAX as usize; + + pub fn sampled( + size: impl Into, + bits: impl Into, + ) -> SampledBitSetStrategy { + SampledBitSetStrategy::new(size.into(), bits.into()) + } + } + + impl Debug for Store { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Store::Array(a) => write!(f, "Store({a:?})"), + Store::Bitmap(b) => write!(f, "Store({b:?})"), + Store::Run(c) => write!(f, "Store({c:?})"), + } + } + } + + impl Store { + fn arbitrary() -> impl Strategy { + prop_oneof![ + ArrayStore::sampled(1..=4096, ..=u16::MAX as usize).prop_map(Store::Array), + BitmapStore::sampled(4097..u16::MAX as usize, ..=u16::MAX as usize) + .prop_map(Store::Bitmap), + IntervalStore::sampled(1..=RUN_MAX_SIZE as usize, ..=u16::MAX as usize) + .prop_map(Store::Run), + ] + } + } + + prop_compose! { + fn containers(n: usize) + (keys in ArrayStore::sampled(..=n, ..=n), + stores in vec(Store::arbitrary(), n)) -> RoaringBitmap { + let containers = keys.into_iter().zip(stores).map(|(key, store)| { + let mut container = Container { key, store }; + container.ensure_correct_store(); + container + }).collect::>(); + RoaringBitmap { containers } + } + } + + impl RoaringBitmap { + prop_compose! { + pub(crate) fn arbitrary()(bitmap in (0usize..=16).prop_flat_map(containers)) -> RoaringBitmap { + bitmap + } + } + } +} diff --git a/vendor/roaring/src/bitmap/cmp.rs b/vendor/roaring/src/bitmap/cmp.rs new file mode 100644 index 0000000..370bfb0 --- /dev/null +++ b/vendor/roaring/src/bitmap/cmp.rs @@ -0,0 +1,152 @@ +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::iter::Peekable; + +use super::container::Container; +use crate::RoaringBitmap; + +impl RoaringBitmap { + /// Returns true if the set has no elements in common with other. This is equivalent to + /// checking for an empty intersection. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb1 = RoaringBitmap::new(); + /// let mut rb2 = RoaringBitmap::new(); + /// + /// rb1.insert(1); + /// + /// assert_eq!(rb1.is_disjoint(&rb2), true); + /// + /// rb2.insert(1); + /// + /// assert_eq!(rb1.is_disjoint(&rb2), false); + /// + /// ``` + pub fn is_disjoint(&self, other: &Self) -> bool { + Pairs::new(&self.containers, &other.containers) + .filter_map(|(c1, c2)| c1.zip(c2)) + .all(|(c1, c2)| c1.is_disjoint(c2)) + } + + /// Returns `true` if this set is a subset of `other`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb1 = RoaringBitmap::new(); + /// let mut rb2 = RoaringBitmap::new(); + /// + /// rb1.insert(1); + /// + /// assert_eq!(rb1.is_subset(&rb2), false); + /// + /// rb2.insert(1); + /// + /// assert_eq!(rb1.is_subset(&rb2), true); + /// + /// rb1.insert(2); + /// + /// assert_eq!(rb1.is_subset(&rb2), false); + /// ``` + pub fn is_subset(&self, other: &Self) -> bool { + for pair in Pairs::new(&self.containers, &other.containers) { + match pair { + (None, _) => (), + (_, None) => return false, + (Some(c1), Some(c2)) => { + if !c1.is_subset(c2) { + return false; + } + } + } + } + true + } + + /// Returns `true` if this set is a superset of `other`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb1 = RoaringBitmap::new(); + /// let mut rb2 = RoaringBitmap::new(); + /// + /// rb1.insert(1); + /// + /// assert_eq!(rb2.is_superset(&rb1), false); + /// + /// rb2.insert(1); + /// + /// assert_eq!(rb2.is_superset(&rb1), true); + /// + /// rb1.insert(2); + /// + /// assert_eq!(rb2.is_superset(&rb1), false); + /// ``` + pub fn is_superset(&self, other: &Self) -> bool { + other.is_subset(self) + } +} + +/// An helping Iterator over pairs of containers. +/// +/// Returns the smallest container according to its key +/// or both if the key is the same. It is useful when you need +/// to iterate over two containers to do operations on them. +pub(crate) struct Pairs +where + I: Iterator, + J: Iterator, + L: Borrow, + R: Borrow, +{ + left: Peekable, + right: Peekable, +} + +impl Pairs +where + I: Iterator, + J: Iterator, + L: Borrow, + R: Borrow, +{ + pub fn new(left: A, right: B) -> Pairs + where + A: IntoIterator, + B: IntoIterator, + { + Pairs { left: left.into_iter().peekable(), right: right.into_iter().peekable() } + } +} + +impl Iterator for Pairs +where + I: Iterator, + J: Iterator, + L: Borrow, + R: Borrow, +{ + type Item = (Option, Option); + + fn next(&mut self) -> Option { + match (self.left.peek(), self.right.peek()) { + (None, None) => None, + (Some(_), None) => Some((self.left.next(), None)), + (None, Some(_)) => Some((None, self.right.next())), + (Some(c1), Some(c2)) => match c1.borrow().key.cmp(&c2.borrow().key) { + Ordering::Equal => Some((self.left.next(), self.right.next())), + Ordering::Less => Some((self.left.next(), None)), + Ordering::Greater => Some((None, self.right.next())), + }, + } + } +} diff --git a/vendor/roaring/src/bitmap/container.rs b/vendor/roaring/src/bitmap/container.rs new file mode 100644 index 0000000..b11a644 --- /dev/null +++ b/vendor/roaring/src/bitmap/container.rs @@ -0,0 +1,482 @@ +use core::fmt; +use core::ops::{ + BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, RangeInclusive, Sub, SubAssign, +}; + +use super::store::{self, ArrayStore, Interval, IntervalStore, Store, BITMAP_BYTES}; +use super::util; + +pub const ARRAY_LIMIT: u64 = 4096; +#[cfg(test)] +pub const RUN_MAX_SIZE: u64 = 2048; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +#[derive(PartialEq, Eq, Clone)] +pub(crate) struct Container { + pub key: u16, + pub store: Store, +} + +#[derive(Clone)] +pub(crate) struct Iter<'a> { + pub key: u16, + inner: store::Iter<'a>, +} + +impl Container { + pub fn new(key: u16) -> Container { + Container { key, store: Store::new() } + } + + pub fn new_with_range(key: u16, range: RangeInclusive) -> Container { + if range.len() <= 2 { + let mut array = ArrayStore::new(); + array.insert_range(range); + Self { key, store: Store::Array(array) } + } else { + Self { + key, + store: Store::Run(IntervalStore::new_with_range( + // This is ok, since range must be non empty + Interval::new_unchecked(*range.start(), *range.end()), + )), + } + } + } + + pub fn full(key: u16) -> Container { + Container { key, store: Store::full() } + } + + pub fn from_lsb0_bytes(key: u16, bytes: &[u8], byte_offset: usize) -> Option { + Some(Container { key, store: Store::from_lsb0_bytes(bytes, byte_offset)? }) + } +} + +impl Container { + pub fn len(&self) -> u64 { + self.store.len() + } + + pub fn is_empty(&self) -> bool { + self.store.is_empty() + } + + #[inline] + pub fn insert(&mut self, index: u16) -> bool { + if self.store.insert(index) { + self.ensure_correct_store(); + true + } else { + false + } + } + + pub fn insert_range(&mut self, range: RangeInclusive) -> u64 { + if range.is_empty() { + return 0; + } + match &self.store { + Store::Bitmap(bitmap) => { + let added_amount = range.len() as u64 + - bitmap.intersection_len_interval(&Interval::new_unchecked( + *range.start(), + *range.end(), + )); + let union_cardinality = bitmap.len() + added_amount; + if union_cardinality == 1 << 16 { + self.store = Store::Run(IntervalStore::full()); + added_amount + } else { + self.store.insert_range(range) + } + } + Store::Array(array) => { + let added_amount = range.len() as u64 + - array.intersection_len_interval(&Interval::new_unchecked( + *range.start(), + *range.end(), + )); + let union_cardinality = array.len() + added_amount; + if union_cardinality == 1 << 16 { + self.store = Store::Run(IntervalStore::full()); + added_amount + } else if union_cardinality <= ARRAY_LIMIT { + self.store.insert_range(range) + } else { + self.store = self.store.to_bitmap(); + self.store.insert_range(range) + } + } + Store::Run(_) => self.store.insert_range(range), + } + } + + /// Pushes `index` at the end of the container only if `index` is the new max. + /// + /// Returns whether the `index` was effectively pushed. + pub fn push(&mut self, index: u16) -> bool { + if self.store.push(index) { + self.ensure_correct_store(); + true + } else { + false + } + } + + /// + /// Pushes `index` at the end of the container. + /// It is up to the caller to have validated index > self.max() + /// + /// # Panics + /// + /// If debug_assertions enabled and index is > self.max() + pub(crate) fn push_unchecked(&mut self, index: u16) { + self.store.push_unchecked(index); + self.ensure_correct_store(); + } + + pub fn remove(&mut self, index: u16) -> bool { + if self.store.remove(index) { + self.ensure_correct_store(); + true + } else { + false + } + } + + pub fn remove_range(&mut self, range: RangeInclusive) -> u64 { + let result = self.store.remove_range(range); + self.ensure_correct_store(); + result + } + + pub fn remove_smallest(&mut self, n: u64) { + match &self.store { + Store::Bitmap(bits) => { + if bits.len() - n <= ARRAY_LIMIT { + let mut replace_array = Vec::with_capacity((bits.len() - n) as usize); + replace_array.extend(bits.iter().skip(n as usize)); + self.store = Store::Array(store::ArrayStore::from_vec_unchecked(replace_array)); + } else { + self.store.remove_smallest(n) + } + } + Store::Array(_) => self.store.remove_smallest(n), + Store::Run(_) => self.store.remove_smallest(n), + }; + } + + pub fn remove_biggest(&mut self, n: u64) { + match &self.store { + Store::Bitmap(bits) => { + if bits.len() - n <= ARRAY_LIMIT { + let mut replace_array = Vec::with_capacity((bits.len() - n) as usize); + replace_array.extend(bits.iter().take((bits.len() - n) as usize)); + self.store = Store::Array(store::ArrayStore::from_vec_unchecked(replace_array)); + } else { + self.store.remove_biggest(n) + } + } + Store::Array(_) => self.store.remove_biggest(n), + Store::Run(_) => self.store.remove_biggest(n), + }; + } + + pub fn contains(&self, index: u16) -> bool { + self.store.contains(index) + } + + pub fn contains_range(&self, range: RangeInclusive) -> bool { + self.store.contains_range(range) + } + + pub fn is_full(&self) -> bool { + self.store.is_full() + } + + pub fn is_disjoint(&self, other: &Self) -> bool { + self.store.is_disjoint(&other.store) + } + + pub fn is_subset(&self, other: &Self) -> bool { + self.len() <= other.len() && self.store.is_subset(&other.store) + } + + pub fn intersection_len(&self, other: &Self) -> u64 { + self.store.intersection_len(&other.store) + } + + pub fn min(&self) -> Option { + self.store.min() + } + + #[inline] + pub fn max(&self) -> Option { + self.store.max() + } + + pub fn rank(&self, index: u16) -> u64 { + self.store.rank(index) + } + + pub(crate) fn ensure_correct_store(&mut self) -> bool { + let new_store = match &self.store { + Store::Bitmap(ref bits) if bits.len() <= ARRAY_LIMIT => { + Store::Array(bits.to_array_store()).into() + } + Store::Array(ref vec) if vec.len() > ARRAY_LIMIT => { + Store::Bitmap(vec.to_bitmap_store()).into() + } + _ => None, + }; + if let Some(new_store) = new_store { + self.store = new_store; + true + } else { + false + } + } + + pub fn optimize(&mut self) -> bool { + match &mut self.store { + Store::Bitmap(_) => { + let num_runs = self.store.count_runs(); + let size_as_run = IntervalStore::serialized_byte_size(num_runs); + if BITMAP_BYTES <= size_as_run { + return false; + } + self.store = self.store.to_run(); + true + } + Store::Array(array) => { + let size_as_array = array.byte_size(); + let num_runs = self.store.count_runs(); + let size_as_run = IntervalStore::serialized_byte_size(num_runs); + if size_as_array <= size_as_run { + return false; + } + self.store = self.store.to_run(); + true + } + Store::Run(runs) => { + let size_as_run = runs.byte_size(); + let card = runs.len(); + let size_as_array = ArrayStore::serialized_byte_size(card); + let min_size_non_run = size_as_array.min(BITMAP_BYTES); + if size_as_run <= min_size_non_run { + return false; + } + if card <= ARRAY_LIMIT { + self.store = Store::Array(runs.to_array()); + return true; + } + self.store = Store::Bitmap(runs.to_bitmap()); + true + } + } + } + + pub fn remove_run_compression(&mut self) -> bool { + match &mut self.store { + Store::Bitmap(_) | Store::Array(_) => false, + Store::Run(runs) => { + let card = runs.len(); + if card <= ARRAY_LIMIT { + self.store = Store::Array(runs.to_array()); + } else { + self.store = Store::Bitmap(runs.to_bitmap()); + } + true + } + } + } +} + +impl BitOr<&Container> for &Container { + type Output = Container; + + fn bitor(self, rhs: &Container) -> Container { + let store = BitOr::bitor(&self.store, &rhs.store); + let mut container = Container { key: self.key, store }; + container.ensure_correct_store(); + container + } +} + +impl BitOrAssign for Container { + fn bitor_assign(&mut self, rhs: Container) { + BitOrAssign::bitor_assign(&mut self.store, rhs.store); + self.ensure_correct_store(); + } +} + +impl BitOrAssign<&Container> for Container { + fn bitor_assign(&mut self, rhs: &Container) { + BitOrAssign::bitor_assign(&mut self.store, &rhs.store); + self.ensure_correct_store(); + } +} + +impl BitAnd<&Container> for &Container { + type Output = Container; + + fn bitand(self, rhs: &Container) -> Container { + let store = BitAnd::bitand(&self.store, &rhs.store); + let mut container = Container { key: self.key, store }; + container.ensure_correct_store(); + container + } +} + +impl BitAndAssign for Container { + fn bitand_assign(&mut self, rhs: Container) { + BitAndAssign::bitand_assign(&mut self.store, rhs.store); + self.ensure_correct_store(); + } +} + +impl BitAndAssign<&Container> for Container { + fn bitand_assign(&mut self, rhs: &Container) { + BitAndAssign::bitand_assign(&mut self.store, &rhs.store); + self.ensure_correct_store(); + } +} + +impl Sub<&Container> for &Container { + type Output = Container; + + fn sub(self, rhs: &Container) -> Container { + let store = Sub::sub(&self.store, &rhs.store); + let mut container = Container { key: self.key, store }; + container.ensure_correct_store(); + container + } +} + +impl SubAssign<&Container> for Container { + fn sub_assign(&mut self, rhs: &Container) { + SubAssign::sub_assign(&mut self.store, &rhs.store); + self.ensure_correct_store(); + } +} + +impl BitXor<&Container> for &Container { + type Output = Container; + + fn bitxor(self, rhs: &Container) -> Container { + let store = BitXor::bitxor(&self.store, &rhs.store); + let mut container = Container { key: self.key, store }; + container.ensure_correct_store(); + container + } +} + +impl BitXorAssign for Container { + fn bitxor_assign(&mut self, rhs: Container) { + BitXorAssign::bitxor_assign(&mut self.store, rhs.store); + self.ensure_correct_store(); + } +} + +impl BitXorAssign<&Container> for Container { + fn bitxor_assign(&mut self, rhs: &Container) { + BitXorAssign::bitxor_assign(&mut self.store, &rhs.store); + self.ensure_correct_store(); + } +} + +impl<'a> IntoIterator for &'a Container { + type Item = u32; + type IntoIter = Iter<'a>; + + fn into_iter(self) -> Iter<'a> { + let store: &Store = &self.store; + Iter { key: self.key, inner: store.into_iter() } + } +} + +impl IntoIterator for Container { + type Item = u32; + type IntoIter = Iter<'static>; + + fn into_iter(self) -> Iter<'static> { + Iter { key: self.key, inner: self.store.into_iter() } + } +} + +impl Iterator for Iter<'_> { + type Item = u32; + fn next(&mut self) -> Option { + self.inner.next().map(|i| util::join(self.key, i)) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + fn count(self) -> usize + where + Self: Sized, + { + self.inner.count() + } + + fn nth(&mut self, n: usize) -> Option { + self.inner.nth(n).map(|i| util::join(self.key, i)) + } +} + +impl DoubleEndedIterator for Iter<'_> { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|i| util::join(self.key, i)) + } +} + +impl ExactSizeIterator for Iter<'_> {} + +impl Iter<'_> { + pub(crate) fn peek(&self) -> Option { + self.inner.peek().map(|i| util::join(self.key, i)) + } + + pub(crate) fn peek_back(&self) -> Option { + self.inner.peek_back().map(|i| util::join(self.key, i)) + } + + pub(crate) fn advance_to(&mut self, index: u16) { + self.inner.advance_to(index); + } + + pub(crate) fn advance_back_to(&mut self, index: u16) { + self.inner.advance_back_to(index); + } + + /// Returns the range of consecutive set bits from the current position to the end of the current run + /// + /// After this call, the iterator will be positioned at the first item after the returned range. + /// Returns `None` if the iterator is exhausted. + pub(crate) fn next_range(&mut self) -> Option> { + self.inner + .next_range() + .map(|r| util::join(self.key, *r.start())..=util::join(self.key, *r.end())) + } + + /// Returns the range of consecutive set bits from the start of the current run to the current back position + /// + /// After this call, the back of the iterator will be positioned at the last item before the returned range. + /// Returns `None` if the iterator is exhausted. + pub(crate) fn next_range_back(&mut self) -> Option> { + self.inner + .next_range_back() + .map(|r| util::join(self.key, *r.start())..=util::join(self.key, *r.end())) + } +} + +impl fmt::Debug for Container { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + format!("Container<{:?} @ {:?}>", self.len(), self.key).fmt(formatter) + } +} diff --git a/vendor/roaring/src/bitmap/fmt.rs b/vendor/roaring/src/bitmap/fmt.rs new file mode 100644 index 0000000..af767bd --- /dev/null +++ b/vendor/roaring/src/bitmap/fmt.rs @@ -0,0 +1,23 @@ +use core::fmt; + +use crate::RoaringBitmap; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl fmt::Debug for RoaringBitmap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.len() < 16 { + write!(f, "RoaringBitmap<{:?}>", self.iter().collect::>()) + } else { + write!( + f, + "RoaringBitmap<{:?} values between {:?} and {:?} in {:?} containers>", + self.len(), + self.min().unwrap(), + self.max().unwrap(), + self.containers.len(), + ) + } + } +} diff --git a/vendor/roaring/src/bitmap/inherent.rs b/vendor/roaring/src/bitmap/inherent.rs new file mode 100644 index 0000000..cbaa6b5 --- /dev/null +++ b/vendor/roaring/src/bitmap/inherent.rs @@ -0,0 +1,1198 @@ +use core::cmp::Ordering; +use core::mem::size_of; +use core::ops::{RangeBounds, RangeInclusive}; + +use crate::bitmap::store::BITMAP_LENGTH; +use crate::{IntegerTooSmall, RoaringBitmap}; + +use super::container::Container; +use super::util; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl RoaringBitmap { + /// Creates an empty `RoaringBitmap`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// let rb = RoaringBitmap::new(); + /// ``` + pub fn new() -> RoaringBitmap { + RoaringBitmap { containers: Vec::new() } + } + + /// Creates a full `RoaringBitmap`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// let rb = RoaringBitmap::full(); + /// ``` + pub fn full() -> RoaringBitmap { + RoaringBitmap { containers: (0..=u16::MAX).map(Container::full).collect() } + } + + /// Creates a `RoaringBitmap` from a byte slice, interpreting the bytes as a bitmap with a specified offset. + /// + /// # Arguments + /// + /// - `offset: u32` - The starting position in the bitmap where the byte slice will be applied, specified in bits. + /// This means that if `offset` is `n`, the first byte in the slice will correspond to the `n`th bit(0-indexed) in the bitmap. + /// - `bytes: &[u8]` - The byte slice containing the bitmap data. The bytes are interpreted in "Least-Significant-First" bit order. + /// + /// # Interpretation of `bytes` + /// + /// The `bytes` slice is interpreted in "Least-Significant-First" bit order. Each byte is read from least significant bit (LSB) to most significant bit (MSB). + /// For example, the byte `0b00000101` represents the bits `1, 0, 1, 0, 0, 0, 0, 0` in that order (see Examples section). + /// + /// + /// # Panics + /// + /// This function will panic if `bytes.len() + offset` is greater than 2^32. + /// + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let bytes = [0b00000101, 0b00000010, 0b00000000, 0b10000000]; + /// // ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ + /// // 76543210 98 + /// let rb = RoaringBitmap::from_lsb0_bytes(0, &bytes); + /// assert!(rb.contains(0)); + /// assert!(!rb.contains(1)); + /// assert!(rb.contains(2)); + /// assert!(rb.contains(9)); + /// assert!(rb.contains(31)); + /// + /// let rb = RoaringBitmap::from_lsb0_bytes(8, &bytes); + /// assert!(rb.contains(8)); + /// assert!(!rb.contains(9)); + /// assert!(rb.contains(10)); + /// assert!(rb.contains(17)); + /// assert!(rb.contains(39)); + /// + /// let rb = RoaringBitmap::from_lsb0_bytes(3, &bytes); + /// assert!(rb.contains(3)); + /// assert!(!rb.contains(4)); + /// assert!(rb.contains(5)); + /// assert!(rb.contains(12)); + /// assert!(rb.contains(34)); + /// ``` + pub fn from_lsb0_bytes(offset: u32, mut bytes: &[u8]) -> RoaringBitmap { + fn shift_bytes(bytes: &[u8], amount: usize) -> Vec { + let mut result = Vec::with_capacity(bytes.len() + 1); + let mut carry = 0u8; + + for &byte in bytes { + let shifted = (byte << amount) | carry; + carry = byte >> (8 - amount); + result.push(shifted); + } + + if carry != 0 { + result.push(carry); + } + + result + } + if offset % 8 != 0 { + let shift = offset as usize % 8; + let shifted_bytes = shift_bytes(bytes, shift); + return RoaringBitmap::from_lsb0_bytes(offset - shift as u32, &shifted_bytes); + } + + if bytes.is_empty() { + return RoaringBitmap::new(); + } + + // Using inclusive range avoids overflow: the max exclusive value is 2^32 (u32::MAX + 1). + let end_bit_inc = u32::try_from(bytes.len()) + .ok() + .and_then(|len_bytes| len_bytes.checked_mul(8)) + // `bytes` is non-empty, so len_bits is > 0 + .and_then(|len_bits| offset.checked_add(len_bits - 1)) + .expect("offset + bytes.len() must be <= 2^32"); + + // offsets are in bytes + let (mut start_container, start_offset) = + (offset as usize >> 16, (offset as usize % 0x1_0000) / 8); + let (end_container_inc, end_offset) = + (end_bit_inc as usize >> 16, (end_bit_inc as usize % 0x1_0000 + 1) / 8); + + let n_containers_needed = end_container_inc + 1 - start_container; + let mut containers = Vec::with_capacity(n_containers_needed); + + // Handle a partial first container + if start_offset != 0 { + let end_byte = if end_container_inc == start_container { + end_offset + } else { + BITMAP_LENGTH * size_of::() + }; + + let (src, rest) = bytes.split_at(end_byte - start_offset); + bytes = rest; + + if let Some(container) = + Container::from_lsb0_bytes(start_container as u16, src, start_offset) + { + containers.push(container); + } + + start_container += 1; + } + + // Handle all full containers + for full_container_key in start_container..end_container_inc { + let (src, rest) = bytes.split_at(BITMAP_LENGTH * size_of::()); + bytes = rest; + + if let Some(container) = Container::from_lsb0_bytes(full_container_key as u16, src, 0) { + containers.push(container); + } + } + + // Handle a last container + if !bytes.is_empty() { + if let Some(container) = Container::from_lsb0_bytes(end_container_inc as u16, bytes, 0) + { + containers.push(container); + } + } + + RoaringBitmap { containers } + } + + /// Adds a value to the set. + /// + /// Returns whether the value was absent from the set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.insert(3), true); + /// assert_eq!(rb.insert(3), false); + /// assert_eq!(rb.contains(3), true); + /// ``` + #[inline] + pub fn insert(&mut self, value: u32) -> bool { + let (key, index) = util::split(value); + let container = match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => &mut self.containers[loc], + Err(loc) => { + self.containers.insert(loc, Container::new(key)); + &mut self.containers[loc] + } + }; + container.insert(index) + } + + /// Searches for the specific container by the given key. + /// Creates a new container if it doesn't exist. + /// + /// Return the index of the target container. + #[inline] + pub(crate) fn find_container_by_key(&mut self, key: u16) -> usize { + match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => loc, + Err(loc) => { + self.containers.insert(loc, Container::new(key)); + loc + } + } + } + + /// Searches and then modifies a specific container with `M` by the given key. + /// Creates a new container using `B` if it doesn't exist. + /// + /// Returns `R` based on `M` or `B`. + #[inline] + pub(crate) fn mod_or_build_container_by_key< + R, + M: FnMut(&mut Container) -> R, + B: FnMut(u16) -> (Container, R), + >( + &mut self, + key: u16, + mut modifier: M, + mut builder: B, + ) -> R { + match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => modifier(&mut self.containers[loc]), + Err(loc) => { + let build_value = builder(key); + self.containers.insert(loc, build_value.0); + build_value.1 + } + } + } + + /// Inserts a range of values. + /// Returns the number of inserted values. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.insert_range(2..4); + /// assert!(rb.contains(2)); + /// assert!(rb.contains(3)); + /// assert!(!rb.contains(4)); + /// ``` + #[inline] + pub fn insert_range(&mut self, range: R) -> u64 + where + R: RangeBounds, + { + let (start, end) = match util::convert_range_to_inclusive(range) { + Ok(range) => (*range.start(), *range.end()), + Err(_) => return 0, + }; + + let (start_container_key, start_index) = util::split(start); + let (end_container_key, end_index) = util::split(end); + let modify_container_range = + |bitmap: &mut Self, container_key: u16, range: RangeInclusive| { + bitmap.mod_or_build_container_by_key( + container_key, + |container| container.insert_range(range.clone()), + |key| (Container::new_with_range(key, range.clone()), range.len() as u64), + ) + }; + + // If the end range value is in the same container, just call into + // the one container. + if start_container_key == end_container_key { + return modify_container_range(self, start_container_key, start_index..=end_index); + } + + // For the first container, insert start_index..=u16::MAX, with + // subsequent containers inserting 0..MAX. + // + // The last container (end_container_key) is handled explicitly outside + // the loop. + let mut low = start_index; + let mut inserted = 0; + + for i in start_container_key..end_container_key { + inserted += modify_container_range(self, i, low..=u16::MAX); + + // After the first container, always fill the containers. + low = 0; + } + + // Handle the last container + inserted += modify_container_range(self, end_container_key, 0..=end_index); + + inserted + } + + /// Pushes `value` in the bitmap only if it is greater than the current maximum value. + /// + /// Returns whether the value was inserted. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert!(rb.push(1)); + /// assert!(rb.push(3)); + /// assert_eq!(rb.push(3), false); + /// assert!(rb.push(5)); + /// + /// assert_eq!(rb.iter().collect::>(), vec![1, 3, 5]); + /// ``` + #[inline] + #[deprecated(since = "0.11.0", note = "use `try_push` instead")] + pub fn push(&mut self, value: u32) -> bool { + self.try_push(value).is_ok() + } + + /// Pushes `value` in the bitmap only if it is greater than the current maximum value. + /// + /// Returns an error if the value is not greater than the current maximum value. + /// + /// # Examples + /// + /// ```rust + /// use roaring::{RoaringBitmap, IntegerTooSmall}; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert!(rb.try_push(1).is_ok()); + /// assert!(rb.try_push(3).is_ok()); + /// assert_eq!(rb.try_push(3), Err(IntegerTooSmall)); + /// assert!(rb.try_push(5).is_ok()); + /// + /// assert_eq!(rb.iter().collect::>(), vec![1, 3, 5]); + /// ``` + #[inline] + pub fn try_push(&mut self, value: u32) -> Result<(), IntegerTooSmall> { + let (key, index) = util::split(value); + + match self.containers.last_mut() { + Some(container) if container.key == key => { + if container.push(index) { + Ok(()) + } else { + Err(IntegerTooSmall) + } + } + Some(container) if container.key > key => Err(IntegerTooSmall), + _otherwise => { + let mut container = Container::new(key); + container.push(index); + self.containers.push(container); + Ok(()) + } + } + } + + /// Pushes `value` at the end of the bitmap. + /// It is up to the caller to have validated index > self.max() + /// + /// # Panics + /// + /// If debug_assertions enabled and index is > self.max() + #[inline] + pub(crate) fn push_unchecked(&mut self, value: u32) { + let (key, index) = util::split(value); + + match self.containers.last_mut() { + Some(container) if container.key == key => container.push_unchecked(index), + Some(container) if cfg!(debug_assertions) && container.key > key => { + panic!("last container key > key of value") + } + _otherwise => { + let mut container = Container::new(key); + container.push_unchecked(index); + self.containers.push(container); + } + } + } + + /// Removes a value from the set. Returns `true` if the value was present in the set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.insert(3); + /// assert_eq!(rb.remove(3), true); + /// assert_eq!(rb.remove(3), false); + /// assert_eq!(rb.contains(3), false); + /// ``` + #[inline] + pub fn remove(&mut self, value: u32) -> bool { + let (key, index) = util::split(value); + match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => { + if self.containers[loc].remove(index) { + if self.containers[loc].is_empty() { + self.containers.remove(loc); + } + true + } else { + false + } + } + _ => false, + } + } + + /// Removes a range of values. + /// Returns the number of removed values. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.insert(2); + /// rb.insert(3); + /// assert_eq!(rb.remove_range(2..4), 2); + /// ``` + #[inline] + pub fn remove_range(&mut self, range: R) -> u64 + where + R: RangeBounds, + { + let (start, end) = match util::convert_range_to_inclusive(range) { + Ok(range) => (*range.start(), *range.end()), + Err(_) => return 0, + }; + + let (start_container_key, start_index) = util::split(start); + let (end_container_key, end_index) = util::split(end); + + let mut index = 0; + let mut removed = 0; + while index < self.containers.len() { + let key = self.containers[index].key; + if key >= start_container_key && key <= end_container_key { + let a = if key == start_container_key { start_index } else { 0 }; + let b = if key == end_container_key { end_index } else { u16::MAX }; + removed += self.containers[index].remove_range(a..=b); + if self.containers[index].is_empty() { + self.containers.remove(index); + continue; + } + } + index += 1; + } + removed + } + + /// Returns `true` if this set contains the specified integer. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.insert(1); + /// assert_eq!(rb.contains(0), false); + /// assert_eq!(rb.contains(1), true); + /// assert_eq!(rb.contains(100), false); + /// ``` + #[inline] + pub fn contains(&self, value: u32) -> bool { + let (key, index) = util::split(value); + match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => self.containers[loc].contains(index), + Err(_) => false, + } + } + + /// Returns `true` if all values in the range are present in this set. + /// + /// # Examples + /// + /// ``` + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// // An empty range is always contained + /// assert!(rb.contains_range(7..7)); + /// + /// rb.insert_range(1..0xFFF); + /// assert!(rb.contains_range(1..0xFFF)); + /// assert!(rb.contains_range(2..0xFFF)); + /// // 0 is not contained + /// assert!(!rb.contains_range(0..2)); + /// // 0xFFF is not contained + /// assert!(!rb.contains_range(1..=0xFFF)); + /// ``` + #[inline] + pub fn contains_range(&self, range: R) -> bool + where + R: RangeBounds, + { + let (start, end) = match util::convert_range_to_inclusive(range) { + Ok(range) => (*range.start(), *range.end()), + // Empty/Invalid ranges are always contained + Err(_) => return true, + }; + let (start_high, start_low) = util::split(start); + let (end_high, end_low) = util::split(end); + debug_assert!(start_high <= end_high); + + let containers = + match self.containers.binary_search_by_key(&start_high, |container| container.key) { + Ok(i) => &self.containers[i..], + Err(_) => return false, + }; + + if start_high == end_high { + return containers[0].contains_range(start_low..=end_low); + } + + let high_span = usize::from(end_high - start_high); + // If this contains everything in the range, there should be a container for every item in the span + // and the container that many items away should be the high key + let containers = match containers.get(high_span) { + Some(c) if c.key == end_high => &containers[..=high_span], + _ => return false, + }; + + match containers { + [first, rest @ .., last] => { + first.contains_range(start_low..=u16::MAX) + && rest.iter().all(|container| container.is_full()) + && last.contains_range(0..=end_low) + } + _ => unreachable!("already validated containers has at least 2 items"), + } + } + + /// Returns the number of elements in this set which are in the passed range. + /// + /// # Examples + /// + /// ``` + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.insert_range(0x10000..0x40000); + /// rb.insert(0x50001); + /// rb.insert(0x50005); + /// rb.insert(u32::MAX); + /// + /// assert_eq!(rb.range_cardinality(0..0x10000), 0); + /// assert_eq!(rb.range_cardinality(0x10000..0x40000), 0x30000); + /// assert_eq!(rb.range_cardinality(0x50000..0x60000), 2); + /// assert_eq!(rb.range_cardinality(0x10000..0x10000), 0); + /// assert_eq!(rb.range_cardinality(0x50000..=u32::MAX), 3); + /// ``` + #[inline] + pub fn range_cardinality(&self, range: R) -> u64 + where + R: RangeBounds, + { + let (start, end) = match util::convert_range_to_inclusive(range) { + Ok(range) => (*range.start(), *range.end()), + // Empty/invalid ranges have 0 bits set in them + Err(_) => return 0, + }; + + let (start_key, start_low) = util::split(start); + let (end_key, end_low) = util::split(end); + + let mut cardinality = 0; + + let i = match self.containers.binary_search_by_key(&start_key, |c| c.key) { + Ok(i) => { + let container = &self.containers[i]; + if start_key == end_key { + cardinality += container.rank(end_low) + } else { + cardinality += container.len(); + } + if start_low != 0 { + cardinality -= container.rank(start_low - 1); + } + i + 1 + } + Err(i) => i, + }; + for container in &self.containers[i..] { + match container.key.cmp(&end_key) { + Ordering::Less => cardinality += container.len(), + Ordering::Equal => { + cardinality += container.rank(end_low); + break; + } + Ordering::Greater => { + break; + } + } + } + + cardinality + } + + /// Clears all integers in this set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.insert(1); + /// assert_eq!(rb.contains(1), true); + /// rb.clear(); + /// assert_eq!(rb.contains(1), false); + /// ``` + #[inline] + pub fn clear(&mut self) { + self.containers.clear(); + } + + /// Returns `true` if there are no integers in this set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.is_empty(), true); + /// + /// rb.insert(3); + /// assert_eq!(rb.is_empty(), false); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.containers.is_empty() + } + + /// Returns `true` if there are every possible integers in this set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::full(); + /// assert!(!rb.is_empty()); + /// assert!(rb.is_full()); + /// ``` + #[inline] + pub fn is_full(&self) -> bool { + self.containers.len() == (u16::MAX as usize + 1) + && self.containers.iter().all(Container::is_full) + } + + /// Returns the number of distinct integers added to the set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.len(), 0); + /// + /// rb.insert(3); + /// assert_eq!(rb.len(), 1); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.len(), 2); + /// ``` + #[inline] + pub fn len(&self) -> u64 { + self.containers.iter().map(|container| container.len()).sum() + } + + /// Returns the minimum value in the set (if the set is non-empty). + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.min(), None); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.min(), Some(3)); + /// ``` + #[inline] + pub fn min(&self) -> Option { + self.containers.first().and_then(|tail| tail.min().map(|min| util::join(tail.key, min))) + } + + /// Returns the maximum value in the set (if the set is non-empty). + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.max(), None); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.max(), Some(4)); + /// ``` + #[inline] + pub fn max(&self) -> Option { + self.containers.last().and_then(|tail| tail.max().map(|max| util::join(tail.key, max))) + } + + /// Returns the number of integers that are <= value. rank(u32::MAX) == len() + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.rank(0), 0); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.rank(3), 1); + /// assert_eq!(rb.rank(10), 2) + /// ``` + #[inline] + pub fn rank(&self, value: u32) -> u64 { + // if len becomes cached for RoaringBitmap: return len if len > value + + let (key, index) = util::split(value); + + match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(i) => { + // For optimal locality of reference: + // * container[i] should be a cache hit after binary search, rank it first + // * sum in reverse to avoid cache misses near i + unsafe { self.containers.get_unchecked(i) }.rank(index) + + self.containers[..i].iter().rev().map(|c| c.len()).sum::() + } + Err(i) => self.containers[..i].iter().map(|c| c.len()).sum(), + } + } + + /// Returns the `n`th integer in the set or `None` if `n >= len()` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.select(0), None); + /// + /// rb.append(vec![0, 10, 100]); + /// + /// assert_eq!(rb.select(0), Some(0)); + /// assert_eq!(rb.select(1), Some(10)); + /// assert_eq!(rb.select(2), Some(100)); + /// assert_eq!(rb.select(3), None); + /// ``` + #[inline] + pub fn select(&self, n: u32) -> Option { + let mut n = n as u64; + + for container in &self.containers { + let len = container.len(); + if len > n { + return container + .store + .select(n as u16) + .map(|index| util::join(container.key, index)); + } + n -= len; + } + + None + } + + /// Removes the `n` smallests values from this bitmap. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::from_iter([1, 5, 7, 9]); + /// rb.remove_smallest(2); + /// assert_eq!(rb, RoaringBitmap::from_iter([7, 9])); + /// + /// let mut rb = RoaringBitmap::from_iter([1, 3, 7, 9]); + /// rb.remove_smallest(2); + /// assert_eq!(rb, RoaringBitmap::from_iter([7, 9])); + #[inline] + pub fn remove_smallest(&mut self, mut n: u64) { + // remove containers up to the front of the target + let position = self.containers.iter().position(|container| { + let container_len = container.len(); + if container_len <= n { + n -= container_len; + false + } else { + true + } + }); + let position = position.unwrap_or(self.containers.len()); + if position > 0 { + self.containers.drain(..position); + } + // remove data in containers if there are still targets for deletion + if n > 0 && !self.containers.is_empty() { + // container immediately before should have been deleted, so the target is 0 index + self.containers[0].remove_smallest(n); + } + } + + /// Removes the `n` biggests values from this bitmap. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::from_iter([1, 5, 7, 9]); + /// rb.remove_biggest(2); + /// assert_eq!(rb, RoaringBitmap::from_iter([1, 5])); + /// rb.remove_biggest(1); + /// assert_eq!(rb, RoaringBitmap::from_iter([1])); + #[inline] + pub fn remove_biggest(&mut self, mut n: u64) { + // remove containers up to the back of the target + let position = self.containers.iter().rposition(|container| { + let container_len = container.len(); + if container_len <= n { + n -= container_len; + false + } else { + true + } + }); + // It is checked at the beginning of the function, so it is usually never an Err + if let Some(position) = position { + self.containers.drain(position + 1..); + if n > 0 && !self.containers.is_empty() { + self.containers[position].remove_biggest(n); + } + } else { + self.containers.clear(); + } + } + + /// Optimizes the container storage for this bitmap. + /// Returns true if the container storage was modified, false if not. + /// + /// # Examples + /// + /// ``` + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::from_iter(1000..100000); + /// rb.optimize(); + /// ``` + pub fn optimize(&mut self) -> bool { + let mut changed = false; + for container in &mut self.containers { + changed |= container.optimize() + } + changed + } + + /// Removes run-length encoding even when it is more space efficient. + /// + /// Returns true if the container storage was modified, false if not. + /// + /// # Examples + /// + /// ``` + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::from_iter(0..=10000); + /// rb.optimize(); + /// assert!(rb.remove_run_compression()); + /// ``` + pub fn remove_run_compression(&mut self) -> bool { + let mut changed = false; + for container in &mut self.containers { + changed |= container.remove_run_compression() + } + changed + } + + /// Ensure the bitmap is internally valid + /// + /// This is useful for development, but is not needed for normal use: + /// bitmaps should _always_ be internally valid. + /// + /// # Errors + /// + /// Returns an error if the bitmap is not valid, with a description of the problem. + #[doc(hidden)] + pub fn internal_validate(&self) -> Result<(), &'static str> { + for window in self.containers.windows(2) { + let [first, second] = window else { unreachable!() }; + if second.key <= first.key { + return Err("keys are not strictly increasing"); + } + } + for container in &self.containers { + container.store.internal_validate()?; + } + Ok(()) + } +} + +impl Default for RoaringBitmap { + fn default() -> RoaringBitmap { + RoaringBitmap::new() + } +} + +impl Clone for RoaringBitmap { + fn clone(&self) -> Self { + RoaringBitmap { containers: self.containers.clone() } + } + + fn clone_from(&mut self, other: &Self) { + self.containers.clone_from(&other.containers); + } +} + +#[cfg(test)] +mod tests { + use proptest::collection::vec; + use proptest::prelude::*; + + use super::*; + + proptest! { + #[test] + fn insert_range( + lo in 0u32..=65535, hi in 65536u32..=131071, + checks in vec(0u32..=262143, 1000) + ){ + let r = lo..hi; + let mut b = RoaringBitmap::new(); + let inserted = b.insert_range(r.clone()); + if r.end > r.start { + assert_eq!(inserted, r.end as u64 - r.start as u64); + } else { + assert_eq!(inserted, 0); + } + + // Assert all values in the range are present + for i in r.clone() { + assert!(b.contains(i), "does not contain {i}"); + } + + // Run the check values looking for any false positives + for i in checks { + let bitmap_has = b.contains(i); + let range_has = r.contains(&i); + assert_eq!( + bitmap_has, range_has, + "value {i} in bitmap={bitmap_has} and range={range_has}" + ); + } + } + } + + #[test] + fn test_insert_remove_range_same_container() { + let mut b = RoaringBitmap::new(); + let inserted = b.insert_range(1..5); + assert_eq!(inserted, 4); + + for i in 1..5 { + assert!(b.contains(i)); + } + + let removed = b.remove_range(2..10); + assert_eq!(removed, 3); + assert!(b.contains(1)); + for i in 2..5 { + assert!(!b.contains(i)); + } + } + + #[test] + fn test_insert_remove_range_pre_populated() { + let mut b = RoaringBitmap::new(); + let inserted = b.insert_range(1..20_000); + assert_eq!(inserted, 19_999); + + let removed = b.remove_range(10_000..21_000); + assert_eq!(removed, 10_000); + + let inserted = b.insert_range(1..20_000); + assert_eq!(inserted, 10_000); + } + + #[test] + fn test_insert_max_u32() { + let mut b = RoaringBitmap::new(); + let inserted = b.insert(u32::MAX); + // We are allowed to add u32::MAX + assert!(inserted); + } + + #[test] + fn test_insert_remove_across_container() { + let mut b = RoaringBitmap::new(); + let inserted = b.insert_range(u16::MAX as u32..=u16::MAX as u32 + 1); + assert_eq!(inserted, 2); + + assert_eq!(b.containers.len(), 2); + + let removed = b.remove_range(u16::MAX as u32 + 1..=u16::MAX as u32 + 1); + assert_eq!(removed, 1); + + assert_eq!(b.containers.len(), 1); + } + + #[test] + fn test_insert_remove_single_element() { + let mut b = RoaringBitmap::new(); + let inserted = b.insert_range(u16::MAX as u32 + 1..=u16::MAX as u32 + 1); + assert_eq!(inserted, 1); + + assert_eq!(b.containers[0].len(), 1); + assert_eq!(b.containers.len(), 1); + + let removed = b.remove_range(u16::MAX as u32 + 1..=u16::MAX as u32 + 1); + assert_eq!(removed, 1); + + assert_eq!(b.containers.len(), 0); + } + + #[test] + fn test_insert_remove_range_multi_container() { + let mut bitmap = RoaringBitmap::new(); + assert_eq!(bitmap.insert_range(0..((1_u32 << 16) + 1)), (1_u64 << 16) + 1); + assert_eq!(bitmap.containers.len(), 2); + assert_eq!(bitmap.containers[0].key, 0); + assert_eq!(bitmap.containers[1].key, 1); + assert_eq!(bitmap.insert_range(0..((1_u32 << 16) + 1)), 0); + + assert!(bitmap.insert((1_u32 << 16) * 4)); + assert_eq!(bitmap.containers.len(), 3); + assert_eq!(bitmap.containers[2].key, 4); + + assert_eq!(bitmap.remove_range(((1_u32 << 16) * 3)..=((1_u32 << 16) * 4)), 1); + assert_eq!(bitmap.containers.len(), 2); + } + + #[test] + fn insert_range_single() { + let mut bitmap = RoaringBitmap::new(); + assert_eq!(bitmap.insert_range((1_u32 << 16)..(2_u32 << 16)), 1_u64 << 16); + assert_eq!(bitmap.containers.len(), 1); + assert_eq!(bitmap.containers[0].key, 1); + } + + #[test] + fn remove_smallest_for_vec() { + let mut bitmap = RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11]); + bitmap.remove_smallest(3); + assert_eq!(bitmap.len(), 3); + assert_eq!(bitmap, RoaringBitmap::from_iter([7, 9, 11])); + + bitmap = RoaringBitmap::from_iter([1, 2, 5, 7, 9, 11]); + bitmap.remove_smallest(3); + assert_eq!(bitmap.len(), 3); + assert_eq!(bitmap, RoaringBitmap::from_iter([7, 9, 11])); + + bitmap = RoaringBitmap::from_iter([1, 3]); + bitmap.remove_smallest(2); + assert_eq!(bitmap.len(), 0); + + bitmap = RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11]); + bitmap.remove_smallest(0); + assert_eq!(bitmap.len(), 6); + assert_eq!(bitmap, RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11])); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..(1_u32 << 16) + 5); + bitmap.remove_smallest(65537); + assert_eq!(bitmap.len(), 4); + assert_eq!(bitmap, RoaringBitmap::from_iter([65537, 65538, 65539, 65540])); + + bitmap = RoaringBitmap::from_iter([1, 2, 5, 7, 9, 11]); + bitmap.remove_smallest(7); + assert_eq!(bitmap, RoaringBitmap::default()); + } + + #[test] + fn remove_smallest_for_bit() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..4098); + bitmap.remove_smallest(4095); + assert_eq!(bitmap.len(), 3); + // removed bit to vec + assert_eq!(bitmap, RoaringBitmap::from_iter([4095, 4096, 4097])); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..6000); + bitmap.remove_smallest(999); + assert_eq!(bitmap.len(), 5001); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..8000); + bitmap.remove_smallest(10); + assert_eq!(bitmap.len(), 7990); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..200000); + bitmap.remove_smallest(2000); + assert_eq!(bitmap.len(), 198000); + assert_eq!(bitmap, RoaringBitmap::from_iter(2000..200000)); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..2); + bitmap.insert_range(4..7); + bitmap.insert_range(1000..6000); + bitmap.remove_smallest(30); + assert_eq!(bitmap.len(), 4975); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..65535); + bitmap.remove_smallest(0); + assert_eq!(bitmap.len(), 65535); + } + + #[test] + fn remove_biggest_for_bit() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..5000); + bitmap.remove_biggest(1000); + assert_eq!(bitmap.len(), 4000); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..6000); + bitmap.remove_biggest(1000); + assert_eq!(bitmap.len(), 5000); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..200000); + bitmap.remove_biggest(196000); + assert_eq!(bitmap.len(), 4000); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..200000); + bitmap.remove_biggest(2000); + assert_eq!(bitmap.len(), 198000); + assert_eq!(bitmap, RoaringBitmap::from_iter(0..198000)); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..65535); + bitmap.remove_biggest(0); + assert_eq!(bitmap.len(), 65535); + } + + #[test] + fn remove_biggest_for_vec() { + let mut bitmap = RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11]); + bitmap.remove_biggest(2); + assert_eq!(bitmap, RoaringBitmap::from_iter([1, 2, 3, 7])); + + bitmap = RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11]); + bitmap.remove_biggest(6); + assert_eq!(bitmap.len(), 0); + + bitmap = RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11]); + bitmap.remove_biggest(0); + assert_eq!(bitmap.len(), 6); + assert_eq!(bitmap, RoaringBitmap::from_iter([1, 2, 3, 7, 9, 11])); + + bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..(1_u32 << 16) + 5); + bitmap.remove_biggest(65537); + assert_eq!(bitmap.len(), 4); + assert_eq!(bitmap, RoaringBitmap::from_iter([0, 1, 2, 3])); + + let mut bitmap = RoaringBitmap::from_iter([1, 2, 3]); + bitmap.remove_biggest(4); + assert_eq!(bitmap, RoaringBitmap::default()); + } +} diff --git a/vendor/roaring/src/bitmap/iter.rs b/vendor/roaring/src/bitmap/iter.rs new file mode 100644 index 0000000..49a5cbc --- /dev/null +++ b/vendor/roaring/src/bitmap/iter.rs @@ -0,0 +1,1051 @@ +use alloc::vec; +use core::iter::FusedIterator; +use core::ops::RangeBounds; +use core::slice; + +use super::container::Container; +use super::{container, util}; +use crate::{NonSortedIntegers, RoaringBitmap}; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +/// An iterator for `RoaringBitmap`. +#[derive(Clone)] +pub struct Iter<'a> { + front: Option>, + containers: slice::Iter<'a, Container>, + back: Option>, +} + +/// An iterator for `RoaringBitmap`. +#[derive(Clone)] +pub struct IntoIter { + front: Option>, + containers: vec::IntoIter, + back: Option>, +} + +#[inline] +fn and_then_or_clear(opt: &mut Option, f: impl FnOnce(&mut T) -> Option) -> Option { + let x = f(opt.as_mut()?); + if x.is_none() { + *opt = None; + } + x +} + +fn advance_to_impl<'a, It>( + n: u32, + front_iter: &mut Option>, + containers: &mut It, + back_iter: &mut Option>, +) where + It: Iterator, + It: AsRef<[Container]>, + It::Item: IntoIterator>, +{ + let (key, index) = util::split(n); + if let Some(iter) = front_iter { + match key.cmp(&iter.key) { + core::cmp::Ordering::Less => return, + core::cmp::Ordering::Equal => { + iter.advance_to(index); + return; + } + core::cmp::Ordering::Greater => { + *front_iter = None; + } + } + } + let containers_slice = containers.as_ref(); + let containers_len = containers_slice.len(); + let to_skip = match containers_slice.binary_search_by_key(&key, |c| c.key) { + Ok(n) => { + let container = containers.nth(n).expect("binary search returned a valid index"); + let mut container_iter = container.into_iter(); + container_iter.advance_to(index); + *front_iter = Some(container_iter); + return; + } + Err(n) => n, + }; + + if let Some(n) = to_skip.checked_sub(1) { + containers.nth(n); + } + if to_skip != containers_len { + // There are still containers with keys greater than the key we are looking for, + // the key we're looking _can't_ be in the back iterator. + return; + } + if let Some(iter) = back_iter { + match key.cmp(&iter.key) { + core::cmp::Ordering::Less => {} + core::cmp::Ordering::Equal => { + iter.advance_to(index); + } + core::cmp::Ordering::Greater => { + *back_iter = None; + } + } + } +} + +fn next_range_impl<'a, It>( + front_iter: &mut Option>, + containers: &mut It, + back_iter: &mut Option>, +) -> Option> +where + It: Iterator + Clone, + It: AsRef<[Container]>, + It::Item: IntoIterator>, +{ + let range = loop { + if let Some(r) = and_then_or_clear(front_iter, container::Iter::next_range) { + break r; + } + *front_iter = match containers.next() { + Some(inner) => Some(inner.into_iter()), + None => return and_then_or_clear(back_iter, container::Iter::next_range), + } + }; + let (range_start, mut range_end) = (*range.start(), *range.end()); + while range_end & 0xFFFF == 0xFFFF { + let Some(after_end) = range_end.checked_add(1) else { + return Some(range_start..=range_end); + }; + let (next_key, _) = util::split(after_end); + + if containers.as_ref().first().is_some_and(|c| c.key == next_key && c.contains(0)) { + let mut iter = containers.next().unwrap().into_iter(); + let next_range = iter.next_range().unwrap(); + *front_iter = Some(iter); + debug_assert_eq!(*next_range.start(), after_end); + range_end = *next_range.end(); + } else { + if let Some(iter) = back_iter { + if iter.peek() == Some(after_end) { + let next_range = iter.next_range().unwrap(); + debug_assert_eq!(*next_range.start(), after_end); + range_end = *next_range.end(); + } + } + break; + } + } + + Some(range_start..=range_end) +} + +fn next_range_back_impl<'a, It>( + front_iter: &mut Option>, + containers: &mut It, + back_iter: &mut Option>, +) -> Option> +where + It: DoubleEndedIterator, + It: AsRef<[Container]>, + It::Item: IntoIterator>, +{ + let range = loop { + if let Some(r) = and_then_or_clear(back_iter, container::Iter::next_range_back) { + break r; + } + *back_iter = match containers.next_back() { + Some(inner) => Some(inner.into_iter()), + None => return and_then_or_clear(front_iter, container::Iter::next_range_back), + } + }; + let (mut range_start, range_end) = (*range.start(), *range.end()); + while range_start & 0xFFFF == 0 { + let Some(before_start) = range_start.checked_sub(1) else { + return Some(range_start..=range_end); + }; + let (prev_key, _) = util::split(before_start); + + if containers.as_ref().last().is_some_and(|c| c.key == prev_key && c.contains(u16::MAX)) { + let mut iter = containers.next_back().unwrap().into_iter(); + let next_range = iter.next_range_back().unwrap(); + *back_iter = Some(iter); + debug_assert_eq!(*next_range.end(), before_start); + range_start = *next_range.start(); + } else { + if let Some(iter) = front_iter { + if iter.key == prev_key && iter.peek_back() == Some(before_start) { + let next_range = iter.next_range_back().unwrap(); + debug_assert_eq!(*next_range.end(), before_start); + range_start = *next_range.start(); + } + } + break; + } + } + + Some(range_start..=range_end) +} + +fn advance_back_to_impl<'a, It>( + n: u32, + front_iter: &mut Option>, + containers: &mut It, + back_iter: &mut Option>, +) where + It: DoubleEndedIterator, + It: AsRef<[Container]>, + It::Item: IntoIterator>, +{ + let (key, index) = util::split(n); + if let Some(iter) = back_iter { + match key.cmp(&iter.key) { + core::cmp::Ordering::Greater => return, + core::cmp::Ordering::Equal => { + iter.advance_back_to(index); + return; + } + core::cmp::Ordering::Less => { + *back_iter = None; + } + } + } + let containers_slice = containers.as_ref(); + let containers_len = containers_slice.len(); + let to_skip = match containers_slice.binary_search_by_key(&key, |c| c.key) { + Ok(n) => { + // n must be less than containers_len, so this can never underflow + let n = containers_len - n - 1; + let container = containers.nth_back(n).expect("binary search returned a valid index"); + let mut container_iter = container.into_iter(); + container_iter.advance_back_to(index); + *back_iter = Some(container_iter); + return; + } + Err(n) => containers_len - n, + }; + + if let Some(n) = to_skip.checked_sub(1) { + containers.nth_back(n); + } + if to_skip != containers_len { + // There are still containers with keys less than the key we are looking for, + // the key we're looking _can't_ be in the front iterator. + return; + } + if let Some(iter) = front_iter { + match key.cmp(&iter.key) { + core::cmp::Ordering::Greater => {} + core::cmp::Ordering::Equal => { + iter.advance_back_to(index); + } + core::cmp::Ordering::Less => { + *front_iter = None; + } + } + } +} + +impl Iter<'_> { + fn new(containers: &'_ [Container]) -> Iter<'_> { + Iter { front: None, containers: containers.iter(), back: None } + } + + fn empty() -> Self { + Self::new(&[]) + } + + /// Advance the iterator to the first position where the item has a value >= `n` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// iter.advance_to(2); + /// + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn advance_to(&mut self, n: u32) { + advance_to_impl(n, &mut self.front, &mut self.containers, &mut self.back); + } + + /// Advance the back of the iterator to the first position where the item has a value <= `n` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// iter.advance_back_to(1); + /// + /// assert_eq!(iter.next_back(), Some(1)); + /// assert_eq!(iter.next_back(), None); + /// ``` + pub fn advance_back_to(&mut self, n: u32) { + advance_back_to_impl(n, &mut self.front, &mut self.containers, &mut self.back); + } + + /// Returns the range of consecutive set bits from the current position to the end of the current run + /// + /// After this call, the iterator will be positioned at the first item after the returned range. + /// Returns `None` if the iterator is exhausted. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let bm = RoaringBitmap::from([1, 2, 4, 5]); + /// let mut iter = bm.iter(); + /// assert_eq!(iter.next_range(), Some(1..=2)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next_range(), Some(5..=5)); + /// ``` + pub fn next_range(&mut self) -> Option> { + next_range_impl(&mut self.front, &mut self.containers, &mut self.back) + } + + /// Returns the range of consecutive set bits from the start of the current run to the current back position + /// + /// After this call, the back of the iterator will be positioned at the last item before the returned range. + /// Returns `None` if the iterator is exhausted. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let bm = RoaringBitmap::from([1, 2, 4, 5]); + /// let mut iter = bm.iter(); + /// assert_eq!(iter.next_range_back(), Some(4..=5)); + /// assert_eq!(iter.next_back(), Some(2)); + /// assert_eq!(iter.next_range_back(), Some(1..=1)); + /// ``` + pub fn next_range_back(&mut self) -> Option> { + next_range_back_impl(&mut self.front, &mut self.containers, &mut self.back) + } +} + +impl IntoIter { + fn new(containers: Vec) -> IntoIter { + IntoIter { front: None, containers: containers.into_iter(), back: None } + } + + fn empty() -> Self { + Self::new(Vec::new()) + } + + /// Advance the iterator to the first position where the item has a value >= `n` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// iter.advance_to(2); + /// + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn advance_to(&mut self, n: u32) { + advance_to_impl(n, &mut self.front, &mut self.containers, &mut self.back); + } + + /// Advance the back of the iterator to the first position where the item has a value <= `n` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.into_iter(); + /// iter.advance_back_to(1); + /// + /// assert_eq!(iter.next_back(), Some(1)); + /// assert_eq!(iter.next_back(), None); + /// ``` + pub fn advance_back_to(&mut self, n: u32) { + advance_back_to_impl(n, &mut self.front, &mut self.containers, &mut self.back); + } + + /// Returns the range of consecutive set bits from the current position to the end of the current run + /// + /// After this call, the iterator will be positioned at the first item after the returned range. + /// Returns `None` if the iterator is exhausted. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let bm = RoaringBitmap::from([1, 2, 4, 5]); + /// let mut iter = bm.into_iter(); + /// assert_eq!(iter.next_range(), Some(1..=2)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next_range(), Some(5..=5)); + /// ``` + pub fn next_range(&mut self) -> Option> { + next_range_impl(&mut self.front, &mut self.containers, &mut self.back) + } + + /// Returns the range of consecutive set bits from the start of the current run to the current back position + /// + /// After this call, the back of the iterator will be positioned at the last item before the returned range. + /// Returns `None` if the iterator is exhausted. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let bm = RoaringBitmap::from([1, 2, 4, 5]); + /// let mut iter = bm.into_iter(); + /// assert_eq!(iter.next_range_back(), Some(4..=5)); + /// assert_eq!(iter.next_back(), Some(2)); + /// assert_eq!(iter.next_range_back(), Some(1..=1)); + /// ``` + pub fn next_range_back(&mut self) -> Option> { + next_range_back_impl(&mut self.front, &mut self.containers, &mut self.back) + } +} + +fn size_hint_impl( + front: &Option>, + containers: &impl AsRef<[Container]>, + back: &Option>, +) -> (usize, Option) { + let first_size = front.as_ref().map_or(0, |it| it.len()); + let last_size = back.as_ref().map_or(0, |it| it.len()); + let mut size = first_size + last_size; + for container in containers.as_ref() { + match size.checked_add(container.len() as usize) { + Some(new_size) => size = new_size, + None => return (usize::MAX, None), + } + } + (size, Some(size)) +} + +impl Iterator for Iter<'_> { + type Item = u32; + + fn next(&mut self) -> Option { + loop { + if let Some(x) = and_then_or_clear(&mut self.front, Iterator::next) { + return Some(x); + } + self.front = match self.containers.next() { + Some(inner) => Some(inner.into_iter()), + None => return and_then_or_clear(&mut self.back, Iterator::next), + } + } + } + + fn size_hint(&self) -> (usize, Option) { + size_hint_impl(&self.front, &self.containers, &self.back) + } + + #[inline] + fn fold(mut self, mut init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + if let Some(iter) = &mut self.front { + init = iter.fold(init, &mut f); + } + init = self.containers.fold(init, |acc, container| { + let iter = <&Container>::into_iter(container); + iter.fold(acc, &mut f) + }); + if let Some(iter) = &mut self.back { + init = iter.fold(init, &mut f); + }; + init + } + + fn count(self) -> usize + where + Self: Sized, + { + let mut count = self.front.map_or(0, Iterator::count); + count += self.containers.map(|container| container.len() as usize).sum::(); + count += self.back.map_or(0, Iterator::count); + count + } + + fn nth(&mut self, n: usize) -> Option { + let mut n = n; + let nth_advance = |it: &mut container::Iter| { + let len = it.len(); + if n < len { + it.nth(n) + } else { + n -= len; + None + } + }; + if let Some(x) = and_then_or_clear(&mut self.front, nth_advance) { + return Some(x); + } + for container in self.containers.by_ref() { + let len = container.len() as usize; + if n < len { + let mut front_iter = container.into_iter(); + let result = front_iter.nth(n); + self.front = Some(front_iter); + return result; + } + n -= len; + } + and_then_or_clear(&mut self.back, |it| it.nth(n)) + } +} + +impl DoubleEndedIterator for Iter<'_> { + fn next_back(&mut self) -> Option { + loop { + if let Some(x) = and_then_or_clear(&mut self.back, DoubleEndedIterator::next_back) { + return Some(x); + } + self.back = match self.containers.next_back() { + Some(inner) => Some(inner.into_iter()), + None => return and_then_or_clear(&mut self.front, DoubleEndedIterator::next_back), + } + } + } + + #[inline] + fn rfold(mut self, mut init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = &mut self.back { + init = iter.rfold(init, &mut fold); + } + init = self.containers.rfold(init, |acc, container| { + let iter = container.into_iter(); + iter.rfold(acc, &mut fold) + }); + if let Some(iter) = &mut self.front { + init = iter.rfold(init, &mut fold); + }; + init + } + + fn nth_back(&mut self, n: usize) -> Option { + let mut n = n; + let nth_advance = |it: &mut container::Iter| { + let len = it.len(); + if n < len { + it.nth_back(n) + } else { + n -= len; + None + } + }; + if let Some(x) = and_then_or_clear(&mut self.back, nth_advance) { + return Some(x); + } + for container in self.containers.by_ref().rev() { + let len = container.len() as usize; + if n < len { + let mut front_iter = container.into_iter(); + let result = front_iter.nth_back(n); + self.back = Some(front_iter); + return result; + } + n -= len; + } + and_then_or_clear(&mut self.front, |it| it.nth_back(n)) + } +} + +#[cfg(target_pointer_width = "64")] +impl ExactSizeIterator for Iter<'_> {} +impl FusedIterator for Iter<'_> {} + +impl Iterator for IntoIter { + type Item = u32; + + fn next(&mut self) -> Option { + loop { + if let Some(x) = and_then_or_clear(&mut self.front, Iterator::next) { + return Some(x); + } + match self.containers.next() { + Some(inner) => self.front = Some(inner.into_iter()), + None => return and_then_or_clear(&mut self.back, Iterator::next), + } + } + } + + fn size_hint(&self) -> (usize, Option) { + size_hint_impl(&self.front, &self.containers, &self.back) + } + + #[inline] + fn fold(mut self, mut init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + if let Some(iter) = &mut self.front { + init = iter.fold(init, &mut f); + } + init = self.containers.fold(init, |acc, container| { + let iter = ::into_iter(container); + iter.fold(acc, &mut f) + }); + if let Some(iter) = &mut self.back { + init = iter.fold(init, &mut f); + }; + init + } + + fn count(self) -> usize + where + Self: Sized, + { + let mut count = self.front.map_or(0, Iterator::count); + count += self.containers.map(|container| container.len() as usize).sum::(); + count += self.back.map_or(0, Iterator::count); + count + } + + fn nth(&mut self, n: usize) -> Option { + let mut n = n; + let nth_advance = |it: &mut container::Iter| { + let len = it.len(); + if n < len { + it.nth(n) + } else { + n -= len; + None + } + }; + if let Some(x) = and_then_or_clear(&mut self.front, nth_advance) { + return Some(x); + } + for container in self.containers.by_ref() { + let len = container.len() as usize; + if n < len { + let mut front_iter = container.into_iter(); + let result = front_iter.nth(n); + self.front = Some(front_iter); + return result; + } + n -= len; + } + and_then_or_clear(&mut self.back, |it| it.nth(n)) + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + loop { + if let Some(x) = and_then_or_clear(&mut self.back, DoubleEndedIterator::next_back) { + return Some(x); + } + match self.containers.next_back() { + Some(inner) => self.back = Some(inner.into_iter()), + None => return and_then_or_clear(&mut self.front, DoubleEndedIterator::next_back), + } + } + } + + #[inline] + fn rfold(mut self, mut init: Acc, mut fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + if let Some(iter) = &mut self.back { + init = iter.rfold(init, &mut fold); + } + init = self.containers.rfold(init, |acc, container| { + let iter = container.into_iter(); + iter.rfold(acc, &mut fold) + }); + if let Some(iter) = &mut self.front { + init = iter.rfold(init, &mut fold); + }; + init + } + + fn nth_back(&mut self, n: usize) -> Option { + let mut n = n; + let nth_advance = |it: &mut container::Iter| { + let len = it.len(); + if n < len { + it.nth_back(n) + } else { + n -= len; + None + } + }; + if let Some(x) = and_then_or_clear(&mut self.back, nth_advance) { + return Some(x); + } + for container in self.containers.by_ref().rev() { + let len = container.len() as usize; + if n < len { + let mut front_iter = container.into_iter(); + let result = front_iter.nth_back(n); + self.back = Some(front_iter); + return result; + } + n -= len; + } + and_then_or_clear(&mut self.front, |it| it.nth_back(n)) + } +} + +#[cfg(target_pointer_width = "64")] +impl ExactSizeIterator for IntoIter {} +impl FusedIterator for IntoIter {} + +impl RoaringBitmap { + /// Iterator over each value stored in the RoaringBitmap, guarantees values are ordered by value. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter(&'_ self) -> Iter<'_> { + Iter::new(&self.containers) + } + + /// Iterator over values within a range stored in the RoaringBitmap. + /// + /// # Examples + /// + /// ```rust + /// use core::ops::Bound; + /// use roaring::RoaringBitmap; + /// + /// let bitmap = RoaringBitmap::from([0, 1, 2, 3, 4, 5, 10, 11, 12, 20, 21, u32::MAX]); + /// let mut iter = bitmap.range(10..20); + /// + /// assert_eq!(iter.next(), Some(10)); + /// assert_eq!(iter.next(), Some(11)); + /// assert_eq!(iter.next(), Some(12)); + /// assert_eq!(iter.next(), None); + /// + /// let mut iter = bitmap.range(100..); + /// assert_eq!(iter.next(), Some(u32::MAX)); + /// assert_eq!(iter.next(), None); + /// + /// let mut iter = bitmap.range((Bound::Excluded(0), Bound::Included(10))); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), Some(5)); + /// assert_eq!(iter.next(), Some(10)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn range(&self, range: R) -> Iter<'_> + where + R: RangeBounds, + { + let range = match util::convert_range_to_inclusive(range) { + Ok(range) => range, + Err(util::ConvertRangeError::Empty) => return Iter::empty(), + Err(util::ConvertRangeError::StartGreaterThanEnd) => { + panic!("range start is greater than range end") + } + Err(util::ConvertRangeError::StartAndEndEqualExcluded) => { + panic!("range start and end are equal and excluded") + } + }; + let (start, end) = (*range.start(), *range.end()); + let mut iter = self.iter(); + if start != 0 { + iter.advance_to(start); + } + if end != u32::MAX { + iter.advance_back_to(end); + } + iter + } + + /// Iterator over values within a range stored in the RoaringBitmap. + /// + /// # Examples + /// + /// ```rust + /// use core::ops::Bound; + /// use roaring::RoaringBitmap; + /// + /// fn bitmap() -> RoaringBitmap { + /// RoaringBitmap::from([0, 1, 2, 3, 4, 5, 10, 11, 12, 20, 21, u32::MAX]) + /// } + /// + /// let mut iter = bitmap().into_range(10..20); + /// + /// assert_eq!(iter.next(), Some(10)); + /// assert_eq!(iter.next(), Some(11)); + /// assert_eq!(iter.next(), Some(12)); + /// assert_eq!(iter.next(), None); + /// + /// let mut iter = bitmap().into_range(100..); + /// assert_eq!(iter.next(), Some(u32::MAX)); + /// assert_eq!(iter.next(), None); + /// + /// let mut iter = bitmap().into_range((Bound::Excluded(0), Bound::Included(10))); + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), Some(3)); + /// assert_eq!(iter.next(), Some(4)); + /// assert_eq!(iter.next(), Some(5)); + /// assert_eq!(iter.next(), Some(10)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn into_range(self, range: R) -> IntoIter + where + R: RangeBounds, + { + let range = match util::convert_range_to_inclusive(range) { + Ok(range) => range, + Err(util::ConvertRangeError::Empty) => return IntoIter::empty(), + Err(util::ConvertRangeError::StartGreaterThanEnd) => { + panic!("range start is greater than range end") + } + Err(util::ConvertRangeError::StartAndEndEqualExcluded) => { + panic!("range start and end are equal and excluded") + } + }; + let (start, end) = (*range.start(), *range.end()); + let mut iter = self.into_iter(); + if start != 0 { + iter.advance_to(start); + } + if end != u32::MAX { + iter.advance_back_to(end); + } + iter + } +} + +impl<'a> IntoIterator for &'a RoaringBitmap { + type Item = u32; + type IntoIter = Iter<'a>; + + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +impl IntoIterator for RoaringBitmap { + type Item = u32; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + IntoIter::new(self.containers) + } +} + +impl From<[u32; N]> for RoaringBitmap { + fn from(arr: [u32; N]) -> Self { + RoaringBitmap::from_iter(arr) + } +} + +impl FromIterator for RoaringBitmap { + fn from_iter>(iterator: I) -> RoaringBitmap { + let mut rb = RoaringBitmap::new(); + rb.extend(iterator); + rb + } +} + +impl<'a> FromIterator<&'a u32> for RoaringBitmap { + fn from_iter>(iterator: I) -> RoaringBitmap { + let mut rb = RoaringBitmap::new(); + rb.extend(iterator); + rb + } +} + +impl Extend for RoaringBitmap { + /// Inserts multiple values and returns the count of new additions. + /// This is expected to be faster than calling [`RoaringBitmap::insert`] on each value. + /// + /// The provided integers values don't have to be in sorted order, but it may be preferable + /// to sort them from a performance point of view. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.extend([1, 2, 3, 4, 1500, 1508, 1507, 1509]); + /// assert!(rb.contains(2)); + /// assert!(rb.contains(1508)); + /// assert!(!rb.contains(5)); + /// ``` + #[inline] + fn extend>(&mut self, values: I) { + let mut values = values.into_iter(); + let value = match values.next() { + Some(value) => value, + None => return, + }; + + let (mut currenthb, lowbit) = util::split(value); + let mut current_container_index = self.find_container_by_key(currenthb); + let mut current_cont = &mut self.containers[current_container_index]; + current_cont.insert(lowbit); + + for val in values { + let (newhb, lowbit) = util::split(val); + if currenthb == newhb { + // easy case, this could be quite frequent + current_cont.insert(lowbit); + } else { + currenthb = newhb; + current_container_index = self.find_container_by_key(currenthb); + current_cont = &mut self.containers[current_container_index]; + current_cont.insert(lowbit); + } + } + } +} + +impl<'a> Extend<&'a u32> for RoaringBitmap { + /// Inserts multiple values and returns the count of new additions. + /// This is expected to be faster than calling [`RoaringBitmap::insert`] on each value. + /// + /// The provided integers values don't have to be in sorted order, but it may be preferable + /// to sort them from a performance point of view. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// rb.extend([1, 2, 3, 4, 1500, 1508, 1507, 1509]); + /// assert!(rb.contains(2)); + /// assert!(rb.contains(1508)); + /// assert!(!rb.contains(5)); + /// ``` + #[inline] + fn extend>(&mut self, values: I) { + self.extend(values.into_iter().copied()); + } +} + +impl RoaringBitmap { + /// Create the set from a sorted iterator. Values must be sorted and deduplicated. + /// + /// The values of the iterator must be ordered and strictly greater than the greatest value + /// in the set. If a value in the iterator doesn't satisfy this requirement, it is not added + /// and the append operation is stopped. + /// + /// Returns `Ok` with the requested `RoaringBitmap`, `Err` with the number of elements + /// that were correctly appended before failure. + /// + /// # Example: Create a set from an ordered list of integers. + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::from_sorted_iter(0..10).unwrap(); + /// + /// assert!(rb.iter().eq(0..10)); + /// ``` + /// + /// # Example: Try to create a set from a non-ordered list of integers. + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let integers = 0..10u32; + /// let error = RoaringBitmap::from_sorted_iter(integers.rev()).unwrap_err(); + /// + /// assert_eq!(error.valid_until(), 1); + /// ``` + pub fn from_sorted_iter>( + iterator: I, + ) -> Result { + let mut rb = RoaringBitmap::new(); + rb.append(iterator).map(|_| rb) + } + + /// Extend the set with a sorted iterator. + /// + /// The values of the iterator must be ordered and strictly greater than the greatest value + /// in the set. If a value in the iterator doesn't satisfy this requirement, it is not added + /// and the append operation is stopped. + /// + /// Returns `Ok` with the number of elements appended to the set, `Err` with + /// the number of elements we effectively appended before an error occurred. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let mut rb = RoaringBitmap::new(); + /// assert_eq!(rb.append(0..10), Ok(10)); + /// + /// assert!(rb.iter().eq(0..10)); + /// ``` + pub fn append>( + &mut self, + iterator: I, + ) -> Result { + // Name shadowed to prevent accidentally referencing the param + let mut iterator = iterator.into_iter(); + + let mut prev = match (iterator.next(), self.max()) { + (None, _) => return Ok(0), + (Some(first), Some(max)) if first <= max => { + return Err(NonSortedIntegers { valid_until: 0 }) + } + (Some(first), _) => first, + }; + + // It is now guaranteed that so long as the values of the iterator are + // monotonically increasing they must also be the greatest in the set. + + self.push_unchecked(prev); + + let mut count = 1; + + for value in iterator { + if value <= prev { + return Err(NonSortedIntegers { valid_until: count }); + } else { + self.push_unchecked(value); + prev = value; + count += 1; + } + } + + Ok(count) + } +} diff --git a/vendor/roaring/src/bitmap/mod.rs b/vendor/roaring/src/bitmap/mod.rs new file mode 100644 index 0000000..add18df --- /dev/null +++ b/vendor/roaring/src/bitmap/mod.rs @@ -0,0 +1,50 @@ +mod arbitrary; +mod container; +mod fmt; +mod multiops; +mod proptests; +mod statistics; +mod store; +mod util; + +// Order of these modules matters as it determines the `impl` blocks order in +// the docs +mod cmp; +mod inherent; +mod iter; +mod ops; +#[cfg(feature = "std")] +mod ops_with_serialized; +#[cfg(feature = "serde")] +mod serde; +#[cfg(feature = "std")] +mod serialization; + +use self::cmp::Pairs; +pub use self::iter::IntoIter; +pub use self::iter::Iter; +pub use self::statistics::Statistics; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +/// A compressed bitmap using the [Roaring bitmap compression scheme](https://roaringbitmap.org/). +/// +/// # Examples +/// +/// ```rust +/// use roaring::RoaringBitmap; +/// +/// let mut rb = RoaringBitmap::new(); +/// +/// // insert all primes less than 10 +/// rb.insert(2); +/// rb.insert(3); +/// rb.insert(5); +/// rb.insert(7); +/// println!("total bits set to true: {}", rb.len()); +/// ``` +#[derive(PartialEq, Eq)] +pub struct RoaringBitmap { + containers: Vec, +} diff --git a/vendor/roaring/src/bitmap/multiops.rs b/vendor/roaring/src/bitmap/multiops.rs new file mode 100644 index 0000000..4ba588a --- /dev/null +++ b/vendor/roaring/src/bitmap/multiops.rs @@ -0,0 +1,453 @@ +use core::{ + cmp::Reverse, + convert::Infallible, + mem, + ops::{BitOrAssign, BitXorAssign}, +}; + +use alloc::borrow::Cow; + +use crate::{MultiOps, RoaringBitmap}; + +use super::{container::Container, store::Store}; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +/// When collecting bitmaps for optimizing the computation. If we don't know how many +// elements are in the iterator we collect 10 elements. +const BASE_COLLECT: usize = 10; + +/// If an iterator contain 50 elements or less we collect everything because it'll be so +/// much faster without impacting the memory usage too much (in most cases). +const MAX_COLLECT: usize = 50; + +impl MultiOps for I +where + I: IntoIterator, +{ + type Output = RoaringBitmap; + + fn union(self) -> Self::Output { + try_multi_or_owned(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } + + fn intersection(self) -> Self::Output { + try_multi_and_owned(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } + + fn difference(self) -> Self::Output { + try_multi_sub_owned(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } + + fn symmetric_difference(self) -> Self::Output { + try_multi_xor_owned(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } +} + +impl MultiOps> for I +where + I: IntoIterator>, +{ + type Output = Result; + + fn union(self) -> Self::Output { + try_multi_or_owned(self) + } + + fn intersection(self) -> Self::Output { + try_multi_and_owned(self) + } + + fn difference(self) -> Self::Output { + try_multi_sub_owned(self) + } + + fn symmetric_difference(self) -> Self::Output { + try_multi_xor_owned(self) + } +} + +impl<'a, I> MultiOps<&'a RoaringBitmap> for I +where + I: IntoIterator, +{ + type Output = RoaringBitmap; + + fn union(self) -> Self::Output { + try_multi_or_ref(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } + + fn intersection(self) -> Self::Output { + try_multi_and_ref(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } + + fn difference(self) -> Self::Output { + try_multi_sub_ref(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } + + fn symmetric_difference(self) -> Self::Output { + try_multi_xor_ref(self.into_iter().map(Ok::<_, Infallible>)).unwrap() + } +} + +impl<'a, I, E: 'a> MultiOps> for I +where + I: IntoIterator>, +{ + type Output = Result; + + fn union(self) -> Self::Output { + try_multi_or_ref(self) + } + + fn intersection(self) -> Self::Output { + try_multi_and_ref(self) + } + + fn difference(self) -> Self::Output { + try_multi_sub_ref(self) + } + + fn symmetric_difference(self) -> Self::Output { + try_multi_xor_ref(self) + } +} + +#[inline] +fn try_multi_and_owned( + bitmaps: impl IntoIterator>, +) -> Result { + let mut iter = bitmaps.into_iter(); + + // We're going to take a bunch of elements at the start of the iterator and sort + // them to reduce the size of our bitmap faster. + let mut start = collect_starting_elements(iter.by_ref())?; + start.sort_unstable_by_key(|bitmap| bitmap.containers.len()); + let mut start = start.into_iter(); + + if let Some(mut lhs) = start.next() { + for rhs in start.map(Ok).chain(iter) { + if lhs.is_empty() { + return Ok(lhs); + } + lhs &= rhs?; + } + + Ok(lhs) + } else { + Ok(RoaringBitmap::new()) + } +} + +#[inline] +fn try_multi_and_ref<'a, E>( + bitmaps: impl IntoIterator>, +) -> Result { + let mut iter = bitmaps.into_iter(); + + // We're going to take a bunch of elements at the start of the iterator and sort + // them to reduce the size of our bitmap faster. + let mut start = collect_starting_elements(iter.by_ref())?; + start.sort_unstable_by_key(|bitmap| bitmap.containers.len()); + let mut start = start.into_iter(); + + if let Some(mut lhs) = start.next().cloned() { + for rhs in start.map(Ok).chain(iter) { + if lhs.is_empty() { + return Ok(lhs); + } + lhs &= rhs?; + } + Ok(lhs) + } else { + Ok(RoaringBitmap::new()) + } +} + +#[inline] +fn try_multi_sub_owned( + bitmaps: impl IntoIterator>, +) -> Result { + let mut iter = bitmaps.into_iter(); + match iter.next().transpose()? { + Some(mut lhs) => { + for rhs in iter { + if lhs.is_empty() { + return Ok(lhs); + } + lhs -= rhs?; + } + Ok(lhs) + } + None => Ok(RoaringBitmap::default()), + } +} + +#[inline] +fn try_multi_sub_ref<'a, E>( + bitmaps: impl IntoIterator>, +) -> Result { + let mut iter = bitmaps.into_iter(); + match iter.next().transpose()?.cloned() { + Some(mut lhs) => { + for rhs in iter { + if lhs.is_empty() { + return Ok(lhs); + } + lhs -= rhs?; + } + + Ok(lhs) + } + None => Ok(RoaringBitmap::default()), + } +} + +#[inline] +fn try_multi_or_owned( + bitmaps: impl IntoIterator>, +) -> Result { + let mut iter = bitmaps.into_iter(); + + // We're going to take a bunch of elements at the start of the iterator and + // move the biggest one first to grow faster. + let mut start = collect_starting_elements(iter.by_ref())?; + start.sort_unstable_by_key(|bitmap| Reverse(bitmap.containers.len())); + let start_size = start.len(); + let mut start = start.into_iter(); + + let mut containers = if let Some(c) = start.next() { + if c.is_empty() { + // everything must be empty if the max is empty + start.by_ref().nth(start_size); + } + c.containers + } else { + return Ok(RoaringBitmap::new()); + }; + + for bitmap in start.map(Ok).chain(iter) { + merge_container_owned(&mut containers, bitmap?.containers, BitOrAssign::bitor_assign); + } + + containers.retain_mut(|container| { + if !container.is_empty() { + container.ensure_correct_store(); + true + } else { + false + } + }); + + Ok(RoaringBitmap { containers }) +} + +#[inline] +fn try_multi_xor_owned( + bitmaps: impl IntoIterator>, +) -> Result { + let mut iter = bitmaps.into_iter(); + let mut containers = match iter.next().transpose()? { + None => Vec::new(), + Some(v) => v.containers, + }; + + for bitmap in iter { + merge_container_owned(&mut containers, bitmap?.containers, BitXorAssign::bitxor_assign); + } + + containers.retain_mut(|container| { + if !container.is_empty() { + container.ensure_correct_store(); + true + } else { + false + } + }); + + Ok(RoaringBitmap { containers }) +} + +fn merge_container_owned( + lhs: &mut Vec, + rhs: Vec, + op: impl Fn(&mut Store, Store), +) { + for mut rhs in rhs { + match lhs.binary_search_by_key(&rhs.key, |c| c.key) { + Err(loc) => lhs.insert(loc, rhs), + Ok(loc) => { + let lhs = &mut lhs[loc]; + match (&lhs.store, &rhs.store) { + (Store::Array(..), Store::Array(..)) => lhs.store = lhs.store.to_bitmap(), + (Store::Array(..), Store::Bitmap(..)) => mem::swap(lhs, &mut rhs), + _ => (), + }; + op(&mut lhs.store, rhs.store); + } + } + } +} + +#[inline] +fn try_multi_or_ref<'a, E: 'a>( + bitmaps: impl IntoIterator>, +) -> Result { + // This algorithm operates on bitmaps. It must deal with arrays for which there are not (yet) + // any others with the same key. + // + // 1. Eager cloning would create useless intermediate values that might become bitmaps + // 2. Eager promoting forces disjoint containers to converted back to arrays at the end + // + // This strategy uses COW to lazily promote arrays to bitmaps as they are operated on. + // More memory efficient, negligible wall time difference benchmarks + + // Phase 1. Borrow all the containers from the first element. + let mut iter = bitmaps.into_iter(); + let mut start = collect_starting_elements(iter.by_ref())?; + let start_size = start.len(); + + start.sort_unstable_by_key(|bitmap| Reverse(bitmap.containers.len())); + let mut start = start.into_iter(); + let mut containers = match start.next() { + Some(c) => { + let c: Vec> = c.containers.iter().map(Cow::Borrowed).collect(); + if c.is_empty() { + // everything must be empty if the max is empty + start.by_ref().nth(start_size); + } + c + } + None => { + return Ok(RoaringBitmap::new()); + } + }; + + // Phase 2: Operate on the remaining containers + for bitmap in start.map(Ok).chain(iter) { + merge_container_ref(&mut containers, &bitmap?.containers, |a, b| *a |= b); + } + + // Phase 3: Clean up + let containers: Vec<_> = containers + .into_iter() + .filter(|container| !container.is_empty()) + .map(|c| { + // Any borrowed bitmaps or arrays left over get cloned here + let mut container = c.into_owned(); + container.ensure_correct_store(); + container + }) + .collect(); + + Ok(RoaringBitmap { containers }) +} + +#[inline] +fn try_multi_xor_ref<'a, E: 'a>( + bitmaps: impl IntoIterator>, +) -> Result { + // + // This algorithm operates on bitmaps. It must deal with arrays for which there are not (yet) + // any others with the same key. + // + // 1. Eager cloning would create useless intermediate values that might become bitmaps + // 2. Eager promoting forces disjoint containers to converted back to arrays at the end + // + // This strategy uses COW to lazily promote arrays to bitmaps as they are operated on. + // More memory efficient, negligible wall time difference benchmarks + + // Phase 1. Borrow all the containers from the first element. + let mut iter = bitmaps.into_iter(); + let mut containers: Vec> = match iter.next().transpose()? { + None => Vec::new(), + Some(v) => v.containers.iter().map(Cow::Borrowed).collect(), + }; + + // Phase 2: Operate on the remaining containers + for bitmap in iter { + merge_container_ref(&mut containers, &bitmap?.containers, |a, b| *a ^= b); + } + + // Phase 3: Clean up + let containers: Vec<_> = containers + .into_iter() + .filter(|container| !container.is_empty()) + .map(|c| { + // Any borrowed bitmaps or arrays left over get cloned here + let mut container = c.into_owned(); + container.ensure_correct_store(); + container + }) + .collect(); + + Ok(RoaringBitmap { containers }) +} + +fn merge_container_ref<'a>( + containers: &mut Vec>, + rhs: &'a [Container], + op: impl Fn(&mut Store, &Store), +) { + for rhs in rhs { + match containers.binary_search_by_key(&rhs.key, |c| c.key) { + Err(loc) => { + // A container not currently in containers. Borrow it. + containers.insert(loc, Cow::Borrowed(rhs)) + } + Ok(loc) => { + // A container that is in containers. Operate on it. + let lhs = &mut containers[loc]; + match (&lhs.store, &rhs.store) { + (Store::Array(..), Store::Array(..)) => { + // We had borrowed an array. Without cloning it, create a new bitmap + // Add all the elements to the new bitmap + let mut store = lhs.store.to_bitmap(); + op(&mut store, &rhs.store); + *lhs = Cow::Owned(Container { key: lhs.key, store }); + } + (Store::Array(..), Store::Bitmap(..)) => { + // We had borrowed an array. Copy the rhs bitmap, add lhs to it + let mut store = rhs.store.clone(); + op(&mut store, &lhs.store); + *lhs = Cow::Owned(Container { key: lhs.key, store }); + } + (Store::Bitmap(..), _) => { + // This might be a owned or borrowed bitmap. + // If it was borrowed it will clone-on-write + op(&mut lhs.to_mut().store, &rhs.store); + } + (Store::Run(..), Store::Run(..)) => { + op(&mut lhs.to_mut().store, &rhs.store); + } + (Store::Run(..), _) => { + op(&mut lhs.to_mut().store, &rhs.store); + } + (Store::Array(..), Store::Run(..)) => { + op(&mut lhs.to_mut().store, &rhs.store); + } + }; + } + } + } +} + +#[inline] +fn collect_starting_elements(iter: I) -> Result, Er> +where + I: IntoIterator>, +{ + let iter = iter.into_iter(); + let mut to_collect = iter.size_hint().1.unwrap_or(BASE_COLLECT); + if to_collect > MAX_COLLECT { + to_collect = BASE_COLLECT; + } + + let mut ret = Vec::with_capacity(to_collect); + for el in iter.take(to_collect) { + ret.push(el?); + } + + Ok(ret) +} diff --git a/vendor/roaring/src/bitmap/ops.rs b/vendor/roaring/src/bitmap/ops.rs new file mode 100644 index 0000000..4337dbd --- /dev/null +++ b/vendor/roaring/src/bitmap/ops.rs @@ -0,0 +1,633 @@ +use core::mem; +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign}; + +use crate::bitmap::container::Container; +use crate::bitmap::Pairs; +use crate::RoaringBitmap; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl RoaringBitmap { + /// Computes the len of the intersection with the specified other bitmap without creating a + /// new bitmap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the intersection. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let rb2: RoaringBitmap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.intersection_len(&rb2), (rb1 & rb2).len()); + /// ``` + pub fn intersection_len(&self, other: &RoaringBitmap) -> u64 { + Pairs::new(&self.containers, &other.containers) + .map(|pair| match pair { + (Some(..), None) => 0, + (None, Some(..)) => 0, + (Some(lhs), Some(rhs)) => lhs.intersection_len(rhs), + (None, None) => 0, + }) + .sum() + } + + /// Computes the len of the union with the specified other bitmap without creating a new bitmap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the union. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let rb2: RoaringBitmap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.union_len(&rb2), (rb1 | rb2).len()); + /// ``` + pub fn union_len(&self, other: &RoaringBitmap) -> u64 { + self.len().wrapping_add(other.len()).wrapping_sub(self.intersection_len(other)) + } + + /// Computes the len of the difference with the specified other bitmap without creating a new + /// bitmap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the difference. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let rb2: RoaringBitmap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.difference_len(&rb2), (rb1 - rb2).len()); + /// ``` + pub fn difference_len(&self, other: &RoaringBitmap) -> u64 { + self.len() - self.intersection_len(other) + } + + /// Computes the len of the symmetric difference with the specified other bitmap without + /// creating a new bitmap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the symmetric difference. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let rb2: RoaringBitmap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.symmetric_difference_len(&rb2), (rb1 ^ rb2).len()); + /// ``` + pub fn symmetric_difference_len(&self, other: &RoaringBitmap) -> u64 { + let intersection_len = self.intersection_len(other); + self.len() + .wrapping_add(other.len()) + .wrapping_sub(intersection_len) + .wrapping_sub(intersection_len) + } +} + +impl BitOr for RoaringBitmap { + type Output = RoaringBitmap; + + /// An `union` between two sets. + fn bitor(mut self, rhs: RoaringBitmap) -> RoaringBitmap { + BitOrAssign::bitor_assign(&mut self, rhs); + self + } +} + +impl BitOr<&RoaringBitmap> for RoaringBitmap { + type Output = RoaringBitmap; + + /// An `union` between two sets. + fn bitor(mut self, rhs: &RoaringBitmap) -> RoaringBitmap { + BitOrAssign::bitor_assign(&mut self, rhs); + self + } +} + +impl BitOr for &RoaringBitmap { + type Output = RoaringBitmap; + + /// An `union` between two sets. + fn bitor(self, rhs: RoaringBitmap) -> RoaringBitmap { + BitOr::bitor(rhs, self) + } +} + +impl BitOr<&RoaringBitmap> for &RoaringBitmap { + type Output = RoaringBitmap; + + /// An `union` between two sets. + fn bitor(self, rhs: &RoaringBitmap) -> RoaringBitmap { + let mut containers = Vec::new(); + + for pair in Pairs::new(&self.containers, &rhs.containers) { + match pair { + (Some(lhs), None) => containers.push(lhs.clone()), + (None, Some(rhs)) => containers.push(rhs.clone()), + (Some(lhs), Some(rhs)) => containers.push(BitOr::bitor(lhs, rhs)), + (None, None) => break, + } + } + + RoaringBitmap { containers } + } +} + +impl BitOrAssign for RoaringBitmap { + /// An `union` between two sets. + fn bitor_assign(&mut self, mut rhs: RoaringBitmap) { + // We make sure that we apply the union operation on the biggest map. + if self.len() < rhs.len() { + mem::swap(self, &mut rhs); + } + + for container in rhs.containers { + let key = container.key; + match self.containers.binary_search_by_key(&key, |c| c.key) { + Err(loc) => self.containers.insert(loc, container), + Ok(loc) => BitOrAssign::bitor_assign(&mut self.containers[loc], container), + } + } + } +} + +impl BitOrAssign<&RoaringBitmap> for RoaringBitmap { + /// An `union` between two sets. + fn bitor_assign(&mut self, rhs: &RoaringBitmap) { + for container in &rhs.containers { + let key = container.key; + match self.containers.binary_search_by_key(&key, |c| c.key) { + Err(loc) => self.containers.insert(loc, container.clone()), + Ok(loc) => BitOrAssign::bitor_assign(&mut self.containers[loc], container), + } + } + } +} + +impl BitAnd for RoaringBitmap { + type Output = RoaringBitmap; + + /// An `intersection` between two sets. + fn bitand(mut self, rhs: RoaringBitmap) -> RoaringBitmap { + BitAndAssign::bitand_assign(&mut self, rhs); + self + } +} + +impl BitAnd<&RoaringBitmap> for RoaringBitmap { + type Output = RoaringBitmap; + + /// An `intersection` between two sets. + fn bitand(mut self, rhs: &RoaringBitmap) -> RoaringBitmap { + BitAndAssign::bitand_assign(&mut self, rhs); + self + } +} + +impl BitAnd for &RoaringBitmap { + type Output = RoaringBitmap; + + /// An `intersection` between two sets. + fn bitand(self, rhs: RoaringBitmap) -> RoaringBitmap { + BitAnd::bitand(rhs, self) + } +} + +impl BitAnd<&RoaringBitmap> for &RoaringBitmap { + type Output = RoaringBitmap; + + /// An `intersection` between two sets. + fn bitand(self, rhs: &RoaringBitmap) -> RoaringBitmap { + let mut containers = Vec::new(); + + for pair in Pairs::new(&self.containers, &rhs.containers) { + if let (Some(lhs), Some(rhs)) = pair { + let container = BitAnd::bitand(lhs, rhs); + if !container.is_empty() { + containers.push(container); + } + } + } + + RoaringBitmap { containers } + } +} + +impl BitAndAssign for RoaringBitmap { + /// An `intersection` between two sets. + fn bitand_assign(&mut self, mut rhs: RoaringBitmap) { + // We make sure that we apply the intersection operation on the smallest map. + if rhs.containers.len() < self.containers.len() { + mem::swap(self, &mut rhs); + } + + self.containers.retain_mut(|cont| { + let key = cont.key; + match rhs.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => { + let rhs_cont = &mut rhs.containers[loc]; + let rhs_cont = mem::replace(rhs_cont, Container::new(rhs_cont.key)); + BitAndAssign::bitand_assign(cont, rhs_cont); + !cont.is_empty() + } + Err(_) => false, + } + }) + } +} + +impl BitAndAssign<&RoaringBitmap> for RoaringBitmap { + /// An `intersection` between two sets. + fn bitand_assign(&mut self, rhs: &RoaringBitmap) { + self.containers.retain_mut(|cont| { + let key = cont.key; + match rhs.containers.binary_search_by_key(&key, |c| c.key) { + Ok(loc) => { + BitAndAssign::bitand_assign(cont, &rhs.containers[loc]); + !cont.is_empty() + } + Err(_) => false, + } + }) + } +} + +impl Sub for RoaringBitmap { + type Output = RoaringBitmap; + + /// A `difference` between two sets. + fn sub(mut self, rhs: RoaringBitmap) -> RoaringBitmap { + SubAssign::sub_assign(&mut self, &rhs); + self + } +} + +impl Sub<&RoaringBitmap> for RoaringBitmap { + type Output = RoaringBitmap; + + /// A `difference` between two sets. + fn sub(mut self, rhs: &RoaringBitmap) -> RoaringBitmap { + SubAssign::sub_assign(&mut self, rhs); + self + } +} + +impl Sub for &RoaringBitmap { + type Output = RoaringBitmap; + + /// A `difference` between two sets. + fn sub(self, rhs: RoaringBitmap) -> RoaringBitmap { + Sub::sub(self, &rhs) + } +} + +impl Sub<&RoaringBitmap> for &RoaringBitmap { + type Output = RoaringBitmap; + + /// A `difference` between two sets. + fn sub(self, rhs: &RoaringBitmap) -> RoaringBitmap { + let mut containers = Vec::new(); + + for pair in Pairs::new(&self.containers, &rhs.containers) { + match pair { + (Some(lhs), None) => containers.push(lhs.clone()), + (None, Some(_)) => (), + (Some(lhs), Some(rhs)) => { + let container = Sub::sub(lhs, rhs); + if !container.is_empty() { + containers.push(container); + } + } + (None, None) => break, + } + } + + RoaringBitmap { containers } + } +} + +impl SubAssign for RoaringBitmap { + /// A `difference` between two sets. + fn sub_assign(&mut self, rhs: RoaringBitmap) { + SubAssign::sub_assign(self, &rhs) + } +} + +impl SubAssign<&RoaringBitmap> for RoaringBitmap { + /// A `difference` between two sets. + fn sub_assign(&mut self, rhs: &RoaringBitmap) { + self.containers.retain_mut(|cont| { + match rhs.containers.binary_search_by_key(&cont.key, |c| c.key) { + Ok(loc) => { + SubAssign::sub_assign(cont, &rhs.containers[loc]); + !cont.is_empty() + } + Err(_) => true, + } + }) + } +} + +impl BitXor for RoaringBitmap { + type Output = RoaringBitmap; + + /// A `symmetric difference` between two sets. + fn bitxor(mut self, rhs: RoaringBitmap) -> RoaringBitmap { + BitXorAssign::bitxor_assign(&mut self, rhs); + self + } +} + +impl BitXor<&RoaringBitmap> for RoaringBitmap { + type Output = RoaringBitmap; + + /// A `symmetric difference` between two sets. + fn bitxor(mut self, rhs: &RoaringBitmap) -> RoaringBitmap { + BitXorAssign::bitxor_assign(&mut self, rhs); + self + } +} + +impl BitXor for &RoaringBitmap { + type Output = RoaringBitmap; + + /// A `symmetric difference` between two sets. + fn bitxor(self, rhs: RoaringBitmap) -> RoaringBitmap { + BitXor::bitxor(rhs, self) + } +} + +impl BitXor<&RoaringBitmap> for &RoaringBitmap { + type Output = RoaringBitmap; + + /// A `symmetric difference` between two sets. + fn bitxor(self, rhs: &RoaringBitmap) -> RoaringBitmap { + let mut containers = Vec::new(); + + for pair in Pairs::new(&self.containers, &rhs.containers) { + match pair { + (Some(lhs), None) => containers.push(lhs.clone()), + (None, Some(rhs)) => containers.push(rhs.clone()), + (Some(lhs), Some(rhs)) => { + let container = BitXor::bitxor(lhs, rhs); + if !container.is_empty() { + containers.push(container); + } + } + (None, None) => break, + } + } + + RoaringBitmap { containers } + } +} + +impl BitXorAssign for RoaringBitmap { + /// A `symmetric difference` between two sets. + fn bitxor_assign(&mut self, rhs: RoaringBitmap) { + for pair in Pairs::new(mem::take(&mut self.containers), rhs.containers) { + match pair { + (Some(mut lhs), Some(rhs)) => { + BitXorAssign::bitxor_assign(&mut lhs, rhs); + if !lhs.is_empty() { + self.containers.push(lhs); + } + } + (Some(lhs), None) => self.containers.push(lhs), + (None, Some(rhs)) => self.containers.push(rhs), + (None, None) => break, + } + } + } +} + +impl BitXorAssign<&RoaringBitmap> for RoaringBitmap { + /// A `symmetric difference` between two sets. + fn bitxor_assign(&mut self, rhs: &RoaringBitmap) { + for pair in Pairs::new(mem::take(&mut self.containers), &rhs.containers) { + match pair { + (Some(mut lhs), Some(rhs)) => { + BitXorAssign::bitxor_assign(&mut lhs, rhs); + if !lhs.is_empty() { + self.containers.push(lhs); + } + } + (Some(lhs), None) => self.containers.push(lhs), + (None, Some(rhs)) => self.containers.push(rhs.clone()), + (None, None) => break, + } + } + } +} + +#[cfg(test)] +mod test { + use crate::{MultiOps, RoaringBitmap}; + use core::convert::Infallible; + use proptest::prelude::*; + + // fast count tests + proptest! { + #[test] + fn union_len_eq_len_of_materialized_union( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(a.union_len(&b), (a | b).len()); + } + + #[test] + fn intersection_len_eq_len_of_materialized_intersection( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(a.intersection_len(&b), (a & b).len()); + } + + #[test] + fn difference_len_eq_len_of_materialized_difference( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(a.difference_len(&b), (a - b).len()); + } + + #[test] + fn symmetric_difference_len_eq_len_of_materialized_symmetric_difference( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(a.symmetric_difference_len(&b), (a ^ b).len()); + } + + #[test] + fn all_union_give_the_same_result( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign |= &b; + ref_assign |= &c; + + let mut own_assign = a.clone(); + own_assign |= b.clone(); + own_assign |= c.clone(); + + let ref_inline = &a | &b | &c; + let own_inline = a.clone() | b.clone() | c.clone(); + + let ref_multiop = [&a, &b, &c].union(); + let own_multiop = [a.clone(), b.clone(), c.clone()].union(); + + let ref_multiop_try = [&a, &b, &c].map(Ok::<_, Infallible>).union().unwrap(); + let own_multiop_try = [a, b, c].map(Ok::<_, Infallible>).union().unwrap(); + + for roar in &[ + own_assign, + ref_inline, + own_inline, + ref_multiop, + own_multiop, + ref_multiop_try, + own_multiop_try, + ] { + prop_assert_eq!(&ref_assign, roar); + } + } + + #[test] + fn all_intersection_give_the_same_result( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign &= &b; + ref_assign &= &c; + + let mut own_assign = a.clone(); + own_assign &= b.clone(); + own_assign &= c.clone(); + + let ref_inline = &a & &b & &c; + let own_inline = a.clone() & b.clone() & c.clone(); + + let ref_multiop = [&a, &b, &c].intersection(); + let own_multiop = [a.clone(), b.clone(), c.clone()].intersection(); + + let ref_multiop_try = [&a, &b, &c].map(Ok::<_, Infallible>).intersection().unwrap(); + let own_multiop_try = [a, b, c].map(Ok::<_, Infallible>).intersection().unwrap(); + + for roar in &[ + own_assign, + ref_inline, + own_inline, + ref_multiop, + own_multiop, + ref_multiop_try, + own_multiop_try, + ] { + prop_assert_eq!(&ref_assign, roar); + } + } + + #[test] + fn all_difference_give_the_same_result( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign -= &b; + ref_assign -= &c; + + let mut own_assign = a.clone(); + own_assign -= b.clone(); + own_assign -= c.clone(); + + let ref_inline = &a - &b - &c; + let own_inline = a.clone() - b.clone() - c.clone(); + + let ref_multiop = [&a, &b, &c].difference(); + let own_multiop = [a.clone(), b.clone(), c.clone()].difference(); + + let ref_multiop_try = [&a, &b, &c].map(Ok::<_, Infallible>).difference().unwrap(); + let own_multiop_try = [a, b, c].map(Ok::<_, Infallible>).difference().unwrap(); + + for roar in &[ + own_assign, + ref_inline, + own_inline, + ref_multiop, + own_multiop, + ref_multiop_try, + own_multiop_try, + ] { + prop_assert_eq!(&ref_assign, roar); + } + } + + #[test] + fn all_symmetric_difference_give_the_same_result( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign ^= &b; + ref_assign ^= &c; + + let mut own_assign = a.clone(); + own_assign ^= b.clone(); + own_assign ^= c.clone(); + + let ref_inline = &a ^ &b ^ &c; + let own_inline = a.clone() ^ b.clone() ^ c.clone(); + + let ref_multiop = [&a, &b, &c].symmetric_difference(); + let own_multiop = [a.clone(), b.clone(), c.clone()].symmetric_difference(); + + let ref_multiop_try = [&a, &b, &c] + .map(Ok::<_, Infallible>) + .symmetric_difference() + .unwrap(); + let own_multiop_try = [a, b, c] + .map(Ok::<_, Infallible>) + .symmetric_difference() + .unwrap(); + + for roar in &[ + own_assign, + ref_inline, + own_inline, + ref_multiop, + own_multiop, + ref_multiop_try, + own_multiop_try, + ] { + prop_assert_eq!(&ref_assign, roar); + } + } + } +} diff --git a/vendor/roaring/src/bitmap/ops_with_serialized.rs b/vendor/roaring/src/bitmap/ops_with_serialized.rs new file mode 100644 index 0000000..3bae76c --- /dev/null +++ b/vendor/roaring/src/bitmap/ops_with_serialized.rs @@ -0,0 +1,300 @@ +use bytemuck::cast_slice_mut; +use byteorder::{LittleEndian, ReadBytesExt}; +use core::convert::Infallible; +use std::error::Error; +use std::io::{self, SeekFrom}; +use std::mem; +use std::ops::RangeInclusive; + +use crate::bitmap::container::Container; +use crate::bitmap::serialization::{ + NO_OFFSET_THRESHOLD, SERIAL_COOKIE, SERIAL_COOKIE_NO_RUNCONTAINER, +}; +use crate::RoaringBitmap; + +use super::container::ARRAY_LIMIT; +use super::store::{ArrayStore, BitmapStore, Store, BITMAP_LENGTH}; + +impl RoaringBitmap { + /// Computes the intersection between a materialized [`RoaringBitmap`] and a serialized one. + /// + /// This is faster and more space efficient when you only need the intersection result. + /// It reduces the number of deserialized internal container and therefore + /// the number of allocations and copies of bytes. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// use std::io::Cursor; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let rb2: RoaringBitmap = (3..5).collect(); + /// + /// // Let's say the rb2 bitmap is serialized + /// let mut bytes = Vec::new(); + /// rb2.serialize_into(&mut bytes).unwrap(); + /// let rb2_bytes = Cursor::new(bytes); + /// + /// assert_eq!( + /// rb1.intersection_with_serialized_unchecked(rb2_bytes).unwrap(), + /// rb1 & rb2, + /// ); + /// ``` + pub fn intersection_with_serialized_unchecked(&self, other: R) -> io::Result + where + R: io::Read + io::Seek, + { + RoaringBitmap::intersection_with_serialized_impl::( + self, + other, + |values| Ok(ArrayStore::from_vec_unchecked(values)), + |len, values| Ok(BitmapStore::from_unchecked(len, values)), + ) + } + + fn intersection_with_serialized_impl( + &self, + mut reader: R, + a: A, + b: B, + ) -> io::Result + where + R: io::Read + io::Seek, + A: Fn(Vec) -> Result, + AErr: Error + Send + Sync + 'static, + B: Fn(u64, Box<[u64; 1024]>) -> Result, + BErr: Error + Send + Sync + 'static, + { + // First read the cookie to determine which version of the format we are reading + let (size, has_offsets, has_run_containers) = { + let cookie = reader.read_u32::()?; + if cookie == SERIAL_COOKIE_NO_RUNCONTAINER { + (reader.read_u32::()? as usize, true, false) + } else if (cookie as u16) == SERIAL_COOKIE { + let size = ((cookie >> 16) + 1) as usize; + (size, size >= NO_OFFSET_THRESHOLD, true) + } else { + return Err(io::Error::other("unknown cookie value")); + } + }; + + // Read the run container bitmap if necessary + let run_container_bitmap = if has_run_containers { + let mut bitmap = vec![0u8; size.div_ceil(8)]; + reader.read_exact(&mut bitmap)?; + Some(bitmap) + } else { + None + }; + + if size > u16::MAX as usize + 1 { + return Err(io::Error::other("size is greater than supported")); + } + + // Read the container descriptions + let mut descriptions = vec![[0; 2]; size]; + reader.read_exact(cast_slice_mut(&mut descriptions))?; + descriptions.iter_mut().for_each(|[ref mut key, ref mut len]| { + *key = u16::from_le(*key); + *len = u16::from_le(*len); + }); + + if has_offsets { + let mut offsets = vec![0; size]; + reader.read_exact(cast_slice_mut(&mut offsets))?; + offsets.iter_mut().for_each(|offset| *offset = u32::from_le(*offset)); + return self.intersection_with_serialized_impl_with_offsets( + reader, + a, + b, + &descriptions, + &offsets, + run_container_bitmap.as_deref(), + ); + } + + // Read each container and skip the useless ones + let mut containers = Vec::new(); + for (i, &[key, len_minus_one]) in descriptions.iter().enumerate() { + let container = match self.containers.binary_search_by_key(&key, |c| c.key) { + Ok(index) => self.containers.get(index), + Err(_) => None, + }; + let cardinality = u64::from(len_minus_one) + 1; + + // If the run container bitmap is present, check if this container is a run container + let is_run_container = + run_container_bitmap.as_ref().is_some_and(|bm| bm[i / 8] & (1 << (i % 8)) != 0); + + let store = if is_run_container { + let runs = reader.read_u16::()?; + match container { + Some(_) => { + let mut intervals = vec![[0, 0]; runs as usize]; + reader.read_exact(cast_slice_mut(&mut intervals))?; + intervals.iter_mut().for_each(|[s, len]| { + *s = u16::from_le(*s); + *len = u16::from_le(*len); + }); + + let cardinality = intervals.iter().map(|[_, len]| *len as usize).sum(); + let mut store = Store::with_capacity(cardinality); + intervals.into_iter().try_for_each( + |[s, len]| -> Result<(), io::ErrorKind> { + let end = s.checked_add(len).ok_or(io::ErrorKind::InvalidData)?; + store.insert_range(RangeInclusive::new(s, end)); + Ok(()) + }, + )?; + store + } + None => { + let runs_size = mem::size_of::() * 2 * runs as usize; + reader.seek(SeekFrom::Current(runs_size as i64))?; + continue; + } + } + } else if cardinality <= ARRAY_LIMIT { + match container { + Some(_) => { + let mut values = vec![0; cardinality as usize]; + reader.read_exact(cast_slice_mut(&mut values))?; + values.iter_mut().for_each(|n| *n = u16::from_le(*n)); + let array = + a(values).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Store::Array(array) + } + None => { + let array_size = mem::size_of::() * cardinality as usize; + reader.seek(SeekFrom::Current(array_size as i64))?; + continue; + } + } + } else { + match container { + Some(_) => { + let mut values = Box::new([0; BITMAP_LENGTH]); + reader.read_exact(cast_slice_mut(&mut values[..]))?; + values.iter_mut().for_each(|n| *n = u64::from_le(*n)); + let bitmap = b(cardinality, values) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Store::Bitmap(bitmap) + } + None => { + let bitmap_size = mem::size_of::() * BITMAP_LENGTH; + reader.seek(SeekFrom::Current(bitmap_size as i64))?; + continue; + } + } + }; + + if let Some(container) = container { + let mut other_container = Container { key, store }; + other_container &= container; + if !other_container.is_empty() { + containers.push(other_container); + } + } + } + + Ok(RoaringBitmap { containers }) + } + + fn intersection_with_serialized_impl_with_offsets( + &self, + mut reader: R, + a: A, + b: B, + descriptions: &[[u16; 2]], + offsets: &[u32], + run_container_bitmap: Option<&[u8]>, + ) -> io::Result + where + R: io::Read + io::Seek, + A: Fn(Vec) -> Result, + AErr: Error + Send + Sync + 'static, + B: Fn(u64, Box<[u64; 1024]>) -> Result, + BErr: Error + Send + Sync + 'static, + { + let mut containers = Vec::new(); + for container in &self.containers { + let i = match descriptions.binary_search_by_key(&container.key, |[k, _]| *k) { + Ok(index) => index, + Err(_) => continue, + }; + + // Seek to the bytes of the container we want. + reader.seek(SeekFrom::Start(offsets[i] as u64))?; + + let [key, len_minus_one] = descriptions[i]; + let cardinality = u64::from(len_minus_one) + 1; + + // If the run container bitmap is present, check if this container is a run container + let is_run_container = + run_container_bitmap.as_ref().is_some_and(|bm| bm[i / 8] & (1 << (i % 8)) != 0); + + let store = if is_run_container { + let runs = reader.read_u16::().unwrap(); + let mut intervals = vec![[0, 0]; runs as usize]; + reader.read_exact(cast_slice_mut(&mut intervals)).unwrap(); + intervals.iter_mut().for_each(|[s, len]| { + *s = u16::from_le(*s); + *len = u16::from_le(*len); + }); + + let cardinality = intervals.iter().map(|[_, len]| *len as usize).sum(); + let mut store = Store::with_capacity(cardinality); + intervals.into_iter().try_for_each(|[s, len]| -> Result<(), io::ErrorKind> { + let end = s.checked_add(len).ok_or(io::ErrorKind::InvalidData)?; + store.insert_range(RangeInclusive::new(s, end)); + Ok(()) + })?; + store + } else if cardinality <= ARRAY_LIMIT { + let mut values = vec![0; cardinality as usize]; + reader.read_exact(cast_slice_mut(&mut values)).unwrap(); + values.iter_mut().for_each(|n| *n = u16::from_le(*n)); + let array = a(values).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Store::Array(array) + } else { + let mut values = Box::new([0; BITMAP_LENGTH]); + reader.read_exact(cast_slice_mut(&mut values[..])).unwrap(); + values.iter_mut().for_each(|n| *n = u64::from_le(*n)); + let bitmap = b(cardinality, values) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Store::Bitmap(bitmap) + }; + + let mut other_container = Container { key, store }; + other_container &= container; + if !other_container.is_empty() { + containers.push(other_container); + } + } + + Ok(RoaringBitmap { containers }) + } +} + +#[cfg(test)] +mod test { + use crate::RoaringBitmap; + use proptest::prelude::*; + use std::io::Cursor; + + // fast count tests + proptest! { + #[test] + fn intersection_with_serialized_eq_materialized_intersection( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + let mut serialized_bytes_b = Vec::new(); + b.serialize_into(&mut serialized_bytes_b).unwrap(); + let serialized_bytes_b = &serialized_bytes_b[..]; + + prop_assert_eq!(a.intersection_with_serialized_unchecked(Cursor::new(serialized_bytes_b)).unwrap(), a & b); + } + } +} diff --git a/vendor/roaring/src/bitmap/proptests.rs b/vendor/roaring/src/bitmap/proptests.rs new file mode 100644 index 0000000..54b9c07 --- /dev/null +++ b/vendor/roaring/src/bitmap/proptests.rs @@ -0,0 +1,1117 @@ +#[cfg(test)] +#[allow(clippy::eq_op)] // Allow equal expressions as operands +mod test { + use crate::RoaringBitmap; + use proptest::prelude::*; + + // + // Tests algebraic set properties in terms of RoaringBitmaps. + // Follows wikipedia article regarding ordering and heading + // + // https://en.wikipedia.org/wiki/Algebra_of_sets + // + // Notes: + // + // * Although a universe set exists, we leave properties involving it it out of these tests. + // It would be ~512 MiB and operations on it would be relatively slow + // + // * Likewise, there is no compliment operator + // + // + // + // + // The fundamental properties of set algebra + // ========================================= + // + // Commutative property: + // -------------------- + + proptest! { + #[test] + fn unions_are_commutative( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(&a | &b, &b | &a); + + { // op_assign_ref + let mut x = a.clone(); + let mut y = b.clone(); + + x |= &b; + y |= &a; + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = a.clone(); + let mut y = b.clone(); + + x |= b; + y |= a; + + prop_assert_eq!(x, y); + } + } + + #[test] + fn intersections_are_commutative( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(&a & &b, &b & &a); + + { // op_assign_ref + let mut x = a.clone(); + let mut y = b.clone(); + + x &= &b; + y &= &a; + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = a.clone(); + let mut y = b.clone(); + + x &= b; + y &= a; + + prop_assert_eq!(x, y); + } + } + + #[test] + fn symmetric_differences_are_commutative( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!(&a ^ &b, &b ^ &a); + + { // op_assign_ref + let mut x = a.clone(); + let mut y = b.clone(); + + x ^= &b; + y ^= &a; + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = a.clone(); + let mut y = b.clone(); + + x ^= b; + y ^= a; + + prop_assert_eq!(x, y); + } + } + } + + // + // Associative property: + // --------------------- + + proptest! { + #[test] + fn unions_are_associative( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &a | ( &b | &c ), + ( &a | &b ) | &c + ); + + { // op_assign_ref + let mut x = b.clone(); + x |= &c; + x |= &a; + + let mut y = a.clone(); + y |= &b; + y |= &c; + + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = b.clone(); + x |= c.clone(); + x |= a.clone(); + + let mut y = a; + y |= b; + y |= c; + + + prop_assert_eq!(x, y); + } + } + + #[test] + fn intersections_are_associative( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &a & ( &b & &c ), + ( &a & &b ) & &c + ); + + { // op_assign_ref + let mut x = b.clone(); + x &= &c; + x &= &a; + + let mut y = a.clone(); + y &= &b; + y &= &c; + + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = b.clone(); + x &= c.clone(); + x &= a.clone(); + + let mut y = a; + y &= b; + y &= c; + + + prop_assert_eq!(x, y); + } + } + + #[test] + fn symmetric_differences_are_associative( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &a ^ ( &b ^ &c ), + ( &a ^ &b ) ^ &c + ); + + { // op_assign_ref + let mut x = b.clone(); + x ^= &c; + x ^= &a; + + let mut y = a.clone(); + y ^= &b; + y ^= &c; + + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = b.clone(); + x ^= c.clone(); + x ^= a.clone(); + + let mut y = a; + y ^= b; + y ^= c; + + + prop_assert_eq!(x, y); + } + } + } + + // + // Distributive property: + // --------------------- + + proptest! { + #[test] + fn union_distributes_over_intersection( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &a | ( &b & &c), + ( &a | &b ) & ( &a | &c ) + ); + + { // op_assign_ref + let mut x = b.clone(); + x &= &c; + x |= &a; + + let y = { + let mut ab = a.clone(); + ab |= &b; + + let mut ac = a.clone(); + ac |= &c; + + ab &= ∾ + ab + }; + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = b.clone(); + x &= c.clone(); + x |= a.clone(); + + let y = { + let mut ab = a.clone(); + ab |= b; + + let mut ac = a; + ac |= c; + + // moves the owned ac on the rhs + ab &= ac; + ab + }; + + prop_assert_eq!(x, y); + } + } + + #[test] + fn intersection_distributes_over_union( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &a & ( &b | &c), + ( &a & &b ) | ( &a & &c ) + ); + + { // op_assign_ref + let mut x = b.clone(); + x |= &c; + x &= &a; + + let y = { + let mut ab = a.clone(); + ab &= &b; + + let mut ac = a.clone(); + ac &= &c; + + ab |= ∾ + ab + }; + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = b.clone(); + x |= c.clone(); + x &= a.clone(); + + let y = { + let mut ab = a.clone(); + ab &= b; + + let mut ac = a; + ac &= c; + + // moves the owned ac on the rhs + ab |= ac; + ab + }; + + prop_assert_eq!(x, y); + } + } + + #[test] + fn intersection_distributes_over_symmetric_difference( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &a & ( &b ^ &c), + ( &a & &b ) ^ ( &a & &c ) + ); + + { // op_assign_ref + let mut x = b.clone(); + x ^= &c; + x &= &a; + + let y = { + let mut ab = a.clone(); + ab &= &b; + + let mut ac = a.clone(); + ac &= &c; + + ab ^= ∾ + ab + }; + + prop_assert_eq!(x, y); + } + + { // op_assign_own + let mut x = b.clone(); + x ^= c.clone(); + x &= a.clone(); + + let y = { + let mut ab = a.clone(); + ab &= b; + + let mut ac = a; + ac &= c; + + // moves the owned ac on the rhs + ab ^= ac; + ab + }; + + prop_assert_eq!(x, y); + } + } + } + + // Identity: + // -------- + + proptest! { + #[test] + fn the_empty_set_is_the_identity_for_union(a in RoaringBitmap::arbitrary()) { + prop_assert_eq!(&(&a | &empty_set()), &a); + + #[allow(clippy::redundant_clone)] + { // op_assign_ref + let mut x = a.clone(); + x |= &empty_set(); + + prop_assert_eq!(x, a.clone()); + } + + { // op_assign_own + let mut x = a.clone(); + // empty_set() returns an owned empty set + x |= empty_set(); + + prop_assert_eq!(x, a); + } + } + + #[test] + fn the_empty_set_is_the_identity_for_symmetric_difference(a in RoaringBitmap::arbitrary()) { + prop_assert_eq!(&(&a ^ &empty_set()), &a); + + #[allow(clippy::redundant_clone)] + { // op_assign_ref + let mut x = a.clone(); + x ^= &empty_set(); + + prop_assert_eq!(x, a.clone()); + } + + { // op_assign_own + let mut x = a.clone(); + // empty_set() returns an owned empty set + x ^= empty_set(); + + prop_assert_eq!(x, a); + } + } + } + + // Some additional laws for unions and intersections + // ================================================= + // + // PROPOSITION 3: For any subsets A and B of a universe set U, the following identities hold: + // + // Idempotent laws + // --------------- + + proptest! { + #[test] + fn unions_are_idempotent(a in RoaringBitmap::arbitrary()) { + prop_assert_eq!(&(&a | &a), &a); + + { // op_assign_ref + let mut x = a.clone(); + x |= &a; + + prop_assert_eq!(x, a.clone()); + } + + { // op_assign_own + let mut x = a.clone(); + x |= a.clone(); + + prop_assert_eq!(x, a); + } + } + + #[test] + fn intersections_are_idempotent(a in RoaringBitmap::arbitrary()) { + prop_assert_eq!(&(&a & &a), &a); + + { // op_assign_ref + let mut x = a.clone(); + x &= &a; + + prop_assert_eq!(x, a.clone()); + } + + { // op_assign_own + let mut x = a.clone(); + x &= a.clone(); + + prop_assert_eq!(x, a); + } + } + } + + // + // Domination laws + // --------------- + + proptest! { + #[test] + fn empty_set_domination(a in RoaringBitmap::arbitrary()) { + prop_assert_eq!(&a & &empty_set(), empty_set()); + + { // op_assign_ref + let mut x = a.clone(); + x &= &empty_set(); + + prop_assert_eq!(x, empty_set()); + } + + { // op_assign_own + let mut x = a; + x &= empty_set(); + + prop_assert_eq!(x, empty_set()); + } + } + } + + // The algebra of inclusion + // ======================== + // PROPOSITION 6: If A, B and C are sets then the following hold: + // + // Note that for inclusion we do not also assert for the assignment operators + // Inclusion is the property under test, not the set operation + + proptest! { + #[test] + fn reflexivity(a in RoaringBitmap::arbitrary()) { + prop_assert!(a.is_subset(&a)); + } + + #[test] + fn antisymmetry(a in RoaringBitmap::arbitrary()) { + let mut b = a.clone(); + prop_assert_eq!(&a, &b); + prop_assert!(a.is_subset(&b) && b.is_subset(&a)); + + // Flip one bit + let mut c = RoaringBitmap::new(); + c.insert(0); + b ^= c; + + prop_assert_ne!(&a, &b); + prop_assert!(!(a.is_subset(&b) && b.is_subset(&a))); + } + + #[test] + fn transitivity( + a in RoaringBitmap::arbitrary(), + mut b in RoaringBitmap::arbitrary(), + mut c in RoaringBitmap::arbitrary() + ) { + b |= &a; + c |= &b; + // If + prop_assert!(a.is_subset(&b)); + prop_assert!(b.is_subset(&c)); + // Then + prop_assert!(a.is_subset(&c)); + + } + } + + // PROPOSITION 7: If A, B and C are subsets of a set S then the following hold: + + proptest! { + #[test] + fn existence_of_joins(a in RoaringBitmap::arbitrary(), b in RoaringBitmap::arbitrary()) { + prop_assert!(a.is_subset(&(&a | &b))); + } + + #[test] + fn existence_of_meets(a in RoaringBitmap::arbitrary(), b in RoaringBitmap::arbitrary()) { + prop_assert!(&(&a & &b).is_subset(&a)); + } + } + + // PROPOSITION 8: For any two sets A and B, the following are equivalent: + + proptest! { + #[test] + fn inclusion_can_be_characterized_by_union_or_inersection( + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + let a = &b - &c; + + prop_assert!(a.is_subset(&b)); + prop_assert_eq!(&(&a & &b), &a); + prop_assert_eq!(&(&a | &b), &b); + prop_assert_eq!(&(&a - &b), &empty_set()); + } + } + + // The algebra of relative complements + // =================================== + // + // PROPOSITION 9: For any universe U and subsets A, B, and C of U, + // the following identities hold: + // Note: I dont have good names for these identities. If somebody could give them good names + // and split each triplet of ref-ref, owned-ref, and owned-owned into a separate test: + // I will happily buy them a very large but finite number of beers. + + proptest! { + #[test] + fn relative_compliments( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + let u = &a | &b | &c; + + prop_assert_eq!( + &c - (&a & &b), + (&c - &a) | (&c - &b) + ); + + { // op assign ref + let mut a_and_b = a.clone(); + a_and_b &= &b; + + let mut c_sub_a = c.clone(); + c_sub_a -= &a; + + let mut c_sub_b = c.clone(); + c_sub_b -= &b; + + let mut x = c.clone(); + x -= &a_and_b; + + let mut y = c_sub_a; + y |= &c_sub_b; + + prop_assert_eq!(x, y); + } + + { // op assign own + let mut a_and_b = a.clone(); + a_and_b &= b.clone(); + + let mut c_sub_a = c.clone(); + c_sub_a -= a.clone(); + + let mut c_sub_b = c.clone(); + c_sub_b -= b.clone(); + + let mut x = c.clone(); + x -= a_and_b; + + let mut y = c_sub_a; + y |= c_sub_b; + + prop_assert_eq!(x, y); + } + + prop_assert_eq!( + &c - (&a | &b), + (&c - &a) & (&c - &b) + ); + + { // op assign ref + let mut a_or_b = a.clone(); + a_or_b |= &b; + + let mut c_sub_a = c.clone(); + c_sub_a -= &a; + + let mut c_sub_b = c.clone(); + c_sub_b -= &b; + + let mut x = c.clone(); + x -= &a_or_b; + + let mut y = c_sub_a; + y &= &c_sub_b; + + prop_assert_eq!(x, y); + } + + { // op assign own + let mut a_or_b = a.clone(); + a_or_b |= b.clone(); + + let mut c_sub_a = c.clone(); + c_sub_a -= a.clone(); + + let mut c_sub_b = c.clone(); + c_sub_b -= b.clone(); + + let mut x = c.clone(); + x -= a_or_b; + + let mut y = c_sub_a; + y &= c_sub_b; + + prop_assert_eq!(x, y); + } + + prop_assert_eq!( + &c - (&b - &a), + (&a & &c) | (&c - &b) + ); + + { // op assign ref + let mut b_sub_a = b.clone(); + b_sub_a -= &b; + + let mut a_and_c = c.clone(); + a_and_c &= &c; + + let mut c_sub_b = c.clone(); + c_sub_b -= &b; + + let mut x = c.clone(); + x -= &b_sub_a; + + let mut y = a_and_c; + y |= &c_sub_b; + + prop_assert_eq!(x, y); + } + + { // op assign own + let mut b_sub_a = b.clone(); + b_sub_a -= b.clone(); + + let mut a_and_c = c.clone(); + a_and_c &= c.clone(); + + let mut c_sub_b = c.clone(); + c_sub_b -= b.clone(); + + let mut x = c.clone(); + x -= b_sub_a; + + let mut y = a_and_c; + y |= c_sub_b; + + prop_assert_eq!(x, y); + } + + { + let x = (&b - &a) & &c; + let y = (&b & &c) - &a; + let z = &b & (&c - &a); + + prop_assert_eq!(&x, &y); + prop_assert_eq!(&y, &z); + prop_assert_eq!(&z, &x); + } + + { // op assign ref + let mut b_sub_a = b.clone(); + b_sub_a -= &a; + + let mut b_and_c = b.clone(); + b_and_c &= &c; + + let mut c_sub_a = c.clone(); + c_sub_a -= &a; + + let mut x = b_sub_a; + x &= &c; + + let mut y = b_and_c; + y -= &a; + + let mut z = c_sub_a; + z &= &b; + + prop_assert_eq!(&x, &y); + prop_assert_eq!(&y, &z); + prop_assert_eq!(&z, &x); + } + + { // op assign own + let mut b_sub_a = b.clone(); + b_sub_a -= a.clone(); + + let mut b_and_c = b.clone(); + b_and_c &= c.clone(); + + let mut c_sub_a = c.clone(); + c_sub_a -= a.clone(); + + let mut x = b_sub_a; + x &= c.clone(); + + let mut y = b_and_c; + y -= a.clone(); + + let mut z = c_sub_a; + z &= b.clone(); + + prop_assert_eq!(&x, &y); + prop_assert_eq!(&y, &z); + prop_assert_eq!(&z, &x); + } + + prop_assert_eq!( + (&b - &a) | &c, + (&b | &c) - (&a - &c) + ); + + { // op assign ref + let mut b_sub_a = b.clone(); + b_sub_a -= &a; + + let mut b_or_c = b.clone(); + b_or_c |= &c; + + let mut a_sub_c = a.clone(); + a_sub_c -= &c; + + let mut x = b_sub_a; + x |= &c; + + let mut y = b_or_c; + y -= &a_sub_c; + + prop_assert_eq!(x, y); + } + + { // op assign own + let mut b_sub_a = b.clone(); + b_sub_a -= a.clone(); + + let mut b_or_c = b.clone(); + b_or_c |= c.clone(); + + let mut a_sub_c = a.clone(); + a_sub_c -= c.clone(); + + let mut x = b_sub_a; + x |= c.clone(); + + let mut y = b_or_c; + y -= a_sub_c; + + prop_assert_eq!(x, y); + } + + prop_assert_eq!( + (&b - &a) - &c, + &b - (&a | &c) + ); + + { // op assign ref + let mut b_sub_a = b.clone(); + b_sub_a -= &a; + + let mut a_or_c = a.clone(); + a_or_c |= &c; + + let mut x = b_sub_a; + x -= &c; + + let mut y = b.clone(); + y -= &a_or_c; + + prop_assert_eq!(x, y); + } + + { // op assign ref + let mut b_sub_a = b.clone(); + b_sub_a -= a.clone(); + + let mut a_or_c = a.clone(); + a_or_c |= c.clone(); + + let mut x = b_sub_a; + x -= c; + + let mut y = b; + y -= a_or_c; + + prop_assert_eq!(x, y); + } + + prop_assert_eq!( + &a - &a, + empty_set() + ); + + { // op assign ref + let mut x = a.clone(); + x -= &a; + + prop_assert_eq!(x, empty_set()); + } + + { // op assign own + let mut x = a.clone(); + x -= a.clone(); + + prop_assert_eq!(x, empty_set()); + } + + prop_assert_eq!( + empty_set() - &a, + empty_set() + ); + + { // op assign ref + let mut x = empty_set(); + x -= &a; + + prop_assert_eq!(x, empty_set()); + } + + { // op assign own + let mut x = empty_set(); + x -= a.clone(); + + prop_assert_eq!(x, empty_set()); + } + + prop_assert_eq!( + &a - &u, + empty_set() + ); + + { // op assign ref + let mut x = a.clone(); + x -= &u; + + prop_assert_eq!(x, empty_set()); + } + + { // op assign own + let mut x = a; + x -= u; + + prop_assert_eq!(x, empty_set()); + } + } + } + + // Additional properties of symmetric differences + // ============================================== + // + + proptest! { + #[test] + fn symmetric_difference_triangle_inequality( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary(), + c in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &((&a ^ &b) ^ (&b ^ &c)), + &(&a ^ &c) + ); + + { // op assign ref + let mut a_xor_b = a.clone(); + a_xor_b ^= &b; + + let mut b_xor_c = b.clone(); + b_xor_c ^= &c; + + let mut a_xor_c = a.clone(); + a_xor_c ^= &c; + + let mut tri = a_xor_b; + tri ^= &b_xor_c; + + prop_assert_eq!(tri, a_xor_c); + } + + { // op assign own + let mut a_xor_b = a.clone(); + a_xor_b ^= b.clone(); + + let mut b_xor_c = b; + b_xor_c ^= c.clone(); + + let mut a_xor_c = a; + a_xor_c ^= c; + + let mut tri = a_xor_b; + tri ^= b_xor_c; + + prop_assert_eq!(tri, a_xor_c); + } + } + + #[test] + fn symmetric_difference_empty_set_neutral( + a in RoaringBitmap::arbitrary() + ) { + prop_assert_eq!( + &(&a ^ &empty_set()), + &a + ); + + { // op assign ref + let mut x = a.clone(); + x ^= &empty_set(); + + prop_assert_eq!(&x, &a); + } + + { // op assign own + let mut x = a.clone(); + x ^= empty_set(); + + prop_assert_eq!(x, a); + } + } + + #[test] + fn symmetric_difference_inverse_of_itself( + a in RoaringBitmap::arbitrary() + ) { + + prop_assert_eq!( + &(&a ^ &a), + &empty_set() + ); + + { // op assign ref + let mut x = a.clone(); + x ^= &a; + + prop_assert_eq!(&x, &empty_set()); + } + + { // op assign own + let mut x = a.clone(); + x ^= a; + + prop_assert_eq!(x, empty_set()); + } + } + + #[test] + fn symmetric_difference_relative_compliments( + a in RoaringBitmap::arbitrary(), + b in RoaringBitmap::arbitrary() + ) { + + prop_assert_eq!( + &(&a ^ &b), + &(&(&a - &b) | &(&b - &a)) + ); + + { // op assign ref + let mut x = a.clone(); + x ^= &b; + + let mut a_sub_b = a.clone(); + a_sub_b -= &b; + + let mut b_sub_a = b.clone(); + b_sub_a -= &a; + + let mut y = a_sub_b; + y |= &b_sub_a; + + prop_assert_eq!(x, y); + } + + { // op assign own + let mut x = a.clone(); + x ^= b.clone(); + + let mut a_sub_b = a.clone(); + a_sub_b -= b.clone(); + + let mut b_sub_a = b.clone(); + b_sub_a -= a.clone(); + + let mut y = a_sub_b; + y |= b_sub_a; + + prop_assert_eq!(x, y); + } + + prop_assert_eq!( + &(&a ^ &b), + &(&(&a | &b) - &(&a & &b)) + ); + + { // op assign ref + let mut x = a.clone(); + x ^= &b; + + let mut a_or_b = a.clone(); + a_or_b |= &b; + + let mut a_and_b = a.clone(); + a_and_b &= &b; + + let mut y = a_or_b; + y -= &a_and_b; + + prop_assert_eq!(x, y); + } + + { // op assign own + let mut x = a.clone(); + x ^= b.clone(); + + let mut a_or_b = a.clone(); + a_or_b |= b.clone(); + + let mut a_and_b = a; + a_and_b &= b; + + let mut y = a_or_b; + y -= a_and_b; + + prop_assert_eq!(x, y); + } + } + } + + fn empty_set() -> RoaringBitmap { + RoaringBitmap::new() + } +} diff --git a/vendor/roaring/src/bitmap/serde.rs b/vendor/roaring/src/bitmap/serde.rs new file mode 100644 index 0000000..08fa462 --- /dev/null +++ b/vendor/roaring/src/bitmap/serde.rs @@ -0,0 +1,82 @@ +use serde::de::SeqAccess; +use serde::de::Visitor; +use serde::Deserialize; +use serde::Deserializer; +use serde::Serialize; + +use crate::RoaringBitmap; + +impl<'de> Deserialize<'de> for RoaringBitmap { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct BitmapVisitor; + + impl<'de> Visitor<'de> for BitmapVisitor { + type Value = RoaringBitmap; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("roaring bitmap") + } + + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: serde::de::Error, + { + RoaringBitmap::deserialize_from(bytes).map_err(serde::de::Error::custom) + } + + // in some case bytes will be serialized as a sequence thus we need to accept both + // even if it means non optimal performance + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut bytes: Vec = Vec::new(); + while let Some(el) = seq.next_element()? { + bytes.push(el); + } + RoaringBitmap::deserialize_from(&*bytes).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_bytes(BitmapVisitor) + } +} + +impl Serialize for RoaringBitmap { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut buf = Vec::new(); + self.serialize_into(&mut buf).map_err(serde::ser::Error::custom)?; + + serializer.serialize_bytes(&buf) + } +} + +#[cfg(test)] +mod test { + use crate::RoaringBitmap; + use proptest::prelude::*; + + proptest! { + #[test] + fn test_serde_json( + bitmap in RoaringBitmap::arbitrary(), + ) { + let json = serde_json::to_vec(&bitmap).unwrap(); + prop_assert_eq!(bitmap, serde_json::from_slice(&json).unwrap()); + } + + #[test] + fn test_postcard( + bitmap in RoaringBitmap::arbitrary(), + ) { + let buffer = postcard::to_allocvec(&bitmap).unwrap(); + prop_assert_eq!(bitmap, postcard::from_bytes(&buffer).unwrap()); + } + } +} diff --git a/vendor/roaring/src/bitmap/serialization.rs b/vendor/roaring/src/bitmap/serialization.rs new file mode 100644 index 0000000..cce5027 --- /dev/null +++ b/vendor/roaring/src/bitmap/serialization.rs @@ -0,0 +1,443 @@ +use crate::bitmap::container::{Container, ARRAY_LIMIT}; +use crate::bitmap::store::{ + ArrayStore, BitmapStore, Interval, Store, BITMAP_BYTES, BITMAP_LENGTH, RUN_ELEMENT_BYTES, + RUN_NUM_BYTES, +}; +use crate::RoaringBitmap; +use bytemuck::cast_slice_mut; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use core::convert::Infallible; +use std::error::Error; +use std::io; + +use super::store::IntervalStore; + +pub(crate) const SERIAL_COOKIE_NO_RUNCONTAINER: u32 = 12346; +pub(crate) const SERIAL_COOKIE: u16 = 12347; +pub(crate) const NO_OFFSET_THRESHOLD: usize = 4; + +// Sizes of header structures +pub(crate) const COOKIE_BYTES: usize = 4; +pub(crate) const SIZE_BYTES: usize = 4; +pub(crate) const DESCRIPTION_BYTES: usize = 4; +pub(crate) const OFFSET_BYTES: usize = 4; + +impl RoaringBitmap { + /// Return the size in bytes of the serialized output. + /// This is compatible with the official C/C++, Java and Go implementations. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let mut bytes = Vec::with_capacity(rb1.serialized_size()); + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringBitmap::deserialize_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn serialized_size(&self) -> usize { + let mut has_run_containers = false; + let size = self.containers.len(); + let container_sizes: usize = self + .containers + .iter() + .map(|container| match container.store { + Store::Array(ref values) => values.byte_size(), + Store::Bitmap(..) => BITMAP_BYTES, + Store::Run(ref intervals) => { + has_run_containers = true; + intervals.byte_size() + } + }) + .sum(); + + // header + container sizes + header_size(size, has_run_containers) + container_sizes + } + + /// Serialize this bitmap into [the standard Roaring on-disk format][format]. + /// This is compatible with the official C/C++, Java and Go implementations. + /// + /// [format]: https://github.com/RoaringBitmap/RoaringFormatSpec + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let mut bytes = vec![]; + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringBitmap::deserialize_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn serialize_into(&self, mut writer: W) -> io::Result<()> { + let has_run_containers = self.containers.iter().any(|c| matches!(c.store, Store::Run(_))); + let size = self.containers.len(); + + // Depending on if run containers are present or not write the appropriate header + if has_run_containers { + // The new format stores the container count in the most significant bits of the header + let cookie = SERIAL_COOKIE as u32 | ((size as u32 - 1) << 16); + writer.write_u32::(cookie)?; + // It is then followed by a bitset indicating which containers are run containers + let run_container_bitmap_size = size.div_ceil(8); + let mut run_container_bitmap = vec![0; run_container_bitmap_size]; + for (i, container) in self.containers.iter().enumerate() { + if let Store::Run(_) = container.store { + run_container_bitmap[i / 8] |= 1 << (i % 8); + } + } + writer.write_all(&run_container_bitmap)?; + } else { + // Write old format, cookie followed by container count + writer.write_u32::(SERIAL_COOKIE_NO_RUNCONTAINER)?; + writer.write_u32::(size as u32)?; + } + + // Write the container descriptions + for container in &self.containers { + writer.write_u16::(container.key)?; + writer.write_u16::((container.len() - 1) as u16)?; + } + + let mut offset = header_size(size, has_run_containers) as u32; + let has_offsets = if has_run_containers { size >= OFFSET_BYTES } else { true }; + if has_offsets { + for container in &self.containers { + writer.write_u32::(offset)?; + match container.store { + Store::Array(ref values) => { + offset += values.len() as u32 * 2; + } + Store::Bitmap(..) => { + offset += 8 * 1024; + } + Store::Run(ref intervals) => { + offset += (RUN_NUM_BYTES + + (intervals.run_amount() as usize * RUN_ELEMENT_BYTES)) + as u32; + } + } + } + } + + for container in &self.containers { + match container.store { + Store::Array(ref values) => { + for &value in values.iter() { + writer.write_u16::(value)?; + } + } + Store::Bitmap(ref bits) => { + for &value in bits.as_array() { + writer.write_u64::(value)?; + } + } + Store::Run(ref intervals) => { + writer.write_u16::(intervals.run_amount() as u16)?; + for iv in intervals.iter_intervals() { + writer.write_u16::(iv.start())?; + writer.write_u16::(iv.end() - iv.start())?; + } + } + } + } + + Ok(()) + } + + /// Deserialize a bitmap into memory from [the standard Roaring on-disk + /// format][format]. This is compatible with the official C/C++, Java and + /// Go implementations. This method checks that all of the internal values + /// are valid. If deserializing from a trusted source consider + /// [RoaringBitmap::deserialize_unchecked_from] + /// + /// [format]: https://github.com/RoaringBitmap/RoaringFormatSpec + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let mut bytes = vec![]; + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringBitmap::deserialize_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn deserialize_from(reader: R) -> io::Result { + RoaringBitmap::deserialize_from_impl(reader, ArrayStore::try_from, BitmapStore::try_from) + } + + /// Deserialize a bitmap into memory from [the standard Roaring on-disk + /// format][format]. This is compatible with the official C/C++, Java and + /// Go implementations. This method is memory safe but will not check if + /// the data is a valid bitmap. + /// + /// [format]: https://github.com/RoaringBitmap/RoaringFormatSpec + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringBitmap; + /// + /// let rb1: RoaringBitmap = (1..4).collect(); + /// let mut bytes = vec![]; + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringBitmap::deserialize_unchecked_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn deserialize_unchecked_from(reader: R) -> io::Result { + RoaringBitmap::deserialize_from_impl::( + reader, + |values| Ok(ArrayStore::from_vec_unchecked(values)), + |len, values| Ok(BitmapStore::from_unchecked(len, values)), + ) + } + + fn deserialize_from_impl( + mut reader: R, + a: A, + b: B, + ) -> io::Result + where + R: io::Read, + A: Fn(Vec) -> Result, + AErr: Error + Send + Sync + 'static, + B: Fn(u64, Box<[u64; 1024]>) -> Result, + BErr: Error + Send + Sync + 'static, + { + // First read the cookie to determine which version of the format we are reading + let (size, has_offsets, has_run_containers) = { + let cookie = reader.read_u32::()?; + if cookie == SERIAL_COOKIE_NO_RUNCONTAINER { + (reader.read_u32::()? as usize, true, false) + } else if (cookie as u16) == SERIAL_COOKIE { + let size = ((cookie >> 16) + 1) as usize; + (size, size >= NO_OFFSET_THRESHOLD, true) + } else { + return Err(io::Error::other("unknown cookie value")); + } + }; + + // Read the run container bitmap if necessary + let run_container_bitmap = if has_run_containers { + let mut bitmap = vec![0u8; size.div_ceil(8)]; + reader.read_exact(&mut bitmap)?; + Some(bitmap) + } else { + None + }; + + if size > u16::MAX as usize + 1 { + return Err(io::Error::other("size is greater than supported")); + } + + // Read the container descriptions + let mut description_bytes = vec![0u8; size * DESCRIPTION_BYTES]; + reader.read_exact(&mut description_bytes)?; + let mut description_bytes = &description_bytes[..]; + + if has_offsets { + let mut offsets = vec![0u8; size * OFFSET_BYTES]; + reader.read_exact(&mut offsets)?; + drop(offsets); // Not useful when deserializing into memory + } + + let mut containers = Vec::with_capacity(size); + + let mut last_key = None::; + // Read each container + for i in 0..size { + let key = description_bytes.read_u16::()?; + if let Some(last_key) = last_key.replace(key) { + if key <= last_key { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "container keys are not sorted", + )); + } + } + let cardinality = u64::from(description_bytes.read_u16::()?) + 1; + + // If the run container bitmap is present, check if this container is a run container + let is_run_container = + run_container_bitmap.as_ref().is_some_and(|bm| bm[i / 8] & (1 << (i % 8)) != 0); + + let store = if is_run_container { + let runs = reader.read_u16::()?; + if runs == 0 { + return Err(io::Error::new( + io::ErrorKind::InvalidData, + "run container with zero runs", + )); + } + let mut intervals = vec![[0, 0]; runs as usize]; + reader.read_exact(cast_slice_mut(&mut intervals))?; + intervals.iter_mut().for_each(|[s, len]| { + *s = u16::from_le(*s); + *len = u16::from_le(*len); + }); + + let mut last_end = None::; + let store = IntervalStore::from_vec_unchecked( + intervals + .into_iter() + .map(|[s, len]| -> Result { + let end = s.checked_add(len).ok_or(io::ErrorKind::InvalidData)?; + if let Some(last_end) = last_end.replace(end) { + if s <= last_end.saturating_add(1) { + // Range overlaps or would be contiguous with the previous range + return Err(io::ErrorKind::InvalidData); + } + } + Ok(Interval::new_unchecked(s, end)) + }) + .collect::>()?, + ); + Store::Run(store) + } else if cardinality <= ARRAY_LIMIT { + let mut values = vec![0; cardinality as usize]; + reader.read_exact(cast_slice_mut(&mut values))?; + values.iter_mut().for_each(|n| *n = u16::from_le(*n)); + let array = a(values).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Store::Array(array) + } else { + let mut values = Box::new([0; BITMAP_LENGTH]); + reader.read_exact(cast_slice_mut(&mut values[..]))?; + values.iter_mut().for_each(|n| *n = u64::from_le(*n)); + let bitmap = b(cardinality, values) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; + Store::Bitmap(bitmap) + }; + + containers.push(Container { key, store }); + } + + Ok(RoaringBitmap { containers }) + } +} + +fn header_size(size: usize, has_run_containers: bool) -> usize { + if has_run_containers { + // New format encodes the size (number of containers) into the 4 byte cookie + // Additionally a bitmap is included marking which containers are run containers + let run_container_bitmap_size = size.div_ceil(8); + // New format conditionally includes offsets if there are 4 or more containers + if size >= NO_OFFSET_THRESHOLD { + COOKIE_BYTES + ((DESCRIPTION_BYTES + OFFSET_BYTES) * size) + run_container_bitmap_size + } else { + COOKIE_BYTES + (DESCRIPTION_BYTES * size) + run_container_bitmap_size + } + } else { + // Old format encodes cookie followed by container count + // It also always includes the offsets + COOKIE_BYTES + SIZE_BYTES + ((DESCRIPTION_BYTES + OFFSET_BYTES) * size) + } +} + +#[cfg(test)] +mod test { + use crate::{bitmap::store::BITMAP_LENGTH, RoaringBitmap}; + use proptest::prelude::*; + + proptest! { + #[test] + fn test_serialization( + bitmap in RoaringBitmap::arbitrary(), + ) { + let mut buffer = Vec::new(); + bitmap.serialize_into(&mut buffer).unwrap(); + prop_assert_eq!(bitmap, RoaringBitmap::deserialize_from(buffer.as_slice()).unwrap()); + } + } + + #[test] + fn test_from_lsb0_bytes() { + const CONTAINER_OFFSET: u32 = u64::BITS * BITMAP_LENGTH as u32; + const CONTAINER_OFFSET_IN_BYTES: u32 = CONTAINER_OFFSET / 8; + let mut bytes = vec![0xff; CONTAINER_OFFSET_IN_BYTES as usize]; + bytes.extend([0x00; CONTAINER_OFFSET_IN_BYTES as usize]); + bytes.extend([0b00000001, 0b00000010, 0b00000011, 0b00000100]); + + let offset = 32; + let rb = RoaringBitmap::from_lsb0_bytes(offset, &bytes); + for i in 0..offset { + assert!(!rb.contains(i), "{i} should not be in the bitmap"); + } + for i in offset..offset + CONTAINER_OFFSET { + assert!(rb.contains(i), "{i} should be in the bitmap"); + } + for i in offset + CONTAINER_OFFSET..offset + CONTAINER_OFFSET * 2 { + assert!(!rb.contains(i), "{i} should not be in the bitmap"); + } + for bit in [0, 9, 16, 17, 26] { + let i = bit + offset + CONTAINER_OFFSET * 2; + assert!(rb.contains(i), "{i} should be in the bitmap"); + } + + assert_eq!(rb.len(), CONTAINER_OFFSET as u64 + 5); + + // Ensure the empty container is not created + let mut bytes = vec![0x00u8; CONTAINER_OFFSET_IN_BYTES as usize]; + bytes.extend([0xff]); + let rb = RoaringBitmap::from_lsb0_bytes(0, &bytes); + assert_eq!(rb.min(), Some(CONTAINER_OFFSET)); + + let rb = RoaringBitmap::from_lsb0_bytes(8, &bytes); + assert_eq!(rb.min(), Some(CONTAINER_OFFSET + 8)); + + // Ensure we can set the last byte in an array container + let bytes = [0x80]; + let rb = RoaringBitmap::from_lsb0_bytes(0xFFFFFFF8, &bytes); + assert_eq!(rb.len(), 1); + assert!(rb.contains(u32::MAX)); + + // Ensure we can set the last byte in a bitmap container + let bytes = vec![0xFF; 0x1_0000 / 8]; + let rb = RoaringBitmap::from_lsb0_bytes(0xFFFF0000, &bytes); + assert_eq!(rb.len(), 0x1_0000); + assert!(rb.contains(u32::MAX)); + } + + #[test] + fn test_from_lsb0_bytes_not_multiple_of_8() { + const CONTAINER_OFFSET: u32 = u64::BITS * BITMAP_LENGTH as u32; + const CONTAINER_OFFSET_IN_BYTES: u32 = CONTAINER_OFFSET / 8; + + let mut bytes = vec![0b0101_1001]; + bytes.extend([0x00; CONTAINER_OFFSET_IN_BYTES as usize]); + bytes.extend([0b00000001, 0b00000010, 0b00000011, 0b00000100]); + + let mut indices = vec![0, 3, 4, 6]; + indices.extend([0, 9, 16, 17, 26].map(|i| 8 + CONTAINER_OFFSET + i)); + + for offset in 0..8 { + let rb = RoaringBitmap::from_lsb0_bytes(offset, &bytes); + for i in indices.iter().map(|&i| i + offset) { + assert!(rb.contains(i), "{i} should be in the bitmap"); + } + } + } + + #[test] + #[should_panic(expected = "<= 2^32")] + fn test_from_lsb0_bytes_overflow() { + let bytes = [0x01, 0x01]; + RoaringBitmap::from_lsb0_bytes(u32::MAX - 7, &bytes); + } + + #[test] + fn test_deserialize_overflow_s_plus_len() { + let data = vec![59, 48, 0, 0, 255, 130, 254, 59, 48, 2, 0, 41, 255, 255, 166, 197, 4, 0, 2]; + let res = RoaringBitmap::deserialize_from(data.as_slice()); + assert!(res.is_err()); + } +} diff --git a/vendor/roaring/src/bitmap/statistics.rs b/vendor/roaring/src/bitmap/statistics.rs new file mode 100644 index 0000000..2869c42 --- /dev/null +++ b/vendor/roaring/src/bitmap/statistics.rs @@ -0,0 +1,116 @@ +use core::mem; + +use crate::bitmap::container::Container; +use crate::RoaringBitmap; + +use super::store::Store; + +/// Detailed statistics on the composition of a bitmap. +#[derive(Clone, Copy, PartialEq, Debug)] +#[non_exhaustive] +pub struct Statistics { + /// Number of containers in the bitmap + pub n_containers: u32, + /// Number of array containers in the bitmap + pub n_array_containers: u32, + /// Number of run containers in the bitmap + pub n_run_containers: u32, + /// Number of bitset containers in the bitmap + pub n_bitset_containers: u32, + /// Number of values stored in array containers + pub n_values_array_containers: u32, + /// Number of values stored in run containers + pub n_values_run_containers: u32, + /// Number of values stored in bitset containers + pub n_values_bitset_containers: u64, + /// Number of bytes used by array containers + pub n_bytes_array_containers: u64, + /// Number of bytes used by run containers + pub n_bytes_run_containers: u64, + /// Number of bytes used by bitset containers + pub n_bytes_bitset_containers: u64, + /// Maximum value stored in the bitmap + pub max_value: Option, + /// Minimum value stored in the bitmap + pub min_value: Option, + /// Number of values stored in the bitmap + pub cardinality: u64, +} + +impl RoaringBitmap { + /// Returns statistics about the composition of a roaring bitmap. + /// + /// ``` + /// use roaring::RoaringBitmap; + /// + /// let mut bitmap: RoaringBitmap = (1..100).collect(); + /// let statistics = bitmap.statistics(); + /// + /// assert_eq!(statistics.n_containers, 1); + /// assert_eq!(statistics.n_array_containers, 1); + /// assert_eq!(statistics.n_run_containers, 0); + /// assert_eq!(statistics.n_bitset_containers, 0); + /// assert_eq!(statistics.n_values_array_containers, 99); + /// assert_eq!(statistics.n_values_run_containers, 0); + /// assert_eq!(statistics.n_values_bitset_containers, 0); + /// assert_eq!(statistics.n_bytes_array_containers, 512); + /// assert_eq!(statistics.n_bytes_run_containers, 0); + /// assert_eq!(statistics.n_bytes_bitset_containers, 0); + /// assert_eq!(statistics.max_value, Some(99)); + /// assert_eq!(statistics.min_value, Some(1)); + /// assert_eq!(statistics.cardinality, 99); + /// ``` + pub fn statistics(&self) -> Statistics { + let mut n_containers = 0; + let mut n_array_containers = 0; + let mut n_bitset_containers = 0; + let mut n_run_containers = 0; + let mut n_values_array_containers = 0; + let mut n_values_bitset_containers = 0; + let mut n_values_run_containers = 0; + let mut n_bytes_array_containers = 0; + let mut n_bytes_bitset_containers = 0; + let mut n_bytes_run_containers = 0; + let mut cardinality = 0; + + for Container { key: _, store } in &self.containers { + match store { + Store::Array(array) => { + cardinality += array.len(); + n_values_array_containers += array.len() as u32; + n_bytes_array_containers += (array.capacity() * mem::size_of::()) as u64; + n_array_containers += 1; + } + Store::Bitmap(bitmap) => { + cardinality += bitmap.len(); + n_values_bitset_containers += bitmap.len(); + n_bytes_bitset_containers += bitmap.capacity() as u64; + n_bitset_containers += 1; + } + Store::Run(runs) => { + cardinality += runs.len(); + n_values_run_containers += runs.len() as u32; + n_bytes_run_containers += runs.byte_size() as u64; + n_run_containers += 1; + } + } + n_containers += 1; + } + + Statistics { + n_containers, + n_array_containers, + n_run_containers, + n_bitset_containers, + n_values_array_containers, + n_values_run_containers, + n_values_bitset_containers, + n_bytes_array_containers, + n_bytes_run_containers, + n_bytes_bitset_containers, + max_value: self.max(), + min_value: self.min(), + cardinality, + } + } +} diff --git a/vendor/roaring/src/bitmap/store/array_store/mod.rs b/vendor/roaring/src/bitmap/store/array_store/mod.rs new file mode 100644 index 0000000..6196770 --- /dev/null +++ b/vendor/roaring/src/bitmap/store/array_store/mod.rs @@ -0,0 +1,705 @@ +mod scalar; +mod vector; +mod visitor; + +use crate::bitmap::store::array_store::visitor::{CardinalityCounter, VecWriter}; +use core::cmp::Ordering; +use core::cmp::Ordering::*; +use core::fmt::{Display, Formatter}; +use core::mem::size_of; +use core::ops::{BitAnd, BitAndAssign, BitOr, BitXor, RangeInclusive, Sub, SubAssign}; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; + +use super::bitmap_store::{bit, key, BitmapStore, BITMAP_LENGTH}; +use super::Interval; + +pub(crate) const ARRAY_ELEMENT_BYTES: usize = 2; + +#[derive(Clone, Eq, PartialEq)] +pub(crate) struct ArrayStore { + vec: Vec, +} + +/// Return the first contiguous range of elements in a sorted slice. +pub(crate) fn first_contiguous_range_len(slice: &[u16]) -> usize { + let [first, rest @ ..] = slice else { + // Explicitly empty range + return 0; + }; + let len = rest.partition_point(|item| { + let item_ptr = core::ptr::addr_of!(*item); + // SAFETY: `item` is guaranteed to be in bounds of `slice`. + let elem_distance = usize::try_from(unsafe { item_ptr.offset_from(first) }).unwrap(); + let value_distance = item.checked_sub(*first).expect("array must be sorted"); + elem_distance == usize::from(value_distance) + }); + len + 1 // +1 for the first element +} + +/// Return the last contiguous range of elements in a sorted slice. +pub(crate) fn last_contiguous_range_len(slice: &[u16]) -> usize { + let [rest @ .., last] = slice else { + // Explicitly empty range + return 0; + }; + let last_ptr = core::ptr::addr_of!(*last); + let len_from_start = rest.partition_point(|item| { + // SAFETY: `item` is guaranteed to be in bounds of `slice`. + let elem_distance = usize::try_from(unsafe { last_ptr.offset_from(item) }).unwrap(); + let value_distance = last.checked_sub(*item).expect("array must be sorted"); + elem_distance != usize::from(value_distance) + }); + slice.len() - len_from_start +} + +impl ArrayStore { + pub fn new() -> ArrayStore { + ArrayStore { vec: vec![] } + } + + pub fn serialized_byte_size(cardinality: u64) -> usize { + cardinality as usize * ARRAY_ELEMENT_BYTES + } + + pub fn byte_size(&self) -> usize { + Self::serialized_byte_size(self.len()) + } + + #[cfg(feature = "std")] + pub fn with_capacity(capacity: usize) -> ArrayStore { + ArrayStore { vec: Vec::with_capacity(capacity) } + } + + /// The number of total values that can be inserted without needing to reallocate. + pub fn capacity(&self) -> usize { + self.vec.capacity() + } + + /// + /// Create a new SortedU16Vec from a given vec + /// It is up to the caller to ensure the vec is sorted and deduplicated + /// Favor `try_from` / `try_into` for cases in which these invariants should be checked + /// + /// # Panics + /// + /// When debug_assertions are enabled and the above invariants are not met + #[inline] + pub fn from_vec_unchecked(vec: Vec) -> ArrayStore { + if cfg!(debug_assertions) { + vec.try_into().unwrap() + } else { + ArrayStore { vec } + } + } + + pub fn from_lsb0_bytes(bytes: &[u8], byte_offset: usize, bits_set: u64) -> Self { + type Word = u64; + + let mut vec = Vec::with_capacity(bits_set as usize); + + let chunks = bytes.chunks_exact(size_of::()); + let remainder = chunks.remainder(); + for (index, chunk) in chunks.enumerate() { + let bit_index = (byte_offset + index * size_of::()) * 8; + let mut word = Word::from_le_bytes(chunk.try_into().unwrap()); + + while word != 0 { + vec.push((word.trailing_zeros() + bit_index as u32) as u16); + word &= word - 1; + } + } + for (index, mut byte) in remainder.iter().copied().enumerate() { + let bit_index = (byte_offset + (bytes.len() - remainder.len()) + index) * 8; + while byte != 0 { + vec.push((byte.trailing_zeros() + bit_index as u32) as u16); + byte &= byte - 1; + } + } + + Self::from_vec_unchecked(vec) + } + + #[inline] + pub fn insert(&mut self, index: u16) -> bool { + self.vec.binary_search(&index).map_err(|loc| self.vec.insert(loc, index)).is_err() + } + + pub fn insert_range(&mut self, range: RangeInclusive) -> u64 { + let start = *range.start(); + let end = *range.end(); + + // Figure out the starting/ending position in the vec. + let pos_start = self.vec.binary_search(&start).unwrap_or_else(|x| x); + let pos_end = pos_start + + match self.vec[pos_start..].binary_search(&end) { + Ok(x) => x + 1, + Err(x) => x, + }; + + // Overwrite the range in the middle - there's no need to take + // into account any existing elements between start and end, as + // they're all being added to the set. + let dropped = self.vec.splice(pos_start..pos_end, start..=end); + + end as u64 - start as u64 + 1 - dropped.len() as u64 + } + + pub fn push(&mut self, index: u16) -> bool { + if self.max().is_none_or(|max| max < index) { + self.vec.push(index); + true + } else { + false + } + } + + /// + /// Pushes `index` at the end of the store. + /// It is up to the caller to have validated index > self.max() + /// + /// # Panics + /// + /// If debug_assertions enabled and index is > self.max() + pub(crate) fn push_unchecked(&mut self, index: u16) { + if cfg!(debug_assertions) { + if let Some(max) = self.max() { + assert!(index > max, "store max >= index") + } + } + self.vec.push(index); + } + + pub fn remove(&mut self, index: u16) -> bool { + self.vec.binary_search(&index).map(|loc| self.vec.remove(loc)).is_ok() + } + + pub fn remove_range(&mut self, range: RangeInclusive) -> u64 { + let start = *range.start(); + let end = *range.end(); + + // Figure out the starting/ending position in the vec. + let pos_start = self.vec.binary_search(&start).unwrap_or_else(|x| x); + let pos_end = pos_start + + match self.vec[pos_start..].binary_search(&end) { + Ok(x) => x + 1, + Err(x) => x, + }; + self.vec.drain(pos_start..pos_end); + (pos_end - pos_start) as u64 + } + + pub fn remove_smallest(&mut self, n: u64) { + self.vec.rotate_left(n as usize); + self.vec.truncate(self.vec.len() - n as usize); + } + + pub fn remove_biggest(&mut self, n: u64) { + self.vec.truncate(self.vec.len() - n as usize); + } + + pub fn contains(&self, index: u16) -> bool { + self.vec.binary_search(&index).is_ok() + } + + pub fn contains_range(&self, range: RangeInclusive) -> bool { + let start = *range.start(); + let end = *range.end(); + let range_count = usize::from(end - start) + 1; + if self.vec.len() < range_count { + return false; + } + let start_i = match self.vec.binary_search(&start) { + Ok(i) => i, + Err(_) => return false, + }; + + // If there are `range_count` items, last item in the next range_count should be the + // expected end value, because this vec is sorted and has no duplicates + self.vec.get(start_i + range_count - 1) == Some(&end) + } + + pub fn is_disjoint(&self, other: &Self) -> bool { + let (mut i1, mut i2) = (self.vec.iter(), other.vec.iter()); + let (mut value1, mut value2) = (i1.next(), i2.next()); + loop { + match value1.and_then(|v1| value2.map(|v2| v1.cmp(v2))) { + None => return true, + Some(Equal) => return false, + Some(Less) => value1 = i1.next(), + Some(Greater) => value2 = i2.next(), + } + } + } + + pub fn is_subset(&self, other: &Self) -> bool { + let (mut i1, mut i2) = (self.iter(), other.iter()); + let (mut value1, mut value2) = (i1.next(), i2.next()); + loop { + match (value1, value2) { + (None, _) => return true, + (Some(..), None) => return false, + (Some(v1), Some(v2)) => match v1.cmp(v2) { + Equal => { + value1 = i1.next(); + value2 = i2.next(); + } + Less => return false, + Greater => value2 = i2.next(), + }, + } + } + } + + pub fn intersection_len(&self, other: &Self) -> u64 { + let mut visitor = CardinalityCounter::new(); + #[cfg(feature = "simd")] + vector::and(self.as_slice(), other.as_slice(), &mut visitor); + #[cfg(not(feature = "simd"))] + scalar::and(self.as_slice(), other.as_slice(), &mut visitor); + visitor.into_inner() + } + + pub fn intersection_len_interval(&self, interval: &Interval) -> u64 { + if interval.is_full() { + return self.len(); + } + let start_id = self.vec.partition_point(|&f| f < interval.start()); + let end_id = self.vec.partition_point(|&f| f <= interval.end()); + (end_id.saturating_sub(start_id)) as u64 + } + + pub fn to_bitmap_store(&self) -> BitmapStore { + let mut bits = Box::new([0; BITMAP_LENGTH]); + let len = self.len(); + + for &index in self.iter() { + bits[key(index)] |= 1 << bit(index); + } + BitmapStore::from_unchecked(len, bits) + } + + pub fn len(&self) -> u64 { + self.vec.len() as u64 + } + + pub fn is_empty(&self) -> bool { + self.vec.is_empty() + } + + pub fn min(&self) -> Option { + self.vec.first().copied() + } + + #[inline] + pub fn max(&self) -> Option { + self.vec.last().copied() + } + + pub fn rank(&self, index: u16) -> u64 { + match self.vec.binary_search(&index) { + Ok(i) => i as u64 + 1, + Err(i) => i as u64, + } + } + + pub fn select(&self, n: u16) -> Option { + self.vec.get(n as usize).cloned() + } + + pub fn iter(&'_ self) -> core::slice::Iter<'_, u16> { + self.vec.iter() + } + + pub fn into_iter(self) -> alloc::vec::IntoIter { + self.vec.into_iter() + } + + pub fn as_slice(&self) -> &[u16] { + &self.vec + } + + /// Retains only the elements specified by the predicate. + pub fn retain(&mut self, mut f: impl FnMut(u16) -> bool) { + // Idea to avoid branching from "Engineering Fast Indexes for Big Data + // Applications" talk by Daniel Lemire + // (https://youtu.be/1QMgGxiCFWE?t=1242). + let slice = self.vec.as_mut_slice(); + let mut pos = 0; + for i in 0..slice.len() { + let val = slice[i]; + // We want to do `slice[pos] = val` but we don't need the bounds check. + // SAFETY: pos is always at most i because `f(val) as usize` is at most 1. + unsafe { *slice.get_unchecked_mut(pos) = val } + pos += f(val) as usize; + } + self.vec.truncate(pos); + } + + pub(crate) fn internal_validate(&self) -> Result<(), &'static str> { + if self.vec.is_empty() { + return Err("zero cardinality in array container"); + } + if self.vec.len() > super::ARRAY_LIMIT as usize { + return Err("array cardinality exceeds ARRAY_LIMIT"); + } + for window in self.vec.windows(2) { + let &[first, second] = window else { unreachable!() }; + if first >= second { + return Err("array elements not strictly increasing"); + } + } + + Ok(()) + } +} + +impl Default for ArrayStore { + fn default() -> Self { + ArrayStore::new() + } +} + +#[derive(Debug)] +pub struct Error { + index: usize, + kind: ErrorKind, +} + +#[derive(Debug)] +pub enum ErrorKind { + Duplicate, + OutOfOrder, +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self.kind { + ErrorKind::Duplicate => { + write!(f, "Duplicate element found at index: {}", self.index) + } + ErrorKind::OutOfOrder => { + write!(f, "An element was out of order at index: {}", self.index) + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +impl TryFrom> for ArrayStore { + type Error = Error; + + fn try_from(value: Vec) -> Result { + let mut iter = value.iter().enumerate(); + if let Some((_, mut prev)) = iter.next() { + for (i, cur) in iter { + match cur.cmp(prev) { + Ordering::Less => return Err(Error { index: i, kind: ErrorKind::OutOfOrder }), + Ordering::Equal => return Err(Error { index: i, kind: ErrorKind::Duplicate }), + Ordering::Greater => (), + } + prev = cur; + } + } + + Ok(ArrayStore { vec: value }) + } +} + +impl BitOr for &ArrayStore { + type Output = ArrayStore; + + fn bitor(self, rhs: Self) -> Self::Output { + #[allow(clippy::suspicious_arithmetic_impl)] + let capacity = self.vec.len() + rhs.vec.len(); + let mut visitor = VecWriter::new(capacity); + #[cfg(feature = "simd")] + vector::or(self.as_slice(), rhs.as_slice(), &mut visitor); + #[cfg(not(feature = "simd"))] + scalar::or(self.as_slice(), rhs.as_slice(), &mut visitor); + ArrayStore::from_vec_unchecked(visitor.into_inner()) + } +} + +impl BitAnd for &ArrayStore { + type Output = ArrayStore; + + fn bitand(self, rhs: Self) -> Self::Output { + let mut visitor = VecWriter::new(self.vec.len().min(rhs.vec.len())); + #[cfg(feature = "simd")] + vector::and(self.as_slice(), rhs.as_slice(), &mut visitor); + #[cfg(not(feature = "simd"))] + scalar::and(self.as_slice(), rhs.as_slice(), &mut visitor); + ArrayStore::from_vec_unchecked(visitor.into_inner()) + } +} + +impl BitAndAssign<&Self> for ArrayStore { + #[allow(clippy::suspicious_op_assign_impl)] + fn bitand_assign(&mut self, rhs: &Self) { + #[cfg(feature = "simd")] + { + let mut visitor = VecWriter::new(self.vec.len().min(rhs.vec.len())); + vector::and(self.as_slice(), rhs.as_slice(), &mut visitor); + self.vec = visitor.into_inner() + } + #[cfg(not(feature = "simd"))] + { + let mut i = 0; + self.retain(|x| { + i += rhs.iter().skip(i).position(|y| *y >= x).unwrap_or(rhs.vec.len()); + rhs.vec.get(i).is_some_and(|y| x == *y) + }); + } + } +} + +impl BitAndAssign<&BitmapStore> for ArrayStore { + fn bitand_assign(&mut self, rhs: &BitmapStore) { + self.retain(|x| rhs.contains(x)); + } +} + +impl Sub for &ArrayStore { + type Output = ArrayStore; + + fn sub(self, rhs: Self) -> Self::Output { + let mut visitor = VecWriter::new(self.vec.len()); + #[cfg(feature = "simd")] + vector::sub(self.as_slice(), rhs.as_slice(), &mut visitor); + #[cfg(not(feature = "simd"))] + scalar::sub(self.as_slice(), rhs.as_slice(), &mut visitor); + ArrayStore::from_vec_unchecked(visitor.into_inner()) + } +} + +impl SubAssign<&Self> for ArrayStore { + #[allow(clippy::suspicious_op_assign_impl)] + fn sub_assign(&mut self, rhs: &Self) { + #[cfg(feature = "simd")] + { + let mut visitor = VecWriter::new(self.vec.len().min(rhs.vec.len())); + vector::sub(self.as_slice(), rhs.as_slice(), &mut visitor); + self.vec = visitor.into_inner() + } + #[cfg(not(feature = "simd"))] + { + let mut i = 0; + self.retain(|x| { + i += rhs.iter().skip(i).position(|y| *y >= x).unwrap_or(rhs.vec.len()); + rhs.vec.get(i).is_none_or(|y| x != *y) + }); + } + } +} + +impl SubAssign<&BitmapStore> for ArrayStore { + fn sub_assign(&mut self, rhs: &BitmapStore) { + self.retain(|x| !rhs.contains(x)); + } +} + +impl BitXor for &ArrayStore { + type Output = ArrayStore; + + fn bitxor(self, rhs: Self) -> Self::Output { + #[allow(clippy::suspicious_arithmetic_impl)] + let capacity = self.vec.len() + rhs.vec.len(); + let mut visitor = VecWriter::new(capacity); + #[cfg(feature = "simd")] + vector::xor(self.as_slice(), rhs.as_slice(), &mut visitor); + #[cfg(not(feature = "simd"))] + scalar::xor(self.as_slice(), rhs.as_slice(), &mut visitor); + ArrayStore::from_vec_unchecked(visitor.into_inner()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::bitmap::store::Store; + + fn into_vec(s: Store) -> Vec { + match s { + Store::Array(vec) => vec.vec, + Store::Bitmap(bits) => bits.to_array_store().vec, + Store::Run(runs) => runs.iter().collect(), + } + } + + fn into_bitmap_store(s: Store) -> Store { + match s { + Store::Array(vec) => Store::Bitmap(vec.to_bitmap_store()), + Store::Bitmap(..) => s, + Store::Run(runs) => Store::Bitmap(runs.to_bitmap()), + } + } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn test_array_insert_invalid_range() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 8, 9])); + + // Insert a range with start > end. + let new = store.insert_range(6..=1); + assert_eq!(new, 0); + + assert_eq!(into_vec(store), vec![1, 2, 8, 9]); + } + + #[test] + fn test_array_insert_range() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 8, 9])); + + let new = store.insert_range(4..=5); + assert_eq!(new, 2); + + assert_eq!(into_vec(store), vec![1, 2, 4, 5, 8, 9]); + } + + #[test] + fn test_array_insert_range_left_overlap() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 8, 9])); + + let new = store.insert_range(2..=5); + assert_eq!(new, 3); + + assert_eq!(into_vec(store), vec![1, 2, 3, 4, 5, 8, 9]); + } + + #[test] + fn test_array_insert_range_right_overlap() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 8, 9])); + + let new = store.insert_range(4..=8); + assert_eq!(new, 4); + + assert_eq!(into_vec(store), vec![1, 2, 4, 5, 6, 7, 8, 9]); + } + + #[test] + fn test_array_contains_range() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![])); + assert!(!store.contains_range(0..=0)); + assert!(!store.contains_range(0..=1)); + assert!(!store.contains_range(1..=u16::MAX)); + + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![0, 1, 2, 3, 4, 5, 100])); + assert!(store.contains_range(0..=0)); + assert!(store.contains_range(0..=5)); + assert!(!store.contains_range(0..=6)); + assert!(store.contains_range(100..=100)); + } + + #[test] + fn test_array_insert_range_full_overlap() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 8, 9])); + + let new = store.insert_range(1..=9); + assert_eq!(new, 5); + + assert_eq!(into_vec(store), vec![1, 2, 3, 4, 5, 6, 7, 8, 9]); + } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn test_bitmap_insert_invalid_range() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 8, 9])); + let mut store = into_bitmap_store(store); + + // Insert a range with start > end. + let new = store.insert_range(6..=1); + assert_eq!(new, 0); + + assert_eq!(into_vec(store), vec![1, 2, 8, 9]); + } + + #[test] + fn test_bitmap_insert_same_key_overlap() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 3, 62, 63])); + let mut store = into_bitmap_store(store); + + let new = store.insert_range(1..=62); + assert_eq!(new, 58); + + assert_eq!(into_vec(store), (1..64).collect::>()); + } + + #[test] + fn test_bitmap_insert_range() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 130])); + let mut store = into_bitmap_store(store); + + let new = store.insert_range(4..=128); + assert_eq!(new, 125); + + let mut want = vec![1, 2]; + want.extend(4..129); + want.extend([130]); + + assert_eq!(into_vec(store), want); + } + + #[test] + fn test_bitmap_insert_range_left_overlap() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 130])); + let mut store = into_bitmap_store(store); + + let new = store.insert_range(1..=128); + assert_eq!(new, 126); + + let mut want = Vec::new(); + want.extend(1..129); + want.extend([130]); + + assert_eq!(into_vec(store), want); + } + + #[test] + fn test_bitmap_insert_range_right_overlap() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 130])); + let mut store = into_bitmap_store(store); + + let new = store.insert_range(4..=132); + assert_eq!(new, 128); + + let mut want = vec![1, 2]; + want.extend(4..133); + + assert_eq!(into_vec(store), want); + } + + #[test] + fn test_bitmap_insert_range_full_overlap() { + let store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 130])); + let mut store = into_bitmap_store(store); + + let new = store.insert_range(1..=134); + assert_eq!(new, 131); + + let mut want = Vec::new(); + want.extend(1..135); + + assert_eq!(into_vec(store), want); + } + + #[test] + fn test_bitmap_remove_smallest() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 130, 500])); + store.remove_smallest(3); + assert_eq!(into_vec(store), vec![500]); + } + + #[test] + fn test_bitmap_remove_biggest() { + let mut store = Store::Array(ArrayStore::from_vec_unchecked(vec![1, 2, 130, 500])); + store.remove_biggest(2); + assert_eq!(into_vec(store), vec![1, 2]); + } +} diff --git a/vendor/roaring/src/bitmap/store/array_store/scalar.rs b/vendor/roaring/src/bitmap/store/array_store/scalar.rs new file mode 100644 index 0000000..d7b699c --- /dev/null +++ b/vendor/roaring/src/bitmap/store/array_store/scalar.rs @@ -0,0 +1,108 @@ +//! Scalar arithmetic binary set operations on `ArrayStore`'s inner types + +use crate::bitmap::store::array_store::visitor::BinaryOperationVisitor; +use core::cmp::Ordering::*; + +#[inline] +pub fn or(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + // Traverse both arrays + let mut i = 0; + let mut j = 0; + while i < lhs.len() && j < rhs.len() { + let a = unsafe { lhs.get_unchecked(i) }; + let b = unsafe { rhs.get_unchecked(j) }; + match a.cmp(b) { + Less => { + visitor.visit_scalar(*a); + i += 1; + } + Greater => { + visitor.visit_scalar(*b); + j += 1; + } + Equal => { + visitor.visit_scalar(*a); + i += 1; + j += 1; + } + } + } + + // Store remaining elements of the arrays + visitor.visit_slice(&lhs[i..]); + visitor.visit_slice(&rhs[j..]); +} + +#[inline] +pub fn and(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + // Traverse both arrays + let mut i = 0; + let mut j = 0; + while i < lhs.len() && j < rhs.len() { + let a = unsafe { lhs.get_unchecked(i) }; + let b = unsafe { rhs.get_unchecked(j) }; + match a.cmp(b) { + Less => i += 1, + Greater => j += 1, + Equal => { + visitor.visit_scalar(*a); + i += 1; + j += 1; + } + } + } +} + +#[inline] +pub fn sub(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + // Traverse both arrays + let mut i = 0; + let mut j = 0; + while i < lhs.len() && j < rhs.len() { + let a = unsafe { lhs.get_unchecked(i) }; + let b = unsafe { rhs.get_unchecked(j) }; + match a.cmp(b) { + Less => { + visitor.visit_scalar(*a); + i += 1; + } + Greater => j += 1, + Equal => { + i += 1; + j += 1; + } + } + } + + // Store remaining elements of the left array + visitor.visit_slice(&lhs[i..]); +} + +#[inline] +pub fn xor(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + // Traverse both arrays + let mut i = 0; + let mut j = 0; + while i < lhs.len() && j < rhs.len() { + let a = unsafe { lhs.get_unchecked(i) }; + let b = unsafe { rhs.get_unchecked(j) }; + match a.cmp(b) { + Less => { + visitor.visit_scalar(*a); + i += 1; + } + Greater => { + visitor.visit_scalar(*b); + j += 1; + } + Equal => { + i += 1; + j += 1; + } + } + } + + // Store remaining elements of the arrays + visitor.visit_slice(&lhs[i..]); + visitor.visit_slice(&rhs[j..]); +} diff --git a/vendor/roaring/src/bitmap/store/array_store/vector.rs b/vendor/roaring/src/bitmap/store/array_store/vector.rs new file mode 100644 index 0000000..94f7ab3 --- /dev/null +++ b/vendor/roaring/src/bitmap/store/array_store/vector.rs @@ -0,0 +1,562 @@ +//! Ported from CRoaring and arXiv:1709.07821 +//! Lemire et al, Roaring Bitmaps: Implementation of an Optimized Software Library +//! +//! Prior work: Schlegel et al., Fast Sorted-Set Intersection using SIMD Instructions +//! +//! Rust port notes: +//! The x86 PCMPESTRM instruction has been replaced with a simple vector or-shift +//! While several more instructions, this is what is available through LLVM intrinsics +//! and is portable. + +#![cfg(feature = "simd")] + +use super::scalar; +use core::simd::cmp::{SimdPartialEq, SimdPartialOrd}; +use core::simd::{ + mask16x8, u16x8, u8x16, LaneCount, Mask, Simd, SimdElement, SupportedLaneCount, ToBytes, +}; + +// a one-pass SSE union algorithm +pub fn or(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + // De-duplicates `slice` in place + // Returns the end index of the deduplicated slice. + // elements after the return value are not guaranteed to be unique or in order + #[inline] + fn dedup(slice: &mut [u16]) -> usize { + let mut pos: usize = 1; + for i in 1..slice.len() { + if slice[i] != slice[i - 1] { + slice[pos] = slice[i]; + pos += 1; + } + } + pos + } + + #[inline] + fn handle_vector(old: u16x8, new: u16x8, f: impl FnOnce(u16x8, u8)) { + let tmp: u16x8 = Shr1::concat_swizzle(new, old); + let mask = 255 - tmp.simd_eq(new).to_bitmask() as u8; + f(new, mask); + } + + if (lhs.len() < 8) || (rhs.len() < 8) { + scalar::or(lhs, rhs, visitor); + return; + } + + let len1: usize = lhs.len() / 8; + let len2: usize = rhs.len() / 8; + + let v_a: u16x8 = load(lhs); + let v_b: u16x8 = load(rhs); + let [mut v_min, mut v_max] = simd_merge_u16(v_a, v_b); + + let mut i = 1; + let mut j = 1; + handle_vector(Simd::splat(u16::MAX), v_min, |v, m| visitor.visit_vector(v, m)); + let mut v_prev: u16x8 = v_min; + if (i < len1) && (j < len2) { + let mut v: u16x8; + let mut cur_a: u16 = lhs[8 * i]; + let mut cur_b: u16 = rhs[8 * j]; + loop { + if cur_a <= cur_b { + v = load(&lhs[8 * i..]); + i += 1; + if i < len1 { + cur_a = lhs[8 * i]; + } else { + break; + } + } else { + v = load(&rhs[8 * j..]); + j += 1; + if j < len2 { + cur_b = rhs[8 * j]; + } else { + break; + } + } + [v_min, v_max] = simd_merge_u16(v, v_max); + handle_vector(v_prev, v_min, |v, m| visitor.visit_vector(v, m)); + v_prev = v_min; + } + [v_min, v_max] = simd_merge_u16(v, v_max); + handle_vector(v_prev, v_min, |v, m| visitor.visit_vector(v, m)); + v_prev = v_min; + } + + debug_assert!(i == len1 || j == len2); + + // we finish the rest off using a scalar algorithm + // could be improved? + // + // copy the small end on a tmp buffer + let mut buffer: [u16; 16] = [0; 16]; + let mut rem = 0; + handle_vector(v_prev, v_max, |v, m| { + store(swizzle_to_front(v, m), buffer.as_mut_slice()); + rem = m.count_ones() as usize; + }); + + let (tail_a, tail_b, tail_len) = if i == len1 { + (&lhs[8 * i..], &rhs[8 * j..], lhs.len() - 8 * len1) + } else { + (&rhs[8 * j..], &lhs[8 * i..], rhs.len() - 8 * len2) + }; + + buffer[rem..rem + tail_len].copy_from_slice(tail_a); + rem += tail_len; + + if rem == 0 { + visitor.visit_slice(tail_b) + } else { + buffer[..rem].sort_unstable(); + rem = dedup(&mut buffer[..rem]); + scalar::or(&buffer[..rem], tail_b, visitor); + } +} + +pub fn and(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + let st_a = (lhs.len() / u16x8::LEN) * u16x8::LEN; + let st_b = (rhs.len() / u16x8::LEN) * u16x8::LEN; + + let mut i: usize = 0; + let mut j: usize = 0; + if (i < st_a) && (j < st_b) { + let mut v_a: u16x8 = load(&lhs[i..]); + let mut v_b: u16x8 = load(&rhs[j..]); + loop { + let mask = matrix_cmp_u16(v_a, v_b).to_bitmask() as u8; + visitor.visit_vector(v_a, mask); + + let a_max: u16 = lhs[i + u16x8::LEN - 1]; + let b_max: u16 = rhs[j + u16x8::LEN - 1]; + if a_max <= b_max { + i += u16x8::LEN; + if i == st_a { + break; + } + v_a = load(&lhs[i..]); + } + if b_max <= a_max { + j += u16x8::LEN; + if j == st_b { + break; + } + v_b = load(&rhs[j..]); + } + } + } + + // intersect the tail using scalar intersection + scalar::and(&lhs[i..], &rhs[j..], visitor); +} + +// a one-pass SSE xor algorithm +pub fn xor(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + /// De-duplicates `slice` in place, removing _both_ duplicates + /// Returns the end index of the xor-ed slice. + /// elements after the return value are not guaranteed to be unique or in order + #[inline] + fn xor_slice(slice: &mut [u16]) -> usize { + let mut pos: usize = 1; + for i in 1..slice.len() { + if slice[i] != slice[i - 1] { + slice[pos] = slice[i]; + pos += 1; + } else { + pos -= 1; // it is identical to previous, delete it + } + } + pos + } + + // write vector new, while omitting repeated values assuming that previously + // written vector was "old" + #[inline] + fn handle_vector(old: u16x8, new: u16x8, f: impl FnOnce(u16x8, u8)) { + let tmp1: u16x8 = Shr2::concat_swizzle(new, old); + let tmp2: u16x8 = Shr1::concat_swizzle(new, old); + let eq_l: mask16x8 = tmp2.simd_eq(tmp1); + let eq_r: mask16x8 = tmp2.simd_eq(new); + let eq_l_or_r: mask16x8 = eq_l | eq_r; + let mask: u8 = eq_l_or_r.to_bitmask() as u8; + f(tmp2, 255 - mask); + } + + if (lhs.len() < 8) || (rhs.len() < 8) { + scalar::xor(lhs, rhs, visitor); + return; + } + + let len1: usize = lhs.len() / 8; + let len2: usize = rhs.len() / 8; + + let v_a: u16x8 = load(lhs); + let v_b: u16x8 = load(rhs); + let [mut v_min, mut v_max] = simd_merge_u16(v_a, v_b); + + let mut i = 1; + let mut j = 1; + handle_vector(Simd::splat(u16::MAX), v_min, |v, m| visitor.visit_vector(v, m)); + let mut v_prev: u16x8 = v_min; + if (i < len1) && (j < len2) { + let mut v: u16x8; + let mut cur_a: u16 = lhs[8 * i]; + let mut cur_b: u16 = rhs[8 * j]; + loop { + if cur_a <= cur_b { + v = load(&lhs[8 * i..]); + i += 1; + if i < len1 { + cur_a = lhs[8 * i]; + } else { + break; + } + } else { + v = load(&rhs[8 * j..]); + j += 1; + if j < len2 { + cur_b = rhs[8 * j]; + } else { + break; + } + } + [v_min, v_max] = simd_merge_u16(v, v_max); + handle_vector(v_prev, v_min, |v, m| visitor.visit_vector(v, m)); + v_prev = v_min; + } + [v_min, v_max] = simd_merge_u16(v, v_max); + handle_vector(v_prev, v_min, |v, m| visitor.visit_vector(v, m)); + v_prev = v_min; + } + + debug_assert!(i == len1 || j == len2); + + // we finish the rest off using a scalar algorithm + // could be improved? + // conditionally stores the last value of laststore as well as all but the + // last value of vecMax, + let mut buffer: [u16; 17] = [0; 17]; + // remaining size + let mut rem = 0; + handle_vector(v_prev, v_max, |v, m| { + store(swizzle_to_front(v, m), buffer.as_mut_slice()); + rem = m.count_ones() as usize; + }); + + let arr_max = v_max.as_array(); + let vec7 = arr_max[7]; + let vec6 = arr_max[6]; + if vec6 != vec7 { + buffer[rem] = vec7; + rem += 1; + } + + let (tail_a, tail_b, tail_len) = if i == len1 { + (&lhs[8 * i..], &rhs[8 * j..], lhs.len() - 8 * len1) + } else { + (&rhs[8 * j..], &lhs[8 * i..], rhs.len() - 8 * len2) + }; + + buffer[rem..rem + tail_len].copy_from_slice(tail_a); + rem += tail_len; + + if rem == 0 { + visitor.visit_slice(tail_b) + } else { + buffer[..rem].sort_unstable(); + rem = xor_slice(&mut buffer[..rem]); + scalar::xor(&buffer[..rem], tail_b, visitor); + } +} + +pub fn sub(lhs: &[u16], rhs: &[u16], visitor: &mut impl BinaryOperationVisitor) { + // we handle the degenerate cases + if lhs.is_empty() { + return; + } else if rhs.is_empty() { + visitor.visit_slice(lhs); + return; + } + + let st_a = (lhs.len() / u16x8::LEN) * u16x8::LEN; + let st_b = (rhs.len() / u16x8::LEN) * u16x8::LEN; + + let mut i = 0; + let mut j = 0; + if (i < st_a) && (j < st_b) { + let mut v_a: u16x8 = load(&lhs[i..]); + let mut v_b: u16x8 = load(&rhs[j..]); + // we have a running mask which indicates which values from a have been + // spotted in b, these don't get written out. + let mut runningmask_a_found_in_b: u8 = 0; + loop { + // a_found_in_b will contain a mask indicate for each entry in A + // whether it is seen in B + let a_found_in_b: u8 = matrix_cmp_u16(v_a, v_b).to_bitmask() as u8; + runningmask_a_found_in_b |= a_found_in_b; + // we always compare the last values of A and B + let a_max: u16 = lhs[i + u16x8::LEN - 1]; + let b_max: u16 = rhs[j + u16x8::LEN - 1]; + if a_max <= b_max { + // Ok. In this code path, we are ready to write our v_a + // because there is no need to read more from B, they will + // all be large values. + let bitmask_belongs_to_difference = runningmask_a_found_in_b ^ 0xFF; + visitor.visit_vector(v_a, bitmask_belongs_to_difference); + i += u16x8::LEN; + if i == st_a { + break; + } + runningmask_a_found_in_b = 0; + v_a = load(&lhs[i..]); + } + if b_max <= a_max { + // in this code path, the current v_b has become useless + j += u16x8::LEN; + if j == st_b { + break; + } + v_b = load(&rhs[j..]); + } + } + + debug_assert!(i == st_a || j == st_b); + + // End of main vectorized loop + // At this point either i_a == st_a, which is the end of the vectorized processing, + // or i_b == st_b and we are not done processing the vector... + // so we need to finish it off. + if i < st_a { + let remaining_rhs = &rhs[j..]; + if !remaining_rhs.is_empty() { + let mut buffer: [u16; 8] = [0; 8]; // buffer to do a masked load + buffer[..remaining_rhs.len()].copy_from_slice(remaining_rhs); + // Ensure the buffer is filled with a value we should remove: we do not want to + // end up trying to remove zero values which aren't actually in rhs + buffer[remaining_rhs.len()..].fill(remaining_rhs[0]); + v_b = Simd::from_array(buffer); + let a_found_in_b: u8 = matrix_cmp_u16(v_a, v_b).to_bitmask() as u8; + runningmask_a_found_in_b |= a_found_in_b; + let [.., max_va] = *v_a.as_array(); + let used_rhs = remaining_rhs.partition_point(|&b| b <= max_va); + j += used_rhs; + } + let bitmask_belongs_to_difference: u8 = runningmask_a_found_in_b ^ 0xFF; + visitor.visit_vector(v_a, bitmask_belongs_to_difference); + i += u16x8::LEN; + } + } + + // do the tail using scalar code + scalar::sub(&lhs[i..], &rhs[j..], visitor); +} + +/// compute the min for each lane in `a` and `b` +#[inline] +fn lanes_min_u16( + lhs: Simd, + rhs: Simd, +) -> Simd +where + LaneCount: SupportedLaneCount, +{ + lhs.simd_le(rhs).select(lhs, rhs) +} + +/// compute the max for each lane in `a` and `b` +#[inline] +fn lanes_max_u16( + lhs: Simd, + rhs: Simd, +) -> Simd +where + LaneCount: SupportedLaneCount, +{ + lhs.simd_gt(rhs).select(lhs, rhs) +} + +#[inline] +pub fn load(src: &[U]) -> Simd +where + U: SimdElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + debug_assert!(src.len() >= LANES); + unsafe { load_unchecked(src) } +} + +/// write `v` to slice `out` without checking bounds +/// +/// ### Safety +/// - The caller must ensure `LANES` does not exceed the allocation for `out` +#[inline] +pub unsafe fn load_unchecked(src: &[U]) -> Simd +where + U: SimdElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + unsafe { core::ptr::read_unaligned(src as *const _ as *const Simd) } +} + +/// write `v` to slice `out` +#[inline] +pub fn store(v: Simd, out: &mut [U]) +where + U: SimdElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + debug_assert!(out.len() >= LANES); + unsafe { + store_unchecked(v, out); + } +} + +/// write `v` to slice `out` without checking bounds +/// +/// ### Safety +/// - The caller must ensure `LANES` does not exceed the allocation for `out` +#[inline] +unsafe fn store_unchecked(v: Simd, out: &mut [U]) +where + U: SimdElement + PartialOrd, + LaneCount: SupportedLaneCount, +{ + unsafe { core::ptr::write_unaligned(out as *mut _ as *mut Simd, v) } +} + +/// Compare all lanes in `a` to all lanes in `b` +/// +/// Returns result mask will be set if any lane at `a[i]` is in any lane of `b` +/// +/// ### Example +/// ```ignore +/// let a = Simd::from_array([1, 2, 3, 4, 32, 33, 34, 35]); +/// let b = Simd::from_array([2, 4, 6, 8, 10, 12, 14, 16]); +/// let result = matrix_cmp_u16(a, b); +/// assert_eq!(result, Mask::from_array([false, true, false, true, false, false, false, false])); +/// ``` +#[inline] +// It would be nice to implement this for all supported lane counts +// However, we currently only support u16x8 so it's not really necessary +fn matrix_cmp_u16(a: Simd, b: Simd) -> Mask { + a.simd_eq(b) + | a.simd_eq(b.rotate_elements_left::<1>()) + | a.simd_eq(b.rotate_elements_left::<2>()) + | a.simd_eq(b.rotate_elements_left::<3>()) + | a.simd_eq(b.rotate_elements_left::<4>()) + | a.simd_eq(b.rotate_elements_left::<5>()) + | a.simd_eq(b.rotate_elements_left::<6>()) + | a.simd_eq(b.rotate_elements_left::<7>()) +} + +use crate::bitmap::store::array_store::visitor::BinaryOperationVisitor; +use core::simd::Swizzle; + +/// Append to vectors to an imaginary 16 lane vector, shift the lanes right by 1, then +/// truncate to the low order 8 lanes +pub struct Shr1; +impl Swizzle<8> for Shr1 { + const INDEX: [usize; 8] = [15, 0, 1, 2, 3, 4, 5, 6]; +} + +/// Append to vectors to an imaginary 16 lane vector, shift the lanes right by 2, then +/// truncate to the low order 8 lanes +pub struct Shr2; +impl Swizzle<8> for Shr2 { + const INDEX: [usize; 8] = [14, 15, 0, 1, 2, 3, 4, 5]; +} + +/// Assuming that a and b are sorted, returns an array of the sorted output. +/// Developed originally for merge sort using SIMD instructions. +/// Standard merge. See, e.g., Inoue and Taura, SIMD- and Cache-Friendly +/// Algorithm for Sorting an Array of Structures +#[inline] +fn simd_merge_u16(a: Simd, b: Simd) -> [Simd; 2] { + let mut tmp: Simd = lanes_min_u16(a, b); + let mut max: Simd = lanes_max_u16(a, b); + tmp = tmp.rotate_elements_left::<1>(); + let mut min: Simd = lanes_min_u16(tmp, max); + for _ in 0..6 { + max = lanes_max_u16(tmp, max); + tmp = min.rotate_elements_left::<1>(); + min = lanes_min_u16(tmp, max); + } + max = lanes_max_u16(tmp, max); + min = min.rotate_elements_left::<1>(); + [min, max] +} + +/// Move the values in `val` with the corresponding index in `bitmask` +/// set to the front of the return vector, preserving their order. +/// +/// The values in the return vector after index bitmask.count_ones() is unspecified. +// Dynamic swizzle is only available for `u8`s. +// +// So we need to convert the `u16x8` to `u8x16`, and then swizzle it two lanes at a time. +// +// e.g. if `bitmask` is `0b0101`, then swizzle the first two bytes (the first u16 lane) to the +// first two positions, and the 5th and 6th bytes (the third u16 lane) to the next two positions. +// +// Note however: +// https://github.com/rust-lang/rust/blob/34097a38afc9efdedf776d3f1c84a190ff334886/library/portable-simd/crates/core_simd/src/swizzle_dyn.rs#L12-L15 +// > Note that the current implementation is selected during build-time +// > of the standard library, so `cargo build -Zbuild-std` may be necessary +// > to unlock better performance, especially for larger vectors. +// > A planned compiler improvement will enable using `#[target_feature]` instead. +pub fn swizzle_to_front(val: u16x8, bitmask: u8) -> u16x8 { + static SWIZZLE_TABLE: [[u8; 16]; 256] = { + let mut table = [[0; 16]; 256]; + let mut n = 0usize; + while n < table.len() { + let mut x = n; + let mut i = 0; + while x > 0 { + let lsb = x.trailing_zeros() as u8; + x ^= 1 << lsb; + table[n][i] = lsb * 2; // first byte + table[n][i + 1] = lsb * 2 + 1; // second byte + i += 2; + } + n += 1; + } + table + }; + + // Our swizzle table retains the order of the bytes in the 16 bit lanes, we can + // stick with native byte order as long as we convert back with native endianness too. + let val_convert: u8x16 = val.to_ne_bytes(); + let swizzle_idxs = u8x16::from_array(SWIZZLE_TABLE[bitmask as usize]); + + // Because the default `x86_64` target does not enable ssse3 (and without -Zbuild-std` + // std will not be compiled with it), use a manual swizzle with intrinsics so we can get + // reasonable performance without requiring the caller to use `-Zbuild-std`. + #[cfg(all(target_arch = "x86_64", any(target_feature = "ssse3", feature = "std")))] + { + let has_ssse3 = { + #[cfg(target_feature = "ssse3")] + { + true + } + #[cfg(not(target_feature = "ssse3"))] + { + // From above, `feature = std` must be true here, so we can do runtime detection + std::arch::is_x86_feature_detected!("ssse3") + } + }; + if has_ssse3 { + use core::arch::x86_64::{__m128i, _mm_shuffle_epi8}; + let val_m128 = __m128i::from(val_convert); + let swizzle_m128 = __m128i::from(swizzle_idxs); + // SAFETY: We only are in this block if the target supports `ssse3` + let swizzled_m128 = unsafe { _mm_shuffle_epi8(val_m128, swizzle_m128) }; + return u16x8::from(swizzled_m128); + } + } + + let swizzled: u8x16 = val_convert.swizzle_dyn(swizzle_idxs); + u16x8::from_ne_bytes(swizzled) +} diff --git a/vendor/roaring/src/bitmap/store/array_store/visitor.rs b/vendor/roaring/src/bitmap/store/array_store/visitor.rs new file mode 100644 index 0000000..d7293d7 --- /dev/null +++ b/vendor/roaring/src/bitmap/store/array_store/visitor.rs @@ -0,0 +1,92 @@ +#[cfg(feature = "simd")] +use crate::bitmap::store::array_store::vector::swizzle_to_front; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +/// This visitor pattern allows multiple different algorithms to be written over the same data +/// For example: vectorized algorithms can pass a visitor off to a scalar algorithm to finish off +/// a tail that is not a multiple of the vector width. +/// +/// Perhaps more importantly: it separates the set algorithms from the operations performed on +/// their results. Future work can utilize the exiting algorithms to trivially implement +/// computing the cardinality of an operation without materializng a new bitmap. +pub trait BinaryOperationVisitor { + #[cfg(feature = "simd")] + fn visit_vector(&mut self, value: core::simd::u16x8, mask: u8); + fn visit_scalar(&mut self, value: u16); + fn visit_slice(&mut self, values: &[u16]); +} + +/// A simple visitor that stores the computation result to a Vec +/// accessible by calling `into_inner()` +pub struct VecWriter { + vec: Vec, +} + +impl VecWriter { + pub fn new(capacity: usize) -> VecWriter { + let vec = Vec::with_capacity(capacity); + VecWriter { vec } + } + + pub fn into_inner(self) -> Vec { + // Consider shrinking the vec here. + // Exactly len could be too aggressive. Len rounded up to next power of 2? + // Related, but not exact issue: https://github.com/RoaringBitmap/roaring-rs/issues/136 + self.vec + } +} + +impl BinaryOperationVisitor for VecWriter { + #[cfg(feature = "simd")] + fn visit_vector(&mut self, value: core::simd::u16x8, mask: u8) { + let result = swizzle_to_front(value, mask); + + // This idiom is better than subslicing result, as it compiles down to an unaligned vector + // store instr. + // A more straightforward, but unsafe way would be ptr::write_unaligned and Vec::set_len + // Writing a vector at once is why the vectorized algorithms do not operate in place + // first write the entire vector + self.vec.extend_from_slice(&result.as_array()[..]); + // next truncate the masked out values + self.vec.truncate(self.vec.len() - (result.len() - mask.count_ones() as usize)); + } + + fn visit_scalar(&mut self, value: u16) { + self.vec.push(value) + } + + fn visit_slice(&mut self, values: &[u16]) { + self.vec.extend_from_slice(values); + } +} + +pub struct CardinalityCounter { + count: usize, +} + +impl CardinalityCounter { + pub fn new() -> CardinalityCounter { + CardinalityCounter { count: 0 } + } + + pub fn into_inner(self) -> u64 { + self.count as u64 + } +} + +impl BinaryOperationVisitor for CardinalityCounter { + #[cfg(feature = "simd")] + fn visit_vector(&mut self, _value: core::simd::u16x8, mask: u8) { + self.count += mask.count_ones() as usize; + } + + fn visit_scalar(&mut self, _value: u16) { + self.count += 1; + } + + fn visit_slice(&mut self, values: &[u16]) { + self.count += values.len(); + } +} diff --git a/vendor/roaring/src/bitmap/store/bitmap_store.rs b/vendor/roaring/src/bitmap/store/bitmap_store.rs new file mode 100644 index 0000000..ca32e2b --- /dev/null +++ b/vendor/roaring/src/bitmap/store/bitmap_store.rs @@ -0,0 +1,931 @@ +use core::borrow::Borrow; +use core::cmp::Ordering; +use core::fmt::{Display, Formatter}; +use core::mem::size_of; +use core::ops::{BitAndAssign, BitOrAssign, BitXorAssign, RangeInclusive, SubAssign}; + +use super::{ArrayStore, Interval}; + +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; +use core::mem; + +pub const BITMAP_LENGTH: usize = 1024; +pub const BITMAP_BYTES: usize = BITMAP_LENGTH * 8; + +#[derive(Clone, Eq, PartialEq)] +pub struct BitmapStore { + len: u64, + bits: Box<[u64; BITMAP_LENGTH]>, +} + +impl BitmapStore { + pub fn new() -> BitmapStore { + BitmapStore { len: 0, bits: Box::new([0; BITMAP_LENGTH]) } + } + + pub fn capacity(&self) -> usize { + BITMAP_LENGTH * u64::BITS as usize + } + + pub fn try_from(len: u64, bits: Box<[u64; BITMAP_LENGTH]>) -> Result { + let actual_len = bits.iter().map(|v| v.count_ones() as u64).sum(); + if len != actual_len { + Err(Error { kind: ErrorKind::Cardinality { expected: len, actual: actual_len } }) + } else { + Ok(BitmapStore { len, bits }) + } + } + + pub fn from_lsb0_bytes_unchecked(bytes: &[u8], byte_offset: usize, bits_set: u64) -> Self { + const BITMAP_BYTES: usize = BITMAP_LENGTH * size_of::(); + assert!(byte_offset.checked_add(bytes.len()).is_some_and(|sum| sum <= BITMAP_BYTES)); + + // If we know we're writing the full bitmap, we can avoid the initial memset to 0 + let mut bits = if bytes.len() == BITMAP_BYTES { + debug_assert_eq!(byte_offset, 0); // Must be true from the above assert + + // Safety: We've checked that the length is correct, and we use an unaligned load in case + // the bytes are not 8 byte aligned. + // The optimizer can see through this, and avoid the double copy to copy directly into + // the allocated box from bytes with memcpy + let bytes_as_words = + unsafe { bytes.as_ptr().cast::<[u64; BITMAP_LENGTH]>().read_unaligned() }; + Box::new(bytes_as_words) + } else { + let mut bits = Box::new([0u64; BITMAP_LENGTH]); + // Safety: It's safe to reinterpret u64s as u8s because u8 has less alignment requirements, + // and has no padding/uninitialized data. + let dst = unsafe { + core::slice::from_raw_parts_mut(bits.as_mut_ptr().cast::(), BITMAP_BYTES) + }; + let dst = &mut dst[byte_offset..][..bytes.len()]; + dst.copy_from_slice(bytes); + bits + }; + + if !cfg!(target_endian = "little") { + // Convert all words we touched (even partially) to little-endian + let start_word = byte_offset / size_of::(); + let end_word = (byte_offset + bytes.len()).div_ceil(size_of::()); + + // The 0th byte is the least significant byte, so we've written the bytes in little-endian + for word in &mut bits[start_word..end_word] { + *word = u64::from_le(*word); + } + } + + Self::from_unchecked(bits_set, bits) + } + + /// + /// Create a new BitmapStore from a given len and bits array + /// It is up to the caller to ensure len == cardinality of bits + /// Favor `try_from` for cases in which this invariants should be checked + /// + /// # Panics + /// + /// When debug_assertions are enabled and the above invariant is not met + pub fn from_unchecked(len: u64, bits: Box<[u64; BITMAP_LENGTH]>) -> BitmapStore { + if cfg!(debug_assertions) { + BitmapStore::try_from(len, bits).unwrap() + } else { + BitmapStore { len, bits } + } + } + + #[inline] + pub fn insert(&mut self, index: u16) -> bool { + let (key, bit) = (key(index), bit(index)); + let old_w = self.bits[key]; + let new_w = old_w | (1 << bit); + let inserted = (old_w ^ new_w) >> bit; // 1 or 0 + self.bits[key] = new_w; + self.len += inserted; + inserted != 0 + } + + pub fn insert_range(&mut self, range: RangeInclusive) -> u64 { + let start = *range.start(); + let end = *range.end(); + + let (start_key, start_bit) = (key(start), bit(start)); + let (end_key, end_bit) = (key(end), bit(end)); + + // MSB > start_bit > end_bit > LSB + if start_key == end_key { + // Set the end_bit -> LSB to 1 + let mut mask = if end_bit == 63 { u64::MAX } else { (1 << (end_bit + 1)) - 1 }; + // Set MSB -> start_bit to 1 + mask &= !((1 << start_bit) - 1); + + let existed = (self.bits[start_key] & mask).count_ones(); + self.bits[start_key] |= mask; + + let inserted = u64::from(end - start + 1) - u64::from(existed); + self.len += inserted; + return inserted; + } + + // Mask off the left-most bits (MSB -> start_bit) + let mask = !((1 << start_bit) - 1); + + // Keep track of the number of bits that were already set to + // return how many new bits were set later + let mut existed = (self.bits[start_key] & mask).count_ones(); + + self.bits[start_key] |= mask; + + // Set the full blocks, tracking the number of set bits + for i in (start_key + 1)..end_key { + existed += self.bits[i].count_ones(); + self.bits[i] = u64::MAX; + } + + // Set the end bits in the last chunk (MSB -> end_bit) + let mask = if end_bit == 63 { u64::MAX } else { (1 << (end_bit + 1)) - 1 }; + existed += (self.bits[end_key] & mask).count_ones(); + self.bits[end_key] |= mask; + + let inserted = end as u64 - start as u64 + 1 - existed as u64; + self.len += inserted; + inserted + } + + pub fn push(&mut self, index: u16) -> bool { + if self.max().is_none_or(|max| max < index) { + self.insert(index); + true + } else { + false + } + } + + /// + /// Pushes `index` at the end of the store. + /// It is up to the caller to have validated index > self.max() + /// + /// # Panics + /// + /// If debug_assertions enabled and index is > self.max() + pub(crate) fn push_unchecked(&mut self, index: u16) { + if cfg!(debug_assertions) { + if let Some(max) = self.max() { + assert!(index > max, "store max >= index") + } + } + self.insert(index); + } + + pub fn remove(&mut self, index: u16) -> bool { + let (key, bit) = (key(index), bit(index)); + let old_w = self.bits[key]; + let new_w = old_w & !(1 << bit); + let removed = (old_w ^ new_w) >> bit; // 0 or 1 + self.bits[key] = new_w; + self.len -= removed; + removed != 0 + } + + pub fn remove_range(&mut self, range: RangeInclusive) -> u64 { + let start = *range.start(); + let end = *range.end(); + + let (start_key, start_bit) = (key(start), bit(start)); + let (end_key, end_bit) = (key(end), bit(end)); + + if start_key == end_key { + let mask = (u64::MAX << start_bit) & (u64::MAX >> (63 - end_bit)); + let removed = (self.bits[start_key] & mask).count_ones(); + self.bits[start_key] &= !mask; + let removed = u64::from(removed); + self.len -= removed; + return removed; + } + + let mut removed = 0; + // start key bits + removed += (self.bits[start_key] & (u64::MAX << start_bit)).count_ones(); + self.bits[start_key] &= !(u64::MAX << start_bit); + // counts bits in between + for word in &self.bits[start_key + 1..end_key] { + removed += word.count_ones(); + // When popcnt is available zeroing in this loop is faster, + // but we opt to perform reasonably on most cpus by zeroing after. + // By doing that the compiler uses simd to count ones. + } + // do zeroing outside the loop + for word in &mut self.bits[start_key + 1..end_key] { + *word = 0; + } + // end key bits + removed += (self.bits[end_key] & (u64::MAX >> (63 - end_bit))).count_ones(); + self.bits[end_key] &= !(u64::MAX >> (63 - end_bit)); + let removed = u64::from(removed); + self.len -= removed; + removed + } + + pub fn contains(&self, index: u16) -> bool { + self.bits[key(index)] & (1 << bit(index)) != 0 + } + + pub fn contains_range(&self, range: RangeInclusive) -> bool { + let start = *range.start(); + let end = *range.end(); + if self.len() < u64::from(end - start) + 1 { + return false; + } + + let (start_i, start_bit) = (key(start), bit(start)); + let (end_i, end_bit) = (key(end), bit(end)); + + // Create a mask to exclude the first `start_bit` bits + // e.g. if we start at bit index 1, this will create a mask which includes all but the bit + // at index 0. + let start_mask = !((1 << start_bit) - 1); + // We want to create a mask which includes the end_bit, so we create a mask of + // `end_bit + 1` bits. `end_bit` will be between [0, 63], so we create a mask including + // between [1, 64] bits. For example, if the last bit is the 0th bit, we make a mask with + // only the 0th bit set (one bit). + let end_mask = (!0) >> (64 - (end_bit + 1)); + + match &self.bits[start_i..=end_i] { + [] => unreachable!(), + &[word] => word & (start_mask & end_mask) == (start_mask & end_mask), + &[first, ref rest @ .., last] => { + (first & start_mask) == start_mask + && rest.iter().all(|&word| word == !0) + && (last & end_mask) == end_mask + } + } + } + + pub fn is_disjoint(&self, other: &BitmapStore) -> bool { + self.bits.iter().zip(other.bits.iter()).all(|(&i1, &i2)| (i1 & i2) == 0) + } + + pub fn is_subset(&self, other: &Self) -> bool { + self.bits.iter().zip(other.bits.iter()).all(|(&i1, &i2)| (i1 & i2) == i1) + } + + pub(crate) fn to_array_store(&self) -> ArrayStore { + let mut vec = Vec::with_capacity(self.len as usize); + for (index, mut bit) in self.bits.iter().cloned().enumerate() { + while bit != 0 { + vec.push((u64::trailing_zeros(bit) + (64 * index as u32)) as u16); + bit &= bit - 1; + } + } + ArrayStore::from_vec_unchecked(vec) + } + + pub fn len(&self) -> u64 { + self.len + } + + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + pub fn min(&self) -> Option { + self.bits + .iter() + .enumerate() + .find(|&(_, &bit)| bit != 0) + .map(|(index, bit)| (index * 64 + (bit.trailing_zeros() as usize)) as u16) + } + + #[inline] + pub fn max(&self) -> Option { + self.bits + .iter() + .enumerate() + .rev() + .find(|&(_, &bit)| bit != 0) + .map(|(index, bit)| (index * 64 + (63 - bit.leading_zeros() as usize)) as u16) + } + + pub fn rank(&self, index: u16) -> u64 { + let (key, bit) = (key(index), bit(index)); + + self.bits[..key].iter().map(|v| v.count_ones() as u64).sum::() + + (self.bits[key] << (63 - bit)).count_ones() as u64 + } + + pub fn select(&self, n: u16) -> Option { + let mut n = n as u64; + + for (key, value) in self.bits.iter().cloned().enumerate() { + let len = value.count_ones() as u64; + if n < len { + let index = select(value, n); + return Some((64 * key as u64 + index) as u16); + } + n -= len; + } + + None + } + + pub fn intersection_len_bitmap(&self, other: &BitmapStore) -> u64 { + self.bits.iter().zip(other.bits.iter()).map(|(&a, &b)| (a & b).count_ones() as u64).sum() + } + + pub(crate) fn intersection_len_interval(&self, interval: &Interval) -> u64 { + if interval.is_full() { + return self.len(); + } + let (start_id, start_bit) = (key(interval.start()), bit(interval.start())); + let (end_id, end_bit) = (key(interval.end()), bit(interval.end())); + let mut amount: u64 = 0; + for (i, mut cur_bit) in self.bits[start_id..=end_id].iter().copied().enumerate() { + if i == 0 { + cur_bit &= u64::MAX << start_bit; + } + if i == end_id - start_id { + cur_bit &= u64::MAX >> (64 - end_bit - 1); + } + amount += u64::from(cur_bit.count_ones()); + } + amount + } + + pub(crate) fn intersection_len_array(&self, other: &ArrayStore) -> u64 { + other + .iter() + .map(|&index| { + let (key, bit) = (key(index), bit(index)); + let old_w = self.bits[key]; + let new_w = old_w & (1 << bit); + new_w >> bit + }) + .sum::() + } + + pub fn iter(&self) -> BitmapIter<&[u64; BITMAP_LENGTH]> { + BitmapIter::new(&self.bits) + } + + pub fn into_iter(self) -> BitmapIter> { + BitmapIter::new(self.bits) + } + + pub fn as_array(&self) -> &[u64; BITMAP_LENGTH] { + &self.bits + } + + pub fn clear(&mut self) { + self.bits.fill(0); + self.len = 0; + } + + /// Set N bits that are currently 1 bit from the lower bit to 0. + pub fn remove_smallest(&mut self, mut clear_bits: u64) { + if self.len() < clear_bits { + self.clear(); + return; + } + self.len -= clear_bits; + for word in self.bits.iter_mut() { + let count = word.count_ones() as u64; + if clear_bits < count { + for _ in 0..clear_bits { + *word = *word & (*word - 1); + } + return; + } + *word = 0; + clear_bits -= count; + if clear_bits == 0 { + return; + } + } + } + + /// Set N bits that are currently 1 bit from the lower bit to 0. + pub fn remove_biggest(&mut self, mut clear_bits: u64) { + if self.len() < clear_bits { + self.clear(); + return; + } + self.len -= clear_bits; + for word in self.bits.iter_mut().rev() { + let count = word.count_ones() as u64; + if clear_bits < count { + for _ in 0..clear_bits { + *word &= !(1 << (63 - word.leading_zeros())); + } + return; + } + *word = 0; + clear_bits -= count; + if clear_bits == 0 { + return; + } + } + } + + pub(crate) fn internal_validate(&self) -> Result<(), &'static str> { + let expected_len: u64 = self.bits.iter().map(|bits| u64::from(bits.count_ones())).sum(); + if self.len != expected_len { + return Err("bitmap cardinality is incorrect"); + } + if self.len <= super::ARRAY_LIMIT { + return Err("cardinality is too small for a bitmap container"); + } + Ok(()) + } +} + +// this can be done in 3 instructions on x86-64 with bmi2 with: tzcnt(pdep(1 << rank, value)) +// if n > value.count_ones() this method returns 0 +fn select(mut value: u64, n: u64) -> u64 { + // reset n of the least significant bits + for _ in 0..n { + value &= value - 1; + } + value.trailing_zeros() as u64 +} + +impl Default for BitmapStore { + fn default() -> Self { + BitmapStore::new() + } +} + +#[derive(Debug)] +pub struct Error { + kind: ErrorKind, +} + +#[derive(Debug)] +pub enum ErrorKind { + Cardinality { expected: u64, actual: u64 }, +} + +impl Display for Error { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self.kind { + ErrorKind::Cardinality { expected, actual } => { + write!(f, "Expected cardinality was {expected} but was {actual}") + } + } + } +} + +#[cfg(feature = "std")] +impl std::error::Error for Error {} + +#[derive(Clone)] +pub struct BitmapIter> { + key: u16, + value: u64, + key_back: u16, + // If key_back <= key, current back value is actually in `value` + value_back: u64, + bits: B, +} + +impl> BitmapIter { + fn new(bits: B) -> BitmapIter { + BitmapIter { + key: 0, + value: bits.borrow()[0], + key_back: BITMAP_LENGTH as u16 - 1, + value_back: bits.borrow()[BITMAP_LENGTH - 1], + bits, + } + } + + /// Advance the iterator to the first value greater than or equal to `n`. + pub(crate) fn advance_to(&mut self, index: u16) { + let new_key = key(index) as u16; + let value = match new_key.cmp(&self.key) { + Ordering::Less => return, + Ordering::Equal => self.value, + Ordering::Greater => { + let bits = self.bits.borrow(); + let cmp = new_key.cmp(&self.key_back); + // Match arms can be reordered, this ordering is perf sensitive + if cmp == Ordering::Less { + // new_key is > self.key, < self.key_back, so it must be in bounds + unsafe { *bits.get_unchecked(new_key as usize) } + } else if cmp == Ordering::Equal { + self.value_back + } else { + // New key is greater than original key and key_back, this iterator is now empty + self.key = self.key_back; + self.value = 0; + self.value_back = 0; + return; + } + } + }; + let bit = bit(index); + let low_bits = (1 << bit) - 1; + + self.key = new_key; + self.value = value & !low_bits; + } + + /// Advance the back of iterator to the first value less than or equal to `n`. + pub(crate) fn advance_back_to(&mut self, index: u16) { + let new_key = key(index) as u16; + let (value, dst) = match new_key.cmp(&self.key_back) { + Ordering::Greater => return, + Ordering::Equal => { + let dst = + if self.key_back <= self.key { &mut self.value } else { &mut self.value_back }; + (*dst, dst) + } + Ordering::Less => { + let bits = self.bits.borrow(); + let cmp = new_key.cmp(&self.key); + // Match arms can be reordered, this ordering is perf sensitive + if cmp == Ordering::Greater { + // new_key is > self.key, < self.key_back, so it must be in bounds + let value = unsafe { *bits.get_unchecked(new_key as usize) }; + (value, &mut self.value_back) + } else if cmp == Ordering::Equal { + (self.value, &mut self.value) + } else { + // New key is less than original key and key_back, this iterator is now empty + self.key_back = self.key; + self.value = 0; + self.value_back = 0; + return; + } + } + }; + let bit = bit(index); + let low_bits = u64::MAX >> (64 - bit - 1); + + self.key_back = new_key; + *dst = value & low_bits; + } + + pub(crate) fn next_range(&mut self) -> Option> { + let value = *advance_to_next_nonzero_word( + &mut self.key, + &mut self.value, + self.bits.borrow(), + &mut self.key_back, + &mut self.value_back, + )?; + let offset = value.trailing_zeros() as u16; + let start = self.key * 64 + offset; + let value = value >> offset; + let num_set = value.trailing_ones() as u16; + let mut end_inclusive = start + (num_set - 1); + if num_set + offset != 64 { + self.value &= !0 << (num_set + offset); + return Some(start..=end_inclusive); + } + self.value = 0; + if self.key == self.key_back { + return Some(start..=end_inclusive); + } + loop { + debug_assert!(self.key < self.key_back); + self.key += 1; + self.value = if self.key == self.key_back { + mem::replace(&mut self.value_back, 0) + } else { + // Safety: + // - self.key and self.key_back are always kept in bounds + unsafe { *self.bits.borrow().get_unchecked(self.key as usize) } + }; + let set_bits = self.value.trailing_ones() as u16; + end_inclusive += set_bits; + if set_bits != 64 || self.key == self.key_back { + if set_bits != 64 { + self.value &= !0 << set_bits; + } else { + self.value = 0; + } + return Some(start..=end_inclusive); + } + } + } + + pub(crate) fn next_range_back(&mut self) -> Option> { + let value_dst = advance_back_to_next_nonzero_word( + &mut self.key, + &mut self.value, + self.bits.borrow(), + &mut self.key_back, + &mut self.value_back, + )?; + + let end_offset = value_dst.leading_zeros() as u16; + let end_inclusive = self.key_back * 64 + (63 - end_offset); + let value = *value_dst << end_offset; + let num_set = value.leading_ones() as u16; + let mut start = end_inclusive - (num_set - 1); + if num_set + end_offset != 64 { + *value_dst &= !0 >> (num_set + end_offset); + return Some(start..=end_inclusive); + } + *value_dst = 0; + if self.key == self.key_back { + return Some(start..=end_inclusive); + } + loop { + debug_assert!(self.key_back > self.key); + self.key_back -= 1; + let value_dst = if self.key_back == self.key { + &mut self.value + } else { + // Safety: + // - self.key and self.key_back are always kept in bounds + let value = unsafe { *self.bits.borrow().get_unchecked(self.key_back as usize) }; + self.value_back = value; + &mut self.value_back + }; + let set_bits = value_dst.leading_ones() as u16; + start -= set_bits; + if set_bits != 64 || self.key_back == self.key { + if set_bits != 64 { + *value_dst &= !0 >> set_bits; + } else { + *value_dst = 0; + } + return Some(start..=end_inclusive); + } + } + } + + pub(crate) fn peek(&self) -> Option { + let mut key = self.key; + let mut value = self.value; + let mut key_back = self.key_back; + let mut value_back = self.value_back; + let value = advance_to_next_nonzero_word( + &mut key, + &mut value, + self.bits.borrow(), + &mut key_back, + &mut value_back, + )?; + + let index = value.trailing_zeros() as u16; + Some(64 * key + index) + } + + pub(crate) fn peek_back(&self) -> Option { + let mut key = self.key; + let mut key_back = self.key_back; + let mut value = self.value; + let mut value_back = self.value_back; + let value = advance_back_to_next_nonzero_word( + &mut key, + &mut value, + self.bits.borrow(), + &mut key_back, + &mut value_back, + )?; + let index_from_left = value.leading_zeros() as u16; + let index = 63 - index_from_left; + Some(64 * key_back + index) + } +} + +fn advance_to_next_nonzero_word<'a>( + key: &mut u16, + value: &'a mut u64, + bits: &[u64; BITMAP_LENGTH], + key_back: &mut u16, + value_back: &'a mut u64, +) -> Option<&'a mut u64> { + if *value == 0 { + if *key >= *key_back { + return None; + } + loop { + debug_assert!(*key < *key_back); + *key += 1; + if *key == *key_back { + *value = mem::replace(value_back, 0); + if *value == 0 { + return None; + } + break; + } + // Safety: + // - self.key and self.key_back are always kept in bounds + *value = unsafe { *bits.get_unchecked(*key as usize) }; + if *value != 0 { + break; + } + } + } + debug_assert!(*value != 0); + Some(value) +} + +fn advance_back_to_next_nonzero_word<'a>( + key: &mut u16, + value: &'a mut u64, + bits: &[u64; BITMAP_LENGTH], + key_back: &mut u16, + value_back: &'a mut u64, +) -> Option<&'a mut u64> { + if *key_back > *key { + if *value_back != 0 { + return Some(value_back); + } + loop { + debug_assert!(key_back > key); + *key_back -= 1; + if *key_back == *key { + break; + } + // Safety: + // - self.key and self.key_back are always kept in bounds + *value_back = unsafe { *bits.get_unchecked(*key_back as usize) }; + if *value_back != 0 { + return Some(value_back); + } + } + } + debug_assert!(*key_back == *key); + if *value != 0 { + Some(value) + } else { + None + } +} + +impl> Iterator for BitmapIter { + type Item = u16; + + fn next(&mut self) -> Option { + let value = advance_to_next_nonzero_word( + &mut self.key, + &mut self.value, + self.bits.borrow(), + &mut self.key_back, + &mut self.value_back, + )?; + let index = value.trailing_zeros() as u16; + *value &= *value - 1; + Some(64 * self.key + index) + } + + fn size_hint(&self) -> (usize, Option) { + let mut len: u32 = self.value.count_ones(); + if self.key < self.key_back { + for v in &self.bits.borrow()[self.key as usize + 1..self.key_back as usize] { + len += v.count_ones(); + } + len += self.value_back.count_ones(); + } + (len as usize, Some(len as usize)) + } + + fn count(self) -> usize + where + Self: Sized, + { + self.len() + } +} + +impl> DoubleEndedIterator for BitmapIter { + fn next_back(&mut self) -> Option { + let value_dst = advance_back_to_next_nonzero_word( + &mut self.key, + &mut self.value, + self.bits.borrow(), + &mut self.key_back, + &mut self.value_back, + )?; + let index_from_left = value_dst.leading_zeros() as u16; + let index = 63 - index_from_left; + *value_dst &= !(1 << index); + Some(64 * self.key_back + index) + } +} + +impl> ExactSizeIterator for BitmapIter {} + +#[inline] +pub fn key(index: u16) -> usize { + index as usize / 64 +} + +#[inline] +pub fn bit(index: u16) -> usize { + index as usize % 64 +} + +#[inline] +fn op_bitmaps(bits1: &mut BitmapStore, bits2: &BitmapStore, op: impl Fn(&mut u64, u64)) { + bits1.len = 0; + for (index1, &index2) in bits1.bits.iter_mut().zip(bits2.bits.iter()) { + op(index1, index2); + bits1.len += index1.count_ones() as u64; + } +} + +impl BitOrAssign<&Self> for BitmapStore { + fn bitor_assign(&mut self, rhs: &Self) { + op_bitmaps(self, rhs, BitOrAssign::bitor_assign); + } +} + +impl BitOrAssign<&ArrayStore> for BitmapStore { + fn bitor_assign(&mut self, rhs: &ArrayStore) { + for &index in rhs.iter() { + let (key, bit) = (key(index), bit(index)); + let old_w = self.bits[key]; + let new_w = old_w | (1 << bit); + self.len += (old_w ^ new_w) >> bit; + self.bits[key] = new_w; + } + } +} + +impl BitAndAssign<&Self> for BitmapStore { + fn bitand_assign(&mut self, rhs: &Self) { + op_bitmaps(self, rhs, BitAndAssign::bitand_assign); + } +} + +impl SubAssign<&Self> for BitmapStore { + #[allow(clippy::suspicious_op_assign_impl)] + fn sub_assign(&mut self, rhs: &Self) { + op_bitmaps(self, rhs, |l, r| *l &= !r); + } +} + +impl SubAssign<&ArrayStore> for BitmapStore { + #[allow(clippy::suspicious_op_assign_impl)] + fn sub_assign(&mut self, rhs: &ArrayStore) { + for &index in rhs.iter() { + let (key, bit) = (key(index), bit(index)); + let old_w = self.bits[key]; + let new_w = old_w & !(1 << bit); + self.len -= (old_w ^ new_w) >> bit; + self.bits[key] = new_w; + } + } +} + +impl BitXorAssign<&Self> for BitmapStore { + fn bitxor_assign(&mut self, rhs: &Self) { + op_bitmaps(self, rhs, BitXorAssign::bitxor_assign); + } +} + +impl BitXorAssign<&ArrayStore> for BitmapStore { + fn bitxor_assign(&mut self, rhs: &ArrayStore) { + let mut len = self.len as i64; + for &index in rhs.iter() { + let (key, bit) = (key(index), bit(index)); + let old_w = self.bits[key]; + let new_w = old_w ^ (1 << bit); + len += 1 - 2 * (((1 << bit) & old_w) >> bit) as i64; // +1 or -1 + self.bits[key] = new_w; + } + self.len = len as u64; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_bitmap_remove_smallest() { + let mut store = BitmapStore::new(); + let range = RangeInclusive::new(1, 3); + store.insert_range(range); + let range_second = RangeInclusive::new(5, 65535); + // store.bits[0] = 0b1111111111111111111111111111111111111111111111111111111111101110 + store.insert_range(range_second); + store.remove_smallest(2); + assert_eq!( + store.bits[0], + 0b1111111111111111111111111111111111111111111111111111111111101000 + ); + } + + #[test] + fn test_bitmap_remove_biggest() { + let mut store = BitmapStore::new(); + let range = RangeInclusive::new(1, 3); + store.insert_range(range); + let range_second = RangeInclusive::new(5, 65535); + // store.bits[1023] = 0b1111111111111111111111111111111111111111111111111111111111111111 + store.insert_range(range_second); + store.remove_biggest(2); + assert_eq!( + store.bits[1023], + 0b11111111111111111111111111111111111111111111111111111111111111 + ); + } +} diff --git a/vendor/roaring/src/bitmap/store/interval_store.rs b/vendor/roaring/src/bitmap/store/interval_store.rs new file mode 100644 index 0000000..86b2022 --- /dev/null +++ b/vendor/roaring/src/bitmap/store/interval_store.rs @@ -0,0 +1,2550 @@ +use alloc::vec::Vec; +use core::ops::{ + BitAnd, BitAndAssign, BitOrAssign, BitXor, BitXorAssign, RangeInclusive, SubAssign, +}; +use core::slice::Iter; +use core::{cmp::Ordering, ops::ControlFlow}; + +use super::{ArrayStore, BitmapStore}; + +#[derive(PartialEq, Eq, Clone, Debug)] +pub(crate) struct IntervalStore(Vec); + +pub(crate) const RUN_NUM_BYTES: usize = 2; +pub(crate) const RUN_ELEMENT_BYTES: usize = 4; + +impl Default for IntervalStore { + fn default() -> Self { + Self::new() + } +} + +impl IntervalStore { + pub fn new() -> Self { + Self(Default::default()) + } + + pub fn new_with_range(range: Interval) -> Self { + Self(alloc::vec![range]) + } + + pub fn full() -> Self { + Self(alloc::vec![Interval::new_unchecked(0, u16::MAX)]) + } + + pub fn byte_size(&self) -> usize { + Self::serialized_byte_size(self.run_amount()) + } + + pub fn serialized_byte_size(run_amount: u64) -> usize { + RUN_NUM_BYTES + (RUN_ELEMENT_BYTES * run_amount as usize) + } + + #[cfg(feature = "std")] + pub fn from_vec_unchecked(vec: Vec) -> Self { + #[cfg(debug_assertions)] + { + for win in vec.windows(2) { + let [cur_interval, next] = [win[0], win[1]]; + assert!(cur_interval.end + 1 < next.start); + assert!(cur_interval.start <= cur_interval.end); + } + } + Self(vec) + } + + pub(crate) fn push_interval_unchecked(&mut self, interval: Interval) { + debug_assert!(self.0.last().map(|f| f.end < interval.start).unwrap_or(true)); + debug_assert!(interval.start <= interval.end); + self.0.push(interval) + } + + #[inline] + pub fn insert(&mut self, index: u16) -> bool { + // All intervals before idx are _fully_ before our index (iv.end < index) + let idx = self.0.partition_point(|iv| iv.end < index); + let (before, maybe_after) = self.0.split_at_mut(idx); + if let Some(next) = maybe_after.first_mut() { + // Check if the next interval actually already contains our index + // Because of partition_point, we know already know end >= index + if next.start <= index { + // index is already in the interval + return false; + } + // `next` is instead the first interval _after_ our index, + // check if we should grow that interval down by one + // Because we know from above that next.start > index, adding 1 is safe + if next.start == index + 1 { + next.start -= 1; + + // Check if the previous interval will now be continuous with this interval + if let Some(prev) = before.last_mut() { + // From the partition point: prev.end < index, subtracting 1 is safe + if prev.end == index - 1 { + prev.end = next.end; + self.0.remove(idx); + } + } + return true; + } + } + if let Some(prev) = before.last_mut() { + // Because we know from the partition point that prev.end < index, adding 1 is safe + if prev.end + 1 == index { + // Merge with previous interval + prev.end += 1; + // If we had needed to merge with the next interval, we would have handled that in + // the previous if statement, so we're done here + return true; + } + } + self.0.insert(idx, Interval::new_unchecked(index, index)); + true + } + + #[inline] + pub fn insert_range(&mut self, range: RangeInclusive) -> u64 { + if range.is_empty() { + return 0; + } + let mut interval = Interval { start: *range.start(), end: *range.end() }; + // All intervals in `start_idx..end_idx` are fully contained in our interval. + let mut start_idx = self.0.partition_point(|iv| iv.start < interval.start); + let mut end_idx = + self.0[start_idx..].partition_point(|iv| iv.end <= interval.end) + start_idx; + + if let Some(prev) = self.0[..start_idx].last() { + // If the previous interval contains our start, or would be contiguous with us, expand + // to include it + // from partition point, we know prev.start < interval.start + if prev.end >= interval.start - 1 { + // We need to merge with the previous interval + interval.start = prev.start; + interval.end = interval.end.max(prev.end); + start_idx -= 1; + } + } + if let Some(next) = self.0.get(end_idx) { + // from partition point, we know next.end > interval.end + if next.start <= interval.end + 1 { + // We need to merge with the next interval + interval.end = next.end; + interval.start = interval.start.min(next.start); + end_idx += 1; + } + } + + let mut added_count = interval.run_len(); + // Replace the first interval to be replaced with an interval covering the new range + // and remove the rest + // Otherwise, just insert a new interval + if let [first, rest @ ..] = &mut self.0[start_idx..end_idx] { + added_count -= first.run_len(); + added_count -= rest.iter().map(|iv| iv.run_len()).sum::(); + *first = interval; + self.0.drain(start_idx + 1..end_idx); + } else { + // No intervals to merge with, we can just insert + self.0.insert(start_idx, interval); + } + added_count + } + + pub fn push(&mut self, index: u16) -> bool { + if let Some(last_interval) = self.0.last_mut() { + if last_interval.end.checked_add(1).map(|f| f == index).unwrap_or(false) { + last_interval.end = index; + true + } else if last_interval.end < index { + self.0.push(Interval::new_unchecked(index, index)); + true + } else { + false + } + } else { + self.0.push(Interval::new_unchecked(index, index)); + true + } + } + + pub fn remove(&mut self, index: u16) -> bool { + self.0 + .binary_search_by(|iv| cmp_index_interval(index, *iv).reverse()) + .map(|loc| { + // loc always points to an interval + if index == self.0[loc].start && index == self.0[loc].end { + // Remove entire run if it only contains this value + self.0.remove(loc); + } else if index == self.0[loc].end { + // Value is last in this interval + self.0[loc].end = index - 1; + } else if index == self.0[loc].start { + // Value is first in this interval + self.0[loc].start = index + 1; + } else { + // Value lies inside the interval, we need to split it + // First construct a new interval with the right part + let new_interval = Interval::new_unchecked(index + 1, self.0[loc].end); + // Then shrink the current interval + self.0[loc].end = index - 1; + // Then insert the new interval leaving gap where value was removed + self.0.insert(loc + 1, new_interval); + } + }) + .is_ok() + } + + pub fn remove_range(&mut self, range: RangeInclusive) -> u64 { + if range.is_empty() { + return 0; + } + + let mut interval = Interval::new_unchecked(*range.start(), *range.end()); + // All intervals in `start_idx..end_idx` are fully contained in our interval. + let start_idx = self.0.partition_point(|iv| iv.start < interval.start); + let end_idx = self.0[start_idx..].partition_point(|iv| iv.end <= interval.end) + start_idx; + let mut removed_count = 0; + let mut add_needed = false; + if let Some(prev) = self.0[..start_idx].last_mut() { + // If the previous interval contains our start, remove it + // from partition point, we know prev.start < interval.start + if prev.end >= interval.start { + // We need to remove from the previous interval + removed_count += + Interval::new_unchecked(interval.start, prev.end.min(interval.end)).run_len(); + let new_end = interval.start - 1; + add_needed = prev.end > interval.end; + if add_needed { + interval.start = interval.end + 1; + interval.end = prev.end; + } + prev.end = new_end; + } + } + if let Some(next) = self.0.get_mut(end_idx) { + // from partition point, we know next.end > interval.end + if next.start <= interval.end { + // We need to remove everything til interval.end + removed_count += + Interval::new_unchecked(next.start.max(interval.start), interval.end).run_len(); + next.start = interval.end + 1; + } + } + + // Replace the first interval to be replaced with an interval covering the new range + // and remove the rest + // Otherwise, just insert a new interval + if let [first, rest @ ..] = &mut self.0[start_idx..end_idx] { + removed_count += first.run_len(); + removed_count += rest.iter().map(|iv| iv.run_len()).sum::(); + self.0.drain(start_idx..end_idx); + } else if add_needed { + // We are removing a range contained in a single interval + // As such we must add a new interval + self.0.insert(start_idx, interval); + } + removed_count + } + + pub fn remove_smallest(&mut self, mut amount: u64) { + let mut remove_to = 0; + let mut last_interval = None; + for (i, interval) in self.0.iter_mut().enumerate() { + let too_much = interval.run_len() < amount; + if too_much { + amount -= interval.run_len(); + } + remove_to = i; + last_interval = Some(interval); + if !too_much { + break; + } + } + if let Some(last_interval) = last_interval { + if last_interval.run_len() < amount { + remove_to += 1; + } else { + last_interval.start += amount as u16; + } + } + self.0.drain(..remove_to); + } + + pub fn remove_biggest(&mut self, mut amount: u64) { + let mut remove_to = 0; + let mut last_interval = None; + for (i, interval) in self.0.iter_mut().enumerate().rev() { + let too_much = interval.run_len() < amount; + if too_much { + amount -= interval.run_len(); + } + remove_to = i; + last_interval = Some(interval); + if !too_much { + break; + } + } + if let Some(last_interval) = last_interval { + if last_interval.run_len() >= amount { + remove_to += 1; + last_interval.end -= amount as u16; + } + } + self.0.drain(remove_to..); + } + + pub fn contains(&self, index: u16) -> bool { + self.0.binary_search_by(|iv| cmp_index_interval(index, *iv).reverse()).is_ok() + } + + pub fn contains_range(&self, range: RangeInclusive) -> bool { + let interval = Interval::new_unchecked(*range.start(), *range.end()); + let start = self.0.binary_search_by(|iv| cmp_index_interval(interval.start, *iv).reverse()); + let end = self.0.binary_search_by(|iv| cmp_index_interval(interval.end, *iv).reverse()); + match (start, end) { + // both start and end are inside an interval, + // check if this interval is that same interval. + // If this is not the case then this range is not contained in this store + (Ok(start_id), Ok(end_id)) => start_id == end_id, + _ => false, + } + } + + fn step_walk< + 'a, + R, + C: FnMut(Interval, Interval, R) -> ControlFlow, + E: FnMut( + (Option, Option), + (Iter<'a, Interval>, Iter<'a, Interval>), + R, + ) -> R, + >( + &'a self, + other: &'a Self, + mut calc: C, + mut else_op: E, + mut buffer: R, + ) -> R { + let (mut i1, mut i2) = (self.0.iter(), other.0.iter()); + let (mut iv1, mut iv2) = (i1.next(), i2.next()); + loop { + match (iv1, iv2) { + (Some(v1), Some(v2)) => { + match calc(*v1, *v2, buffer) { + ControlFlow::Continue(new_buffer) => buffer = new_buffer, + ControlFlow::Break(end) => return end, + } + + // We increase the iterator based on which one is furthest behind. + // Or both if they are equal to each other. + match v1.end.cmp(&v2.end) { + Ordering::Less => iv1 = i1.next(), + Ordering::Greater => iv2 = i2.next(), + Ordering::Equal => { + iv1 = i1.next(); + iv2 = i2.next(); + } + } + } + (value1, value2) => { + return else_op((value1.copied(), value2.copied()), (i1, i2), buffer) + } + } + } + } + + pub fn is_disjoint(&self, other: &Self) -> bool { + self.step_walk( + other, + |interval1, interval2, _| { + if interval1.overlaps(&interval2) { + ControlFlow::Break(false) + } else { + ControlFlow::Continue(true) + } + }, + |_, _, _| true, + false, + ) + } + + pub(crate) fn is_disjoint_array(&self, array: &ArrayStore) -> bool { + array.iter().all(|&i| !self.contains(i)) + } + + pub(crate) fn is_disjoint_bitmap(&self, array: &BitmapStore) -> bool { + // TODO: make this better + array.iter().all(|i| !self.contains(i)) + } + + pub fn is_subset(&self, other: &Self) -> bool { + self.0.iter().all(|interval| other.contains_range(interval.start..=interval.end)) + } + + pub(crate) fn is_subset_array(&self, other: &ArrayStore) -> bool { + self.0.iter().all(|interval| other.contains_range(interval.start..=interval.end)) + } + + pub(crate) fn is_subset_bitmap(&self, other: &BitmapStore) -> bool { + self.0.iter().all(|interval| other.contains_range(interval.start..=interval.end)) + } + + pub fn intersection_len(&self, other: &Self) -> u64 { + self.step_walk( + other, + |interval1, interval2, buffer| { + ControlFlow::Continue( + interval1.overlapping_interval(&interval2).map(|f| f.run_len()).unwrap_or(0) + + buffer, + ) + }, + |_, _, buffer| buffer, + 0, + ) + } + + pub(crate) fn intersection_len_bitmap(&self, other: &BitmapStore) -> u64 { + self.0.iter().map(|f| other.intersection_len_interval(f)).sum() + } + + pub(crate) fn intersection_len_array(&self, other: &ArrayStore) -> u64 { + other.iter().map(|&f| self.contains(f) as u64).sum() + } + + pub fn len(&self) -> u64 { + self.0.iter().map(|iv| iv.run_len()).sum() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + pub fn min(&self) -> Option { + self.0.first().map(|f| f.start) + } + + pub fn max(&self) -> Option { + self.0.last().map(|f| f.end) + } + + pub fn rank(&self, value: u16) -> u64 { + let mut rank = 0; + for iv in self.0.iter() { + if iv.end <= value { + rank += iv.run_len(); + } else if iv.start <= value { + rank += Interval::new_unchecked(iv.start, value).run_len(); + } else { + break; + } + } + rank + } + + pub fn select(&self, mut n: u16) -> Option { + for iv in self.0.iter() { + let run_len = iv.run_len(); + if run_len <= n.into() { + n -= iv.run_len() as u16; // this conversion never overflows since run_len is + // smaller then a u16 + } else { + return Some(iv.start + n); + } + } + None + } + + pub fn run_amount(&self) -> u64 { + self.0.len() as u64 + } + + pub fn to_bitmap(&self) -> BitmapStore { + let mut bits = BitmapStore::new(); + for iv in self.0.iter() { + bits.insert_range(iv.start..=iv.end); + } + bits + } + + pub fn to_array(&self) -> ArrayStore { + let mut array = ArrayStore::new(); + for iv in self.0.iter() { + array.insert_range(iv.start..=iv.end); + } + array + } + + pub(crate) fn iter(&'_ self) -> RunIterBorrowed<'_> { + self.into_iter() + } + + pub(crate) fn iter_intervals(&'_ self) -> core::slice::Iter<'_, Interval> { + self.0.iter() + } + + pub(crate) fn internal_validate(&self) -> Result<(), &'static str> { + if self.0.is_empty() { + return Err("run container with zero runs"); + } + let mut last_end: Option = None; + for run in &self.0 { + if run.start > run.end { + return Err("empty run container"); + } + if let Some(last_end) = last_end.replace(run.end) { + if last_end >= run.start { + return Err("overlapping or unordered runs"); + } + if last_end.saturating_add(1) >= run.start { + return Err("contiguous runs"); + } + } + } + + Ok(()) + } +} + +impl From for BitmapStore { + fn from(value: IntervalStore) -> Self { + value.to_bitmap() + } +} + +impl From for ArrayStore { + fn from(value: IntervalStore) -> Self { + value.to_array() + } +} + +impl BitOrAssign for IntervalStore { + fn bitor_assign(&mut self, mut rhs: Self) { + let (add_intervals, take_intervals, self_is_add) = + if self.len() > rhs.len() { (self, &mut rhs, true) } else { (&mut rhs, self, false) }; + for iv in take_intervals.iter_intervals() { + add_intervals.insert_range(iv.start..=iv.end); + } + if !self_is_add { + core::mem::swap(add_intervals, take_intervals); + } + } +} + +impl BitOrAssign<&ArrayStore> for IntervalStore { + fn bitor_assign(&mut self, rhs: &ArrayStore) { + for &i in rhs.iter() { + self.insert(i); + } + } +} + +impl BitOrAssign<&Self> for IntervalStore { + fn bitor_assign(&mut self, rhs: &Self) { + for iv in rhs.iter_intervals() { + self.insert_range(iv.start..=iv.end); + } + } +} + +impl BitAnd for &IntervalStore { + type Output = IntervalStore; + + fn bitand(self, rhs: Self) -> Self::Output { + self.step_walk( + rhs, + |iv1, iv2, mut buf: IntervalStore| { + if let Some(new_iv) = iv1.overlapping_interval(&iv2) { + buf.insert_range(new_iv.start..=new_iv.end); + } + ControlFlow::Continue(buf) + }, + |_, _, buf| buf, + IntervalStore::new(), + ) + } +} + +impl BitAndAssign<&IntervalStore> for ArrayStore { + fn bitand_assign(&mut self, rhs: &IntervalStore) { + self.retain(|f| rhs.contains(f)); + } +} + +impl SubAssign<&Self> for IntervalStore { + fn sub_assign(&mut self, rhs: &Self) { + for iv in rhs.iter_intervals() { + self.remove_range(iv.start..=iv.end); + } + } +} + +impl BitXor for &IntervalStore { + type Output = IntervalStore; + + fn bitxor(self, rhs: Self) -> Self::Output { + let mut union = self.clone(); + union |= rhs; + let intersection = self & rhs; + union -= &intersection; + union + } +} + +impl BitXorAssign<&ArrayStore> for IntervalStore { + fn bitxor_assign(&mut self, rhs: &ArrayStore) { + rhs.iter().for_each(|&f| { + if self.contains(f) { + self.remove(f); + } else { + self.insert(f); + } + }) + } +} + +pub(crate) type RunIterOwned = RunIter>; +pub(crate) type RunIterBorrowed<'a> = RunIter>; + +impl IntoIterator for IntervalStore { + type Item = u16; + type IntoIter = RunIter>; + + fn into_iter(self) -> Self::IntoIter { + RunIter::new(self.0.into_iter()) + } +} + +impl<'a> IntoIterator for &'a IntervalStore { + type Item = u16; + type IntoIter = RunIter>; + + fn into_iter(self) -> Self::IntoIter { + RunIter::new(self.0.iter()) + } +} + +pub(crate) trait SliceIterator: Iterator + DoubleEndedIterator { + fn as_slice(&self) -> &[I]; +} + +impl SliceIterator for alloc::vec::IntoIter { + fn as_slice(&self) -> &[I] { + alloc::vec::IntoIter::as_slice(self) + } +} + +impl<'a, I> SliceIterator for core::slice::Iter<'a, I> { + fn as_slice(&self) -> &'a [I] { + core::slice::Iter::as_slice(self) + } +} + +#[derive(Clone)] +pub(crate) struct RunIter> { + forward_offset: u16, + backward_offset: u16, + intervals: I, +} + +impl> RunIter { + fn new(intervals: I) -> Self { + Self { forward_offset: 0, backward_offset: 0, intervals } + } + + fn move_next(&mut self) { + if let Some(value) = self.forward_offset.checked_add(1) { + self.forward_offset = value; + } else { + self.intervals.next(); + self.forward_offset = 0; + return; + } + let only_interval = self.intervals.as_slice().len() == 1; + let total_offset = u64::from(self.forward_offset) + + if only_interval { u64::from(self.backward_offset) } else { 0 }; + if Some(total_offset) >= self.intervals.as_slice().first().map(|f| f.run_len()) { + self.intervals.next(); + self.forward_offset = 0; + if only_interval { + self.backward_offset = 0; + } + } + } + + fn move_next_back(&mut self) { + if let Some(value) = self.backward_offset.checked_add(1) { + self.backward_offset = value; + } else { + self.intervals.next_back(); + self.backward_offset = 0; + return; + } + let only_interval = self.intervals.as_slice().len() == 1; + let total_offset = u64::from(self.backward_offset) + + if only_interval { u64::from(self.forward_offset) } else { 0 }; + if Some(total_offset) >= self.intervals.as_slice().last().map(|f| f.run_len()) { + self.intervals.next_back(); + self.backward_offset = 0; + if only_interval { + self.forward_offset = 0; + } + } + } + + fn remaining_size(&self) -> usize { + let total_size = self.intervals.as_slice().iter().map(|f| f.run_len()).sum::(); + let total_offset = u64::from(self.forward_offset) + u64::from(self.backward_offset); + debug_assert!(total_size >= total_offset); + total_size.saturating_sub(total_offset) as usize + } + + /// Advance the iterator to the first value greater than or equal to `n`. + pub(crate) fn advance_to(&mut self, n: u16) { + if n == 0 { + return; + } + if self + .intervals + .as_slice() + .first() + .map(|f| f.start + self.forward_offset > n) + .unwrap_or(true) + { + return; + } + match self.intervals.as_slice().binary_search_by(|iv| cmp_index_interval(n, *iv).reverse()) + { + Ok(index) => { + if let Some(value) = index.checked_sub(1) { + self.intervals.nth(value); + } + let first_interval = self.intervals.as_slice().first().unwrap(); + self.forward_offset = n - first_interval.start; + if self.intervals.as_slice().len() == 1 + && u64::from(self.forward_offset) + u64::from(self.backward_offset) + >= first_interval.run_len() + { + // If we are now the only interval, and we've now met the forward offset, + // consume the final interval + _ = self.intervals.next(); + self.forward_offset = 0; + self.backward_offset = 0; + } + } + Err(index) => { + if index == self.intervals.as_slice().len() { + // Consume the whole iterator + self.intervals.nth(index); + self.forward_offset = 0; + self.backward_offset = 0; + return; + } + if let Some(value) = index.checked_sub(1) { + self.intervals.nth(value); + self.forward_offset = 0; + } + } + } + } + + /// Advance the back of iterator to the first value less than or equal to `n`. + pub(crate) fn advance_back_to(&mut self, n: u16) { + if n == u16::MAX { + return; + } + if self + .intervals + .as_slice() + .last() + .map(|f| f.end - self.backward_offset < n) + .unwrap_or(true) + { + return; + } + match self.intervals.as_slice().binary_search_by(|iv| cmp_index_interval(n, *iv).reverse()) + { + Ok(index) => { + let backward_index = self.intervals.as_slice().len() - index - 1; + if let Some(value) = backward_index.checked_sub(1) { + self.intervals.nth_back(value); + } + let last_interval = self.intervals.as_slice().last().unwrap(); + self.backward_offset = last_interval.end - n; + if self.intervals.as_slice().len() == 1 + && u64::from(self.forward_offset) + u64::from(self.backward_offset) + >= last_interval.run_len() + { + // If we are now the only interval, and we've now met the forward offset, + // consume the final interval + _ = self.intervals.next_back(); + self.forward_offset = 0; + self.backward_offset = 0; + } + } + Err(index) => { + if index == 0 { + // Consume the whole iterator + self.intervals.nth_back(self.intervals.as_slice().len()); + self.forward_offset = 0; + self.backward_offset = 0; + return; + } + let backward_index = self.intervals.as_slice().len() - index; + if let Some(value) = backward_index.checked_sub(1) { + self.intervals.nth_back(value); + self.backward_offset = 0; + } + } + } + } + + pub(crate) fn next_range(&mut self) -> Option> { + let interval = self.intervals.as_slice().first()?; + let end_offset = + if self.intervals.as_slice().len() == 1 { self.backward_offset } else { 0 }; + let result = interval.start + self.forward_offset..=interval.end - end_offset; + _ = self.intervals.next(); + self.forward_offset = 0; + if self.intervals.as_slice().is_empty() { + self.backward_offset = 0; + } + Some(result) + } + + pub(crate) fn next_range_back(&mut self) -> Option> { + let interval = self.intervals.as_slice().last()?; + let start_offset = + if self.intervals.as_slice().len() == 1 { self.forward_offset } else { 0 }; + let result = interval.start + start_offset..=interval.end - self.backward_offset; + _ = self.intervals.next_back(); + self.backward_offset = 0; + if self.intervals.as_slice().is_empty() { + self.forward_offset = 0; + } + Some(result) + } + + pub(crate) fn peek(&self) -> Option { + let result = self.intervals.as_slice().first()?.start + self.forward_offset; + Some(result) + } + + pub(crate) fn peek_back(&self) -> Option { + let result = self.intervals.as_slice().last()?.end - self.backward_offset; + Some(result) + } +} + +impl> Iterator for RunIter { + type Item = u16; + + fn next(&mut self) -> Option { + let result = self.intervals.as_slice().first()?.start + self.forward_offset; + self.move_next(); + Some(result) + } + + fn size_hint(&self) -> (usize, Option) { + let remaining_size = self.remaining_size(); + (remaining_size, Some(remaining_size)) + } + + fn count(self) -> usize { + self.remaining_size() + } + + fn nth(&mut self, n: usize) -> Option { + if n > usize::from(u16::MAX) { + // Consume the whole iterator + self.intervals.nth(self.intervals.as_slice().len()); + self.forward_offset = 0; + self.backward_offset = 0; + return None; + } + if let Some(skip) = n.checked_sub(1) { + let mut to_skip = skip as u64; + loop { + let full_first_interval_len = self.intervals.as_slice().first()?.run_len(); + let consumed_len = u64::from(self.forward_offset) + + if self.intervals.as_slice().len() == 1 { + u64::from(self.backward_offset) + } else { + 0 + }; + let to_remove = (full_first_interval_len - consumed_len).min(to_skip); + to_skip -= to_remove; + self.forward_offset += to_remove as u16; + self.move_next(); + if to_skip == 0 { + break; + } + } + } + self.next() + } +} + +impl> DoubleEndedIterator for RunIter { + fn next_back(&mut self) -> Option { + let result = self.intervals.as_slice().last()?.end - self.backward_offset; + self.move_next_back(); + Some(result) + } +} + +impl> ExactSizeIterator for RunIter {} + +/// This interval is inclusive to end. +#[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Debug)] +pub(crate) struct Interval { + start: u16, + end: u16, +} + +impl From> for Interval { + fn from(value: RangeInclusive) -> Self { + Interval::new_unchecked(*value.start(), *value.end()) + } +} + +impl IntoIterator for Interval { + type Item = u16; + type IntoIter = RangeInclusive; + + fn into_iter(self) -> Self::IntoIter { + self.start..=self.end + } +} + +impl IntoIterator for &'_ Interval { + type Item = u16; + type IntoIter = RangeInclusive; + + fn into_iter(self) -> Self::IntoIter { + self.start..=self.end + } +} + +pub(crate) fn cmp_index_interval(index: u16, iv: Interval) -> Ordering { + if index < iv.start { + Ordering::Less + } else if index > iv.end { + Ordering::Greater + } else { + Ordering::Equal + } +} + +impl Interval { + pub fn new_unchecked(start: u16, end: u16) -> Self { + debug_assert!(start <= end); + Self { start, end } + } + + pub fn start(&self) -> u16 { + self.start + } + + pub fn end(&self) -> u16 { + self.end + } + + pub fn overlaps(&self, interval: &Self) -> bool { + interval.start <= self.end && self.start <= interval.end + } + + pub fn overlapping_interval(&self, other: &Self) -> Option { + if self.overlaps(other) { + Some(Self::new_unchecked(self.start.max(other.start), self.end.min(other.end))) + } else { + None + } + } + + pub fn run_len(&self) -> u64 { + u64::from(self.end - self.start) + 1 + } + + pub fn is_full(&self) -> bool { + self.start == 0 && self.end == u16::MAX + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn insert_empty() { + let mut interval_store = IntervalStore(alloc::vec![]); + assert!(interval_store.insert(1)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 1, end: 1 }])) + } + + #[test] + fn insert_consecutive_begin() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 0, end: 0 },]); + assert!(interval_store.insert(1)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 0, end: 1 }])) + } + + #[test] + fn insert_consecutive_end() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 1, end: 1 },]); + assert!(interval_store.insert(0)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 0, end: 1 }])) + } + + #[test] + fn insert_consecutive_begin_end() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 0, end: 0 }, + Interval { start: 2, end: 2 }, + ]); + interval_store.insert(1); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 0, end: 2 }])) + } + + #[test] + fn insert_arbitrary() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 0, end: 3 }, + Interval { start: 9, end: 10 }, + ]); + interval_store.insert(5); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 0, end: 3 }, + Interval { start: 5, end: 5 }, + Interval { start: 9, end: 10 }, + ]) + ) + } + + #[test] + fn insert_u16_max() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 0, end: 3 },]); + interval_store.insert(u16::MAX); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 0, end: 3 }, + Interval { start: u16::MAX, end: u16::MAX }, + ]) + ) + } + + #[test] + fn insert_u16_max_consecutive() { + let mut interval_store = + IntervalStore(alloc::vec![Interval { start: 0, end: u16::MAX - 1 },]); + interval_store.insert(u16::MAX); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![Interval { start: 0, end: u16::MAX },]) + ) + } + + #[test] + fn insert_consecutive_end_with_extra() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 65079, end: 65079 }, + Interval { start: 65179, end: 65179 }, + ]); + assert!(interval_store.insert(65080)); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 65079, end: 65080 }, + Interval { start: 65179, end: 65179 }, + ]) + ) + } + + #[test] + fn insert_range_empty() { + let mut interval_store = IntervalStore(alloc::vec![]); + assert_eq!(interval_store.insert_range(1..=2), Interval::new_unchecked(1, 2).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 1, end: 2 },])); + } + + #[test] + fn insert_range_overlap_begin() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 1, end: 20 }]); + assert_eq!(interval_store.insert_range(5..=50), Interval::new_unchecked(21, 50).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 1, end: 50 },])); + } + + #[test] + fn insert_range_overlap_end() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 10, end: 20 }]); + assert_eq!(interval_store.insert_range(5..=15), Interval::new_unchecked(5, 9).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 5, end: 20 },])); + } + + #[test] + fn insert_range_overlap_begin_end() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 40, end: 60 }, + ]); + assert_eq!(interval_store.insert_range(15..=50), Interval::new_unchecked(21, 39).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 10, end: 60 },])); + } + + #[test] + fn insert_range_concescutive_begin() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 10, end: 20 },]); + assert_eq!(interval_store.insert_range(21..=50), Interval::new_unchecked(21, 50).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 10, end: 50 },])); + } + + #[test] + fn insert_range_concescutive_begin_overlap_end() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 40, end: 60 }, + ]); + assert_eq!(interval_store.insert_range(21..=50), Interval::new_unchecked(21, 39).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 10, end: 60 },])); + } + + #[test] + fn insert_range_concescutive_end() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 70 },]); + assert_eq!(interval_store.insert_range(21..=49), Interval::new_unchecked(21, 49).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 21, end: 70 },])); + } + + #[test] + fn insert_range_concescutive_begin_end() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + ]); + assert_eq!(interval_store.insert_range(21..=49), Interval::new_unchecked(21, 49).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 10, end: 70 },])); + } + + #[test] + fn insert_range_no_overlap() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + ]); + assert_eq!(interval_store.insert_range(25..=30), Interval::new_unchecked(25, 30).run_len()); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 25, end: 30 }, + Interval { start: 50, end: 70 }, + ]) + ); + } + + #[test] + fn insert_range_u16_max_no_overlap() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + ]); + assert_eq!( + interval_store.insert_range(90..=u16::MAX), + Interval::new_unchecked(90, u16::MAX).run_len() + ); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + Interval { start: 90, end: u16::MAX }, + ]) + ); + } + + #[test] + fn insert_range_u16_max_overlap_begin() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + ]); + assert_eq!( + interval_store.insert_range(70..=u16::MAX), + Interval::new_unchecked(71, u16::MAX).run_len() + ); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: u16::MAX }, + ]) + ); + } + + #[test] + fn insert_range_u16_max_overlap_all() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + ]); + assert_eq!( + interval_store.insert_range(0..=u16::MAX), + Interval::new_unchecked(0, u16::MAX).run_len() + - Interval::new_unchecked(10, 20).run_len() + - Interval::new_unchecked(50, 70).run_len() + ); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![Interval { start: 0, end: u16::MAX },]) + ); + } + + #[test] + fn insert_range_overlap_some() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 10, end: 20 }, + Interval { start: 50, end: 70 }, + Interval { start: 500, end: 700 }, + ]); + assert_eq!( + interval_store.insert_range(0..=100), + Interval::new_unchecked(0, 100).run_len() + - Interval::new_unchecked(10, 20).run_len() + - Interval::new_unchecked(50, 70).run_len() + ); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 0, end: 100 }, + Interval { start: 500, end: 700 }, + ]) + ); + } + + #[test] + fn insert_range_begin_overlap_concescutive_end() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(2, 10), + Interval::new_unchecked(12, 700), + ]); + assert_eq!(interval_store.insert_range(2..=11), 1); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval::new_unchecked(2, 700)])); + } + + #[test] + fn insert_range_pin_1() { + let mut interval_store = IntervalStore(alloc::vec![Interval::new_unchecked(65079, 65079)]); + assert_eq!(interval_store.insert_range(65080..=65080), 1); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![Interval::new_unchecked(65079, 65080)]) + ); + } + + #[test] + fn push_empty() { + let mut interval_store = IntervalStore(alloc::vec![]); + assert!(interval_store.push(80)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 80, end: 80 },])); + } + + #[test] + fn push_new_max() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 70 },]); + assert!(interval_store.push(80)); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 50, end: 70 }, + Interval { start: 80, end: 80 }, + ]) + ); + } + + #[test] + fn push_new_max_consecutive() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 70 },]); + assert!(interval_store.push(71)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 50, end: 71 },])); + } + + #[test] + fn push_existing() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 70 },]); + assert!(!interval_store.push(60)); + assert_eq!(interval_store, interval_store); + } + + #[test] + fn push_non_existing_non_max() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 70 },]); + assert!(!interval_store.push(10)); + assert_eq!(interval_store, interval_store); + } + + #[test] + fn push_existing_u16_max() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: u16::MAX },]); + assert!(!interval_store.push(u16::MAX)); + assert_eq!(interval_store, interval_store); + } + + #[test] + fn push_new_u16_max() { + let mut interval_store = + IntervalStore(alloc::vec![Interval { start: 50, end: u16::MAX - 1 },]); + assert!(interval_store.push(u16::MAX)); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![Interval { start: 50, end: u16::MAX },]) + ); + } + + #[test] + fn remove_end_of_interval() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 60 },]); + assert!(interval_store.remove(60)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 50, end: 59 },])); + } + + #[test] + fn remove_begin_of_interval() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 60 },]); + assert!(interval_store.remove(50)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 51, end: 60 },])); + } + + #[test] + fn remove_middle() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 1, end: 3 },]); + assert!(interval_store.remove(2)); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 1, end: 1 }, + Interval { start: 3, end: 3 }, + ]) + ); + } + + #[test] + fn remove_nothing() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 60 },]); + assert!(!interval_store.remove(90)); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 50, end: 60 },])); + } + + #[test] + fn remove_u16_max() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: u16::MAX },]); + assert!(interval_store.remove(u16::MAX)); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![Interval { start: 50, end: u16::MAX - 1 },]) + ); + } + + #[test] + fn remove_interval() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 50, end: 50 },]); + assert!(interval_store.remove(50)); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_exact_one() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + assert_eq!(interval_store.remove_range(40..=60), 21); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_one_with_extra_1() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + assert_eq!(interval_store.remove_range(40..=70), 21); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_one_with_extra_2() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 400, end: 600 }, + Interval { start: 4000, end: 6000 }, + ]); + assert_eq!(interval_store.remove_range(40..=70), 21); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval::new_unchecked(400, 600), + Interval::new_unchecked(4000, 6000), + ]) + ); + } + + #[test] + fn remove_range_exact_many() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 80, end: 90 }, + Interval { start: 100, end: 200 }, + ]); + assert_eq!( + interval_store.remove_range(40..=200), + Interval::new_unchecked(40, 60).run_len() + + Interval::new_unchecked(80, 90).run_len() + + Interval::new_unchecked(100, 200).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_begin_exact_overlap_end_one() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 70, end: 90 }, + ]); + assert_eq!( + interval_store.remove_range(40..=80), + Interval::new_unchecked(40, 60).run_len() + Interval::new_unchecked(70, 80).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 81, end: 90 },])); + } + + #[test] + fn remove_range_begin_overlap_end_exact_one() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 70, end: 90 }, + ]); + assert_eq!( + interval_store.remove_range(50..=90), + Interval::new_unchecked(70, 90).run_len() + Interval::new_unchecked(50, 60).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 40, end: 49 },])); + } + + #[test] + fn remove_range_begin_no_overlap_end_exact_one_1() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 70, end: 90 }, + ]); + assert_eq!( + interval_store.remove_range(30..=90), + Interval::new_unchecked(70, 90).run_len() + Interval::new_unchecked(40, 60).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_begin_no_overlap_end_exact_one_2() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 70, end: 90 }, + Interval { start: 700, end: 900 }, + ]); + assert_eq!( + interval_store.remove_range(30..=90), + Interval::new_unchecked(70, 90).run_len() + Interval::new_unchecked(40, 60).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval::new_unchecked(700, 900),])); + } + + #[test] + fn remove_range_both_overlap() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 70, end: 90 }, + ]); + assert_eq!( + interval_store.remove_range(50..=80), + Interval::new_unchecked(70, 80).run_len() + Interval::new_unchecked(50, 60).run_len() + ); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval { start: 40, end: 49 }, + Interval { start: 81, end: 90 }, + ]) + ); + } + + #[test] + fn remove_range_begin_overlap() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + assert_eq!( + interval_store.remove_range(50..=100), + Interval::new_unchecked(50, 60).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 40, end: 49 },])); + } + + #[test] + fn remove_range_begin_overlap_many() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 80, end: 100 }, + Interval { start: 200, end: 500 }, + ]); + assert_eq!( + interval_store.remove_range(50..=1000), + Interval::new_unchecked(50, 60).run_len() + + Interval::new_unchecked(80, 100).run_len() + + Interval::new_unchecked(200, 500).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 40, end: 49 },])); + } + + #[test] + fn remove_range_end_overlap() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + assert_eq!(interval_store.remove_range(20..=50), Interval::new_unchecked(40, 50).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 51, end: 60 },])); + } + + #[test] + fn remove_range_end_overlap_many() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 100, end: 500 }, + Interval { start: 800, end: 900 }, + ]); + assert_eq!( + interval_store.remove_range(20..=850), + Interval::new_unchecked(40, 60).run_len() + + Interval::new_unchecked(100, 500).run_len() + + Interval::new_unchecked(800, 850).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval { start: 851, end: 900 },])); + } + + #[test] + fn remove_range_no_overlap() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + assert_eq!(interval_store.remove_range(20..=80), Interval::new_unchecked(40, 60).run_len()); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_no_overlap_many() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 40, end: 60 }, + Interval { start: 400, end: 600 }, + Interval { start: 4000, end: 6000 }, + ]); + assert_eq!( + interval_store.remove_range(20..=60000), + Interval::new_unchecked(40, 60).run_len() + + Interval::new_unchecked(400, 600).run_len() + + Interval::new_unchecked(4000, 6000).run_len() + ); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_complete_overlap() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 51, end: 6000 },]); + assert_eq!( + interval_store.remove_range(500..=600), + Interval::new_unchecked(500, 600).run_len() + ); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval::new_unchecked(51, 499), + Interval::new_unchecked(601, 6000), + ]) + ); + } + + #[test] + fn remove_range_nothing() { + let mut interval_store = IntervalStore(alloc::vec![]); + assert_eq!(interval_store.remove_range(50000..=60000), 0); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_range_with_extra() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(38161, 38162), + Interval::new_unchecked(40562, 40562), + ]); + assert_eq!(interval_store.remove_range(38162..=38163), 1); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval::new_unchecked(38161, 38161), + Interval::new_unchecked(40562, 40562), + ]) + ); + } + + #[test] + fn remove_smallest_one() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + interval_store.remove_smallest(500); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_smallest_many_1() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 0, end: 99 }, + Interval { start: 400, end: 600 }, + Interval { start: 4000, end: 6000 }, + ]); + interval_store.remove_smallest(200); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval::new_unchecked(500, 600), + Interval::new_unchecked(4000, 6000), + ]) + ); + } + + #[test] + fn remove_smallest_many_2() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 0, end: 99 }, + Interval { start: 400, end: 599 }, + Interval { start: 4000, end: 6000 }, + ]); + interval_store.remove_smallest(500); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![Interval::new_unchecked(4200, 6000),]) + ); + } + + #[test] + fn remove_biggest_one() { + let mut interval_store = IntervalStore(alloc::vec![Interval { start: 40, end: 60 },]); + interval_store.remove_biggest(500); + assert_eq!(interval_store, IntervalStore(alloc::vec![])); + } + + #[test] + fn remove_biggest_many_1() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 0, end: 99 }, + Interval { start: 400, end: 600 }, + Interval { start: 5901, end: 6000 }, + ]); + interval_store.remove_biggest(200); + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 99), + Interval::new_unchecked(400, 500), + ]) + ); + } + + #[test] + fn remove_biggest_many_2() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 1, end: 6000 }, + Interval { start: 8401, end: 8600 }, + Interval { start: 9901, end: 10000 }, + ]); + interval_store.remove_biggest(500); + assert_eq!(interval_store, IntervalStore(alloc::vec![Interval::new_unchecked(1, 5800),])); + } + + #[test] + fn contains_index_1() { + let interval_store = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(interval_store.contains(5)); + assert!(interval_store.contains(16000)); + } + + #[test] + fn contains_index_2() { + let interval_store = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(!interval_store.contains(0)); + } + + #[test] + fn contains_range_1() { + let interval_store = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(interval_store.contains_range(1..=500)); + } + + #[test] + fn contains_range_2() { + let interval_store = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(!interval_store.contains_range(1..=1500)); + } + + #[test] + fn contains_range_3() { + let interval_store = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(interval_store.contains_range(1..=1)); + } + + #[test] + fn is_disjoint_1() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + let interval_store_2 = IntervalStore(alloc::vec![Interval { start: 601, end: 1200 },]); + assert!(!interval_store_1.is_disjoint(&interval_store_1)); + assert!(!interval_store_2.is_disjoint(&interval_store_2)); + assert!(interval_store_1.is_disjoint(&interval_store_2)); + assert!(interval_store_2.is_disjoint(&interval_store_1)); + } + + #[test] + fn is_disjoint_2() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + let interval_store_2 = IntervalStore(alloc::vec![Interval { start: 600, end: 1200 },]); + assert!(!interval_store_1.is_disjoint(&interval_store_1)); + assert!(!interval_store_2.is_disjoint(&interval_store_2)); + assert!(!interval_store_1.is_disjoint(&interval_store_2)); + assert!(!interval_store_2.is_disjoint(&interval_store_1)); + } + + #[test] + fn is_disjoint_3() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + let interval_store_2 = IntervalStore(alloc::vec![Interval { start: 15800, end: 15905 },]); + assert!(!interval_store_1.is_disjoint(&interval_store_1)); + assert!(!interval_store_2.is_disjoint(&interval_store_2)); + assert!(!interval_store_1.is_disjoint(&interval_store_2)); + assert!(!interval_store_2.is_disjoint(&interval_store_1)); + } + + #[test] + fn is_disjoint_array_store_1() { + let array_store = ArrayStore::from_vec_unchecked(alloc::vec![0, 60, 200, 500,]); + let interval_store = IntervalStore(alloc::vec![Interval { start: 70, end: 199 },]); + assert!(interval_store.is_disjoint_array(&array_store)); + } + + #[test] + fn is_disjoint_array_store_2() { + let array_store = ArrayStore::from_vec_unchecked(alloc::vec![0, 60, 200, 500,]); + let interval_store = IntervalStore(alloc::vec![Interval { start: 1, end: 400 },]); + assert!(!interval_store.is_disjoint_array(&array_store)); + } + + #[test] + fn is_disjoint_bitmap_store_1() { + let mut bitmap_store = BitmapStore::new(); + for to_set in [500, 5001, 20, 40] { + bitmap_store.insert(to_set); + } + let interval_store = IntervalStore(alloc::vec![ + Interval { start: 1000, end: 4000 }, + Interval { start: 8000, end: 10000 }, + ]); + assert!(interval_store.is_disjoint_bitmap(&bitmap_store)); + } + + #[test] + fn is_disjoint_bitmap_store_2() { + let mut bitmap_store = BitmapStore::new(); + for to_set in [500, 5001, 20, 40] { + bitmap_store.insert(to_set); + } + let interval_store = IntervalStore(alloc::vec![Interval { start: 1, end: 400 },]); + assert!(!interval_store.is_disjoint_bitmap(&bitmap_store)); + } + + #[test] + fn is_subset_1() { + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 1500, end: 1600 },]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(interval_store_1.is_subset(&interval_store_1)); + assert!(interval_store_2.is_subset(&interval_store_2)); + assert!(interval_store_1.is_subset(&interval_store_2)); + assert!(!interval_store_2.is_subset(&interval_store_1)); + } + + #[test] + fn is_subset_2() { + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 50, end: 700 },]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 600 }, + Interval { start: 1401, end: 1600 }, + Interval { start: 15901, end: 16000 }, + ]); + assert!(interval_store_1.is_subset(&interval_store_1)); + assert!(interval_store_2.is_subset(&interval_store_2)); + assert!(!interval_store_1.is_subset(&interval_store_2)); + assert!(!interval_store_2.is_subset(&interval_store_1)); + } + + #[test] + fn overlapping_interval_1() { + let interval1 = Interval::new_unchecked(0, 100); + let interval2 = Interval::new_unchecked(50, 300); + + assert_eq!( + interval1.overlapping_interval(&interval2), + Some(Interval::new_unchecked(50, 100)) + ) + } + + #[test] + fn overlapping_interval_2() { + let interval1 = Interval::new_unchecked(50, 300); + let interval2 = Interval::new_unchecked(0, 100); + + assert_eq!( + interval1.overlapping_interval(&interval2), + Some(Interval::new_unchecked(50, 100)) + ) + } + + #[test] + fn overlapping_interval_3() { + let interval1 = Interval::new_unchecked(0, 100); + let interval2 = Interval::new_unchecked(500, 700); + + assert_eq!(interval1.overlapping_interval(&interval2), None) + } + + #[test] + fn intersection_len_1() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 11, end: 20 }, + Interval { start: 51, end: 80 }, + Interval { start: 111, end: 120 }, + ]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 20 }, + Interval { start: 41, end: 80 }, + Interval { start: 101, end: 120 }, + ]); + assert_eq!( + interval_store_1.intersection_len(&interval_store_2), + Interval::new_unchecked(11, 20).run_len() + + Interval::new_unchecked(51, 80).run_len() + + Interval::new_unchecked(111, 120).run_len() + ) + } + + #[test] + fn intersection_len_2() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 11, end: 20 }, + Interval { start: 51, end: 80 }, + Interval { start: 111, end: 120 }, + ]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval { start: 1, end: 80 }, + Interval { start: 101, end: 120 }, + ]); + let intersect_len = Interval::new_unchecked(11, 20).run_len() + + Interval::new_unchecked(51, 80).run_len() + + Interval::new_unchecked(111, 120).run_len(); + assert_eq!(interval_store_1.intersection_len(&interval_store_2), intersect_len); + assert_eq!(interval_store_2.intersection_len(&interval_store_1), intersect_len); + } + + #[test] + fn intersection_len_3() { + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 1, end: 2000 },]); + let interval_store_2 = IntervalStore(alloc::vec![Interval { start: 1001, end: 3000 },]); + let intersect_len = Interval::new_unchecked(1001, 2000).run_len(); + assert_eq!(interval_store_1.intersection_len(&interval_store_2), intersect_len); + assert_eq!(interval_store_2.intersection_len(&interval_store_1), intersect_len); + } + + #[test] + fn intersection_len_bitmap_1() { + let mut bitmap_store = BitmapStore::new(); + for to_set in [500, 5001, 20, 40, 60] { + bitmap_store.insert(to_set); + } + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 20, end: 600 },]); + let intersect_len = 4; + assert_eq!(interval_store_1.intersection_len_bitmap(&bitmap_store), intersect_len); + } + + #[test] + fn intersection_len_bitmap_2() { + let mut bitmap_store = BitmapStore::new(); + for to_set in 0..=200 { + bitmap_store.insert(to_set); + } + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 20, end: 600 },]); + let intersect_len = Interval::new_unchecked(20, 200).run_len(); + assert_eq!(interval_store_1.intersection_len_bitmap(&bitmap_store), intersect_len); + } + + #[test] + fn intersection_len_bitmap_3() { + let mut bitmap_store = BitmapStore::new(); + for to_set in 0..=20000 { + bitmap_store.insert(to_set); + } + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 20, end: 6000 }, + Interval { start: 5000, end: 33333 }, + ]); + let intersect_len = Interval::new_unchecked(20, 6000).run_len() + + Interval::new_unchecked(5000, 20000).run_len(); + assert_eq!(interval_store_1.intersection_len_bitmap(&bitmap_store), intersect_len); + } + + #[test] + fn intersection_len_bitmap_4() { + let mut bitmap_store = BitmapStore::new(); + for to_set in 0..=20000 { + bitmap_store.insert(to_set); + } + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 64, end: 6400 }, + Interval { start: 7680, end: 64000 }, + ]); + let intersect_len = Interval::new_unchecked(64, 6400).run_len() + + Interval::new_unchecked(7680, 20000).run_len(); + assert_eq!(interval_store_1.intersection_len_bitmap(&bitmap_store), intersect_len); + } + + #[test] + fn intersection_len_bitmap_5() { + let mut bitmap_store = BitmapStore::new(); + for to_set in 0..=20005 { + bitmap_store.insert(to_set); + } + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 64, end: 6400 }, + Interval { start: 7680, end: 64000 }, + ]); + let intersect_len = Interval::new_unchecked(64, 6400).run_len() + + Interval::new_unchecked(7680, 20005).run_len(); + assert_eq!(interval_store_1.intersection_len_bitmap(&bitmap_store), intersect_len); + } + + #[test] + fn intersection_len_bitmap_6() { + let mut bitmap_store = BitmapStore::new(); + for to_set in 0..=20005 { + bitmap_store.insert(to_set); + } + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 64, end: 64 },]); + let intersect_len = Interval::new_unchecked(64, 64).run_len(); + assert_eq!(interval_store_1.intersection_len_bitmap(&bitmap_store), intersect_len); + } + + #[test] + fn intersection_len_array_1() { + let array_store = ArrayStore::from_vec_unchecked(alloc::vec![20, 40, 60, 500, 5001]); + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 20, end: 600 },]); + let intersect_len = 4; + assert_eq!(interval_store_1.intersection_len_array(&array_store), intersect_len); + } + + #[test] + fn intersection_len_array_2() { + let array_store = ArrayStore::from_vec_unchecked(Vec::from_iter(0..200)); + let interval_store_1 = IntervalStore(alloc::vec![Interval { start: 20, end: 600 },]); + let intersect_len = 200 - 20; + assert_eq!(interval_store_1.intersection_len_array(&array_store), intersect_len); + } + + #[test] + fn len_1() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval { start: 20, end: 600 }, + Interval { start: 5000, end: 8000 }, + ]); + assert_eq!( + interval_store_1.len(), + Interval::new_unchecked(20, 600).run_len() + + Interval::new_unchecked(5000, 8000).run_len() + ); + } + + #[test] + fn is_empty() { + let mut interval_store = IntervalStore(alloc::vec![ + Interval { start: 20, end: 600 }, + Interval { start: 5000, end: 8000 }, + ]); + assert!(!interval_store.is_empty()); + interval_store.remove_range(0..=u16::MAX); + assert!(interval_store.is_empty()); + } + + #[test] + fn min_0() { + let interval_store = IntervalStore(alloc::vec![Interval::new_unchecked(20, u16::MAX)]); + assert_eq!(interval_store.min(), Some(20)); + } + + #[test] + fn min_1() { + let interval_store = IntervalStore(alloc::vec![]); + assert_eq!(interval_store.min(), None); + } + + #[test] + fn max_0() { + let interval_store = IntervalStore(alloc::vec![Interval::new_unchecked(20, u16::MAX)]); + assert_eq!(interval_store.max(), Some(u16::MAX)); + } + + #[test] + fn max_1() { + let interval_store = IntervalStore(alloc::vec![]); + assert_eq!(interval_store.max(), None); + } + + #[test] + fn rank() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 200), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + ]); + assert_eq!( + interval_store.rank(5020), + Interval::new_unchecked(0, 200).run_len() + + Interval::new_unchecked(5000, 5020).run_len() + ); + assert_eq!(interval_store.rank(u16::MAX), interval_store.len()); + } + + #[test] + fn select() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + ]); + assert_eq!(interval_store.select(0), Some(0)); + assert_eq!(interval_store.select(1), Some(2)); + assert_eq!(interval_store.select(10), Some(11)); + assert_eq!(interval_store.select(11), Some(5000)); + assert_eq!(interval_store.select(11 + 3), Some(5003)); + assert_eq!(interval_store.select(11 + 2001), Some(8000)); + } + + #[test] + fn union_1() { + let mut interval_store_1 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + ]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 10), + Interval::new_unchecked(12, 7000), + Interval::new_unchecked(65000, 65050), + ]); + interval_store_1 |= interval_store_2; + assert_eq!( + interval_store_1, + IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 7000), + Interval::new_unchecked(8000, 10000), + Interval::new_unchecked(65000, 65050), + ]) + ) + } + + #[test] + fn union_array() { + let mut values = alloc::vec![0, 1, 2, 3, 4, 2000, 5000, u16::MAX]; + values.sort(); + let array = ArrayStore::from_vec_unchecked(values); + let mut interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + ]); + interval_store |= &array; + assert_eq!( + interval_store, + IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 11), + Interval::new_unchecked(2000, 2000), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + Interval::new_unchecked(u16::MAX, u16::MAX), + ]) + ) + } + + #[test] + fn intersection() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + ]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(5, 50), + Interval::new_unchecked(4000, 10000), + ]); + assert_eq!( + &interval_store_1 & &interval_store_2, + IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(5, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 10000), + ]) + ); + assert_eq!(&interval_store_1 & &interval_store_1, interval_store_1); + } + + #[test] + fn difference() { + let mut interval_store_1 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 11000), + ]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(5, 50), + Interval::new_unchecked(4000, 10000), + ]); + interval_store_1 -= &interval_store_2; + assert_eq!( + interval_store_1, + IntervalStore(alloc::vec![ + Interval::new_unchecked(2, 4), + Interval::new_unchecked(10001, 11000), + ]) + ) + } + + #[test] + fn symmetric_difference_0() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(2, 11), + Interval::new_unchecked(5000, 7000), + Interval::new_unchecked(8000, 11000), + Interval::new_unchecked(40000, 50000), + ]); + let interval_store_2 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 0), + Interval::new_unchecked(5, 50), + Interval::new_unchecked(4000, 10000), + ]); + assert_eq!( + &interval_store_1 ^ &interval_store_2, + IntervalStore(alloc::vec![ + Interval::new_unchecked(2, 4), + Interval::new_unchecked(12, 50), + Interval::new_unchecked(4000, 4999), + Interval::new_unchecked(7001, 7999), + Interval::new_unchecked(10001, 11000), + Interval::new_unchecked(40000, 50000), + ]) + ); + } + + #[test] + fn symmetric_difference_1() { + let interval_store_1 = IntervalStore(alloc::vec![Interval::new_unchecked(0, 50),]); + let interval_store_2 = IntervalStore(alloc::vec![Interval::new_unchecked(100, 200),]); + assert_eq!( + &interval_store_1 ^ &interval_store_2, + IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(100, 200), + ]) + ); + } + + #[test] + fn symmetric_difference_2() { + let interval_store_1 = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let interval_store_2 = IntervalStore(alloc::vec![Interval::new_unchecked(0, 6000),]); + assert_eq!( + &interval_store_1 ^ &interval_store_2, + IntervalStore(alloc::vec![ + Interval::new_unchecked(51, 499), + Interval::new_unchecked(601, 799), + Interval::new_unchecked(1001, 6000), + ]) + ); + } + + #[test] + fn iter_next() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let mut iter = interval_store.into_iter(); + + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next() { + assert_eq!(i, value as usize); + i += 1; + if i >= 51 { + break; + } + let size = (Interval::new_unchecked(i as u16, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let size = (Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next() { + assert_eq!(i + 500, value as usize); + i += 1; + if i >= 101 { + break; + } + let size = (Interval::new_unchecked((i + 500) as u16, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let size = Interval::new_unchecked(800, 1000).run_len() as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next() { + if i >= 201 { + break; + } + assert_eq!(i + 800, value as usize); + i += 1; + if i >= 201 { + break; + } + let size = (Interval::new_unchecked((i + 800) as u16, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + + assert!(iter.next().is_none()); + assert!(iter.next_back().is_none()); + } + + #[test] + fn iter_next_back() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let mut iter = interval_store.into_iter(); + + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next_back() { + assert_eq!(1000 - i, value as usize); + i += 1; + if i >= 201 { + break; + } + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, (1000 - i) as u16).run_len()) + as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let mut i = 0; + while let Some(value) = iter.next_back() { + assert_eq!(600 - i, value as usize); + i += 1; + if i >= 101 { + break; + } + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, (600 - i) as u16).run_len()) + as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let mut i = 0; + while let Some(value) = iter.next_back() { + assert_eq!(50 - i, value as usize); + i += 1; + if i >= 51 { + break; + } + let size = (Interval::new_unchecked(0, (50 - i) as u16).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert!(iter.next().is_none()); + assert!(iter.next_back().is_none()); + } + + #[test] + fn iter_next_and_next_back() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let mut iter = interval_store.into_iter(); + + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next_back() { + assert_eq!(1000 - i, value as usize); + i += 1; + if i >= 201 { + break; + } + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, (1000 - i) as u16).run_len()) + as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next_back() { + assert_eq!(600 - i, value as usize); + i += 1; + if i >= 101 { + break; + } + let size = (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, (600 - i) as u16).run_len()) + as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let size = (Interval::new_unchecked(0, 50).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + + let mut i = 0; + while let Some(value) = iter.next() { + assert_eq!(i, value as usize); + i += 1; + if i >= 51 { + break; + } + let size = (Interval::new_unchecked(i as u16, 50).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert!(iter.next().is_none()); + assert!(iter.next_back().is_none()); + } + + #[test] + fn iter_u16_max() { + let interval_store = IntervalStore(alloc::vec![Interval::new_unchecked(0, u16::MAX),]); + let mut iter = interval_store.iter(); + + let mut i = 0; + while let Some(value) = iter.next() { + assert_eq!(i, value as usize); + i += 1; + if i >= u16::MAX as usize { + break; + } + let size = (Interval::new_unchecked(i as u16, u16::MAX).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + + let mut iter = interval_store.iter(); + + let mut i = 0; + while let Some(value) = iter.next_back() { + assert_eq!(u16::MAX as usize - i, value as usize); + i += 1; + if i >= u16::MAX as usize { + break; + } + let size = (Interval::new_unchecked(0, u16::MAX - i as u16).run_len()) as usize; + assert_eq!(iter.size_hint(), (size, Some(size))); + } + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(u16::MAX as usize), Some(u16::MAX)); + } + + #[test] + fn iter_nth() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(50), Some(50)); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(51), Some(500)); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(100), Some(549)); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(152), Some(800)); + + let mut iter = interval_store.iter(); + assert_eq!( + iter.nth( + (Interval::new_unchecked(0, 50).run_len() + + Interval::new_unchecked(500, 600).run_len() + + Interval::new_unchecked(800, 1000).run_len() + - 1) as usize + ), + Some(1000) + ); + + let mut iter = interval_store.iter(); + iter.next(); + iter.next(); + iter.next(); + assert_eq!(iter.nth(152), Some(803)); + + let mut iter = interval_store.iter(); + assert_eq!(iter.nth(u16::MAX as usize), None); + } + + #[test] + fn iter_advance_to() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let mut iter = interval_store.iter(); + iter.advance_to(20); + assert_eq!(iter.next(), Some(20)); + iter.advance_to(800); + assert_eq!(iter.next(), Some(800)); + iter.advance_to(u16::MAX); + assert_eq!(iter.next(), None); + + let mut iter = interval_store.iter(); + iter.advance_to(100); + assert_eq!(iter.next(), Some(500)); + iter.advance_to(800); + assert_eq!(iter.next(), Some(800)); + iter.advance_to(900); + assert_eq!(iter.next(), Some(900)); + iter.advance_to(800); + assert_eq!(iter.next(), Some(901)); + let mut iter = interval_store.iter(); + iter.next(); + iter.next(); + iter.next(); + iter.advance_to(499); + assert_eq!(iter.next(), Some(500)); + + let mut iter = interval_store.iter(); + iter.advance_to(100); + assert_eq!(iter.next(), Some(500)); + } + + #[test] + fn iter_advance_back_to() { + let interval_store = IntervalStore(alloc::vec![ + Interval::new_unchecked(0, 50), + Interval::new_unchecked(500, 600), + Interval::new_unchecked(800, 1000), + ]); + let mut iter = interval_store.iter(); + iter.advance_back_to(u16::MAX); + assert_eq!(iter.next_back(), Some(1000)); + iter.advance_back_to(800); + assert_eq!(iter.next_back(), Some(800)); + iter.advance_back_to(20); + assert_eq!(iter.next_back(), Some(20)); + + let mut iter = interval_store.iter(); + iter.advance_back_to(800); + assert_eq!(iter.next_back(), Some(800)); + iter.advance_back_to(900); + assert_eq!(iter.next_back(), Some(600)); + iter.advance_back_to(550); + assert_eq!(iter.next_back(), Some(550)); + iter.advance_back_to(20); + assert_eq!(iter.next_back(), Some(20)); + let mut iter = interval_store.iter(); + iter.next_back(); + iter.next_back(); + iter.next_back(); + iter.advance_back_to(700); + assert_eq!(iter.next_back(), Some(600)); + let mut iter = interval_store.iter(); + iter.advance_back_to(400); + assert_eq!(iter.next_back(), Some(50)); + } +} diff --git a/vendor/roaring/src/bitmap/store/mod.rs b/vendor/roaring/src/bitmap/store/mod.rs new file mode 100644 index 0000000..1b62e0e --- /dev/null +++ b/vendor/roaring/src/bitmap/store/mod.rs @@ -0,0 +1,1050 @@ +mod array_store; +mod bitmap_store; +mod interval_store; + +use alloc::vec; +use core::mem; +use core::ops::{ + BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, RangeInclusive, Sub, SubAssign, +}; +use core::slice; + +pub use self::bitmap_store::{BITMAP_BYTES, BITMAP_LENGTH}; +use self::Store::{Array, Bitmap, Run}; + +pub(crate) use self::array_store::ArrayStore; +pub use self::bitmap_store::{BitmapIter, BitmapStore}; +pub(crate) use self::interval_store::Interval; +pub(crate) use interval_store::{IntervalStore, RunIterBorrowed, RunIterOwned}; +#[cfg(feature = "std")] +pub(crate) use interval_store::{RUN_ELEMENT_BYTES, RUN_NUM_BYTES}; + +use crate::bitmap::container::ARRAY_LIMIT; + +#[cfg(not(feature = "std"))] +use alloc::boxed::Box; + +#[derive(Clone, Eq)] +pub(crate) enum Store { + Array(ArrayStore), + Bitmap(BitmapStore), + Run(IntervalStore), +} + +#[derive(Clone)] +pub(crate) enum Iter<'a> { + Array(slice::Iter<'a, u16>), + Vec(vec::IntoIter), + BitmapBorrowed(BitmapIter<&'a [u64; BITMAP_LENGTH]>), + BitmapOwned(BitmapIter>), + RunBorrowed(RunIterBorrowed<'a>), + RunOwned(RunIterOwned), +} + +impl Store { + pub fn new() -> Store { + Store::Array(ArrayStore::new()) + } + + #[cfg(feature = "std")] + pub fn with_capacity(capacity: usize) -> Store { + if capacity <= ARRAY_LIMIT as usize { + Store::Array(ArrayStore::with_capacity(capacity)) + } else { + Store::Bitmap(BitmapStore::new()) + } + } + + pub fn full() -> Store { + Store::Run(IntervalStore::full()) + } + + pub fn from_lsb0_bytes(bytes: &[u8], byte_offset: usize) -> Option { + assert!(byte_offset + bytes.len() <= BITMAP_LENGTH * mem::size_of::()); + + // It seems to be pretty considerably faster to count the bits + // using u64s than for each byte + let bits_set = { + let mut bits_set = 0; + let chunks = bytes.chunks_exact(mem::size_of::()); + let remainder = chunks.remainder(); + for chunk in chunks { + let chunk = u64::from_ne_bytes(chunk.try_into().unwrap()); + bits_set += u64::from(chunk.count_ones()); + } + for byte in remainder { + bits_set += u64::from(byte.count_ones()); + } + bits_set + }; + if bits_set == 0 { + return None; + } + + Some(if bits_set < ARRAY_LIMIT { + Array(ArrayStore::from_lsb0_bytes(bytes, byte_offset, bits_set)) + } else { + Bitmap(BitmapStore::from_lsb0_bytes_unchecked(bytes, byte_offset, bits_set)) + }) + } + + #[inline] + pub fn insert(&mut self, index: u16) -> bool { + match self { + Array(vec) => vec.insert(index), + Bitmap(bits) => bits.insert(index), + Run(runs) => runs.insert(index), + } + } + + pub fn insert_range(&mut self, range: RangeInclusive) -> u64 { + // A Range is defined as being of size 0 if start >= end. + if range.is_empty() { + return 0; + } + + match self { + Array(vec) => vec.insert_range(range), + Bitmap(bits) => bits.insert_range(range), + Run(runs) => runs.insert_range(range), + } + } + + /// Push `index` at the end of the store only if `index` is the new max. + /// + /// Returns whether `index` was effectively pushed. + pub fn push(&mut self, index: u16) -> bool { + match self { + Array(vec) => vec.push(index), + Bitmap(bits) => bits.push(index), + Run(runs) => runs.push(index), + } + } + + /// + /// Pushes `index` at the end of the store. + /// It is up to the caller to have validated index > self.max() + /// + /// # Panics + /// + /// If debug_assertions enabled and index is > self.max() + pub(crate) fn push_unchecked(&mut self, index: u16) { + match self { + Array(vec) => vec.push_unchecked(index), + Bitmap(bits) => bits.push_unchecked(index), + Run(runs) => { + // push unchecked for intervals doesn't make sense since we have to check anyways to + // intervals and such when the index is consecutive + debug_assert!(runs.max().map(|f| f < index).unwrap_or(true)); + runs.push(index); + } + } + } + + pub fn remove(&mut self, index: u16) -> bool { + match self { + Array(vec) => vec.remove(index), + Bitmap(bits) => bits.remove(index), + Run(runs) => runs.remove(index), + } + } + + pub fn remove_range(&mut self, range: RangeInclusive) -> u64 { + if range.is_empty() { + return 0; + } + + match self { + Array(vec) => vec.remove_range(range), + Bitmap(bits) => bits.remove_range(range), + Run(runs) => runs.remove_range(range), + } + } + + pub fn remove_smallest(&mut self, index: u64) { + match self { + Array(vec) => vec.remove_smallest(index), + Bitmap(bits) => bits.remove_smallest(index), + Run(runs) => runs.remove_smallest(index), + } + } + + pub fn remove_biggest(&mut self, index: u64) { + match self { + Array(vec) => vec.remove_biggest(index), + Bitmap(bits) => bits.remove_biggest(index), + Run(runs) => runs.remove_biggest(index), + } + } + + pub fn contains(&self, index: u16) -> bool { + match self { + Array(vec) => vec.contains(index), + Bitmap(bits) => bits.contains(index), + Run(intervals) => intervals.contains(index), + } + } + + pub fn contains_range(&self, range: RangeInclusive) -> bool { + match self { + Array(vec) => vec.contains_range(range), + Bitmap(bits) => bits.contains_range(range), + Run(runs) => runs.contains_range(range), + } + } + + pub fn is_full(&self) -> bool { + self.len() == (1 << 16) + } + + pub fn is_disjoint(&self, other: &Self) -> bool { + match (self, other) { + (Array(vec1), Array(vec2)) => vec1.is_disjoint(vec2), + (Bitmap(bits1), Bitmap(bits2)) => bits1.is_disjoint(bits2), + (Array(vec), Bitmap(bits)) | (Bitmap(bits), Array(vec)) => { + vec.iter().all(|&i| !bits.contains(i)) + } + (Run(intervals1), Run(intervals2)) => intervals1.is_disjoint(intervals2), + (Run(runs), Array(vec)) | (Array(vec), Run(runs)) => runs.is_disjoint_array(vec), + (Run(intervals), Bitmap(bitmap)) | (Bitmap(bitmap), Run(intervals)) => { + intervals.is_disjoint_bitmap(bitmap) + } + } + } + + pub fn is_subset(&self, other: &Self) -> bool { + match (self, other) { + (Array(vec1), Array(vec2)) => vec1.is_subset(vec2), + (Bitmap(bits1), Bitmap(bits2)) => bits1.is_subset(bits2), + (Array(vec), Bitmap(bits)) => vec.iter().all(|&i| bits.contains(i)), + (Bitmap(..), &Array(..)) => false, + (Array(vec), Run(runs)) => vec.iter().all(|&i| runs.contains(i)), + (Bitmap(bitmap), Run(runs)) => bitmap.iter().all(|i| runs.contains(i)), + (Run(intervals1), Run(intervals2)) => intervals1.is_subset(intervals2), + (Run(intervals), Array(vec)) => intervals.is_subset_array(vec), + (Run(intervals), Bitmap(bitmap)) => intervals.is_subset_bitmap(bitmap), + } + } + + pub fn intersection_len(&self, other: &Self) -> u64 { + match (self, other) { + (Array(vec1), Array(vec2)) => vec1.intersection_len(vec2), + (Bitmap(bits1), Bitmap(bits2)) => bits1.intersection_len_bitmap(bits2), + (Array(vec), Bitmap(bits)) => bits.intersection_len_array(vec), + (Bitmap(bits), Array(vec)) => bits.intersection_len_array(vec), + (Run(runs), Array(vec)) | (Array(vec), Run(runs)) => runs.intersection_len_array(vec), + (Run(runs), Bitmap(bitmap)) | (Bitmap(bitmap), Run(runs)) => { + runs.intersection_len_bitmap(bitmap) + } + (Run(runs1), Run(runs2)) => runs1.intersection_len(runs2), + } + } + + pub fn len(&self) -> u64 { + match self { + Array(vec) => vec.len(), + Bitmap(bits) => bits.len(), + Run(intervals) => intervals.len(), + } + } + + pub fn is_empty(&self) -> bool { + match self { + Array(vec) => vec.is_empty(), + Bitmap(bits) => bits.is_empty(), + Run(runs) => runs.is_empty(), + } + } + + pub fn min(&self) -> Option { + match self { + Array(vec) => vec.min(), + Bitmap(bits) => bits.min(), + Run(runs) => runs.min(), + } + } + + #[inline] + pub fn max(&self) -> Option { + match self { + Array(vec) => vec.max(), + Bitmap(bits) => bits.max(), + Run(runs) => runs.max(), + } + } + + pub fn rank(&self, index: u16) -> u64 { + match self { + Array(vec) => vec.rank(index), + Bitmap(bits) => bits.rank(index), + Run(runs) => runs.rank(index), + } + } + + pub fn select(&self, n: u16) -> Option { + match self { + Array(vec) => vec.select(n), + Bitmap(bits) => bits.select(n), + Run(runs) => runs.select(n), + } + } + + pub fn count_runs(&self) -> u64 { + match self { + Array(vec) => { + vec.iter() + .fold((-2, 0u64), |(prev, runs), &v| { + let new = v as i32; + if prev + 1 != new { + (new, runs + 1) + } else { + (new, runs) + } + }) + .1 + } + Bitmap(bits) => { + let mut num_runs = 0u64; + + for i in 0..BITMAP_LENGTH - 1 { + let word = bits.as_array()[i]; + let next_word = bits.as_array()[i + 1]; + num_runs += + ((word << 1) & !word).count_ones() as u64 + ((word >> 63) & !next_word); + } + + let last = bits.as_array()[BITMAP_LENGTH - 1]; + num_runs += ((last << 1) & !last).count_ones() as u64 + (last >> 63); + num_runs + } + Run(intervals) => intervals.run_amount(), + } + } + + pub(crate) fn to_bitmap(&self) -> Store { + match self { + Array(arr) => Bitmap(arr.to_bitmap_store()), + Bitmap(_) => self.clone(), + Run(intervals) => Bitmap(intervals.to_bitmap()), + } + } + + pub(crate) fn to_run(&self) -> Self { + match self { + Array(vec) => { + let mut intervals = IntervalStore::new(); + if let Some(mut start) = vec.as_slice().first().copied() { + for (idx, &v) in vec.as_slice()[1..].iter().enumerate() { + // subtract current and previous values, then check if the gap is too large + // for a run + if v - vec.as_slice()[idx] > 1 { + intervals.push_interval_unchecked(Interval::new_unchecked( + start, + vec.as_slice()[idx], + )); + start = v + } + } + intervals.push_interval_unchecked(Interval::new_unchecked( + start, + *vec.as_slice().last().unwrap(), + )); + } + Run(intervals) + } + Bitmap(bits) => { + let mut current = bits.as_array()[0]; + let mut i = 0u16; + let mut start; + let mut last; + + let mut intervals = IntervalStore::new(); + + loop { + // Skip over empty words + while current == 0 && i < BITMAP_LENGTH as u16 - 1 { + i += 1; + current = bits.as_array()[i as usize]; + } + // Reached end of the bitmap without finding anymore bits set + if current == 0 { + break; + } + let current_start = current.trailing_zeros() as u16; + start = 64 * i + current_start; + + // Pad LSBs with 1s + current |= current - 1; + + // Find next 0 + while current == u64::MAX && i < BITMAP_LENGTH as u16 - 1 { + i += 1; + current = bits.as_array()[i as usize]; + } + + // Run continues until end of this container + if current == u64::MAX { + intervals.push_interval_unchecked(Interval::new_unchecked(start, u16::MAX)); + break; + } + + let current_last = (!current).trailing_zeros() as u16; + last = 64 * i + current_last; + intervals.push_interval_unchecked(Interval::new_unchecked(start, last - 1)); + + // pad LSBs with 0s + current &= current + 1; + } + Run(intervals) + } + Run(intervals) => Run(intervals.clone()), + } + } + + pub(crate) fn internal_validate(&self) -> Result<(), &'static str> { + match self { + Array(vec) => vec.internal_validate(), + Bitmap(bits) => bits.internal_validate(), + Run(runs) => runs.internal_validate(), + } + } +} + +impl Default for Store { + fn default() -> Self { + Store::new() + } +} + +impl BitOr<&Store> for &Store { + type Output = Store; + + fn bitor(self, rhs: &Store) -> Store { + match (self, rhs) { + (Array(vec1), Array(vec2)) => Array(BitOr::bitor(vec1, vec2)), + (&Bitmap(..), &Array(..)) => { + let mut lhs = self.clone(); + BitOrAssign::bitor_assign(&mut lhs, rhs); + lhs + } + (&Bitmap(..), &Bitmap(..)) => { + let mut lhs = self.clone(); + BitOrAssign::bitor_assign(&mut lhs, rhs); + lhs + } + (&Array(..), &Bitmap(..)) => { + let mut rhs = rhs.clone(); + BitOrAssign::bitor_assign(&mut rhs, self); + rhs + } + (Run(left), Run(right)) => { + let (smallest, biggest) = if left.run_amount() > right.run_amount() { + (right, left) + } else { + (left, right) + }; + let mut res = biggest.clone(); + BitOrAssign::bitor_assign(&mut res, smallest); + Run(res) + } + (Run(runs), Array(array)) | (Array(array), Run(runs)) => { + let mut ret = runs.clone(); + BitOrAssign::bitor_assign(&mut ret, array); + Run(ret) + } + (Run(runs), Bitmap(bitmap)) | (Bitmap(bitmap), Run(runs)) => { + let mut ret = runs.to_bitmap(); + BitOrAssign::bitor_assign(&mut ret, bitmap); + Bitmap(ret) + } + } + } +} + +impl BitOrAssign for Store { + fn bitor_assign(&mut self, rhs: Store) { + match (self, rhs) { + (&mut Array(ref mut vec1), Array(ref vec2)) => { + *vec1 = BitOr::bitor(&*vec1, vec2); + } + (&mut Bitmap(ref mut bits1), Array(ref vec2)) => { + BitOrAssign::bitor_assign(bits1, vec2); + } + (&mut Bitmap(ref mut bits1), Bitmap(ref bits2)) => { + BitOrAssign::bitor_assign(bits1, bits2); + } + (this @ &mut Bitmap(..), rhs @ Run(..)) => { + let other = rhs.to_bitmap(); + BitOrAssign::bitor_assign(this, other); + } + (Run(intervals1), Run(intervals2)) => BitOrAssign::bitor_assign(intervals1, intervals2), + (Run(intervals1), Array(ref vec)) => BitOrAssign::bitor_assign(intervals1, vec), + (this @ Array(..), Run(mut intervals)) => { + let Array(vec) = &this else { unreachable!() }; + BitOrAssign::bitor_assign(&mut intervals, vec); + *this = Run(intervals); + } + (this @ Run(..), rhs @ Bitmap(..)) => { + *this = this.to_bitmap(); + BitOrAssign::bitor_assign(this, rhs); + } + (this @ &mut Array(..), mut rhs @ Bitmap(..)) => { + mem::swap(this, &mut rhs); + BitOrAssign::bitor_assign(this, rhs); + } + } + } +} + +impl BitOrAssign<&Store> for Store { + fn bitor_assign(&mut self, rhs: &Store) { + match (self, rhs) { + (&mut Array(ref mut vec1), Array(vec2)) => { + let this = mem::take(vec1); + *vec1 = BitOr::bitor(&this, vec2); + } + (&mut Bitmap(ref mut bits1), Array(vec2)) => { + BitOrAssign::bitor_assign(bits1, vec2); + } + (&mut Bitmap(ref mut bits1), Bitmap(bits2)) => { + BitOrAssign::bitor_assign(bits1, bits2); + } + (this @ &mut Array(..), Bitmap(bits2)) => { + let mut lhs: Store = Bitmap(bits2.clone()); + BitOrAssign::bitor_assign(&mut lhs, &*this); + *this = lhs; + } + (Run(runs1), Run(runs2)) => { + BitOrAssign::bitor_assign(runs1, runs2); + } + (Run(runs), Array(array)) => { + BitOrAssign::bitor_assign(runs, array); + } + (this @ Array(..), Run(runs)) => { + let mut runs = runs.clone(); + let Array(array) = &this else { unreachable!() }; + BitOrAssign::bitor_assign(&mut runs, array); + *this = Run(runs); + } + (this @ Run(..), Bitmap(bitmap)) => { + let Run(runs) = &this else { unreachable!() }; + let mut new = runs.to_bitmap(); + BitOrAssign::bitor_assign(&mut new, bitmap); + *this = Bitmap(new); + } + (Bitmap(bitmap), Run(runs)) => { + BitOrAssign::bitor_assign(bitmap, &runs.to_bitmap()); + } + } + } +} + +impl BitAnd<&Store> for &Store { + type Output = Store; + + fn bitand(self, rhs: &Store) -> Store { + match (self, rhs) { + (Array(vec1), Array(vec2)) => Array(BitAnd::bitand(vec1, vec2)), + (&Bitmap(..), &Array(..)) => { + let mut rhs = rhs.clone(); + BitAndAssign::bitand_assign(&mut rhs, self); + rhs + } + _ => { + let mut lhs = self.clone(); + BitAndAssign::bitand_assign(&mut lhs, rhs); + lhs + } + } + } +} + +impl BitAndAssign for Store { + #[allow(clippy::suspicious_op_assign_impl)] + fn bitand_assign(&mut self, mut rhs: Store) { + match (self, &mut rhs) { + (&mut Array(ref mut vec1), &mut Array(ref mut vec2)) => { + if vec2.len() < vec1.len() { + mem::swap(vec1, vec2); + } + BitAndAssign::bitand_assign(vec1, &*vec2); + } + (&mut Bitmap(ref mut bits1), &mut Bitmap(ref bits2)) => { + BitAndAssign::bitand_assign(bits1, bits2); + } + (&mut Array(ref mut vec1), &mut Bitmap(ref bits2)) => { + BitAndAssign::bitand_assign(vec1, bits2); + } + (Run(intervals1), Run(intervals2)) => { + *intervals1 = BitAnd::bitand(&*intervals1, &*intervals2); + } + (this @ &mut Run(..), Array(array)) => { + let Run(runs) = &this else { unreachable!() }; + BitAndAssign::bitand_assign(array, runs); + *this = rhs; + } + (Array(array), Run(runs)) => { + BitAndAssign::bitand_assign(array, &*runs); + } + (this @ &mut Run(..), Bitmap(bitmap)) => { + let Run(runs) = &this else { unreachable!() }; + let mut new_bitmap = runs.to_bitmap(); + BitAndAssign::bitand_assign(&mut new_bitmap, &*bitmap); + *this = Bitmap(new_bitmap); + } + (Bitmap(bitmap), Run(runs)) => { + BitAndAssign::bitand_assign(bitmap, &runs.to_bitmap()); + } + (this @ &mut Bitmap(..), &mut Array(..)) => { + mem::swap(this, &mut rhs); + BitAndAssign::bitand_assign(this, rhs); + } + } + } +} + +impl BitAndAssign<&Store> for Store { + #[allow(clippy::suspicious_op_assign_impl)] + fn bitand_assign(&mut self, rhs: &Store) { + match (self, rhs) { + (&mut Array(ref mut vec1), Array(vec2)) => { + let (mut lhs, rhs) = if vec2.len() < vec1.len() { + (vec2.clone(), &*vec1) + } else { + (mem::take(vec1), vec2) + }; + + BitAndAssign::bitand_assign(&mut lhs, rhs); + *vec1 = lhs; + } + (&mut Bitmap(ref mut bits1), Bitmap(bits2)) => { + BitAndAssign::bitand_assign(bits1, bits2); + } + (&mut Array(ref mut vec1), Bitmap(bits2)) => { + BitAndAssign::bitand_assign(vec1, bits2); + } + (this @ &mut Bitmap(..), &Array(..)) => { + let mut new = rhs.clone(); + BitAndAssign::bitand_assign(&mut new, &*this); + *this = new; + } + (Run(runs1), Run(runs2)) => { + *runs1 = BitAnd::bitand(&*runs1, runs2); + } + (this @ Run(..), Bitmap(bitmap)) => { + let Run(runs) = &this else { unreachable!() }; + let mut new_bitmap = runs.to_bitmap(); + BitAndAssign::bitand_assign(&mut new_bitmap, bitmap); + *this = Bitmap(new_bitmap); + } + (Bitmap(bitmap), Run(runs)) => { + BitAndAssign::bitand_assign(bitmap, &runs.to_bitmap()); + } + (this @ Run(..), Array(array)) => { + let Run(runs) = &this else { unreachable!() }; + let mut new_array = array.clone(); + new_array.retain(|f| runs.contains(f)); + *this = Array(new_array); + } + (Array(array), Run(runs)) => array.retain(|f| runs.contains(f)), + } + } +} + +impl Sub<&Store> for &Store { + type Output = Store; + + fn sub(self, rhs: &Store) -> Store { + match (self, rhs) { + (Array(vec1), Array(vec2)) => Array(Sub::sub(vec1, vec2)), + _ => { + let mut lhs = self.clone(); + SubAssign::sub_assign(&mut lhs, rhs); + lhs + } + } + } +} + +impl SubAssign<&Store> for Store { + fn sub_assign(&mut self, rhs: &Store) { + match (self, rhs) { + (&mut Array(ref mut vec1), Array(vec2)) => { + SubAssign::sub_assign(vec1, vec2); + } + (&mut Bitmap(ref mut bits1), Array(vec2)) => { + SubAssign::sub_assign(bits1, vec2); + } + (&mut Bitmap(ref mut bits1), Bitmap(bits2)) => { + SubAssign::sub_assign(bits1, bits2); + } + (&mut Array(ref mut vec1), Bitmap(bits2)) => { + SubAssign::sub_assign(vec1, bits2); + } + (Run(runs1), Run(runs2)) => { + SubAssign::sub_assign(runs1, runs2); + } + (Run(runs), Array(array)) => { + array.iter().for_each(|&f| { + runs.remove(f); + }); + } + (Array(array), Run(runs)) => { + runs.iter_intervals().for_each(|iv| { + array.remove_range(iv.start()..=iv.end()); + }); + } + (this @ Run(..), Bitmap(bitmap)) => { + let Run(runs) = &this else { unreachable!() }; + let mut new_bitmap = runs.to_bitmap(); + SubAssign::sub_assign(&mut new_bitmap, bitmap); + *this = Bitmap(new_bitmap); + } + (Bitmap(bitmap), Run(runs)) => { + let new_bitmap = runs.to_bitmap(); + SubAssign::sub_assign(bitmap, &new_bitmap); + } + } + } +} + +impl BitXor<&Store> for &Store { + type Output = Store; + + fn bitxor(self, rhs: &Store) -> Store { + match (self, rhs) { + (Array(vec1), Array(vec2)) => Array(BitXor::bitxor(vec1, vec2)), + (&Array(..), &Bitmap(..)) => { + let mut lhs = rhs.clone(); + BitXorAssign::bitxor_assign(&mut lhs, self); + lhs + } + _ => { + let mut lhs = self.clone(); + BitXorAssign::bitxor_assign(&mut lhs, rhs); + lhs + } + } + } +} + +impl BitXorAssign for Store { + fn bitxor_assign(&mut self, mut rhs: Store) { + match (self, &mut rhs) { + (&mut Array(ref mut vec1), &mut Array(ref vec2)) => { + *vec1 = BitXor::bitxor(&*vec1, vec2); + } + (&mut Bitmap(ref mut bits1), &mut Array(ref vec2)) => { + BitXorAssign::bitxor_assign(bits1, vec2); + } + (&mut Bitmap(ref mut bits1), &mut Bitmap(ref bits2)) => { + BitXorAssign::bitxor_assign(bits1, bits2); + } + (this @ &mut Array(..), &mut Bitmap(..)) => { + mem::swap(this, &mut rhs); + BitXorAssign::bitxor_assign(this, rhs); + } + (Run(runs1), Run(runs2)) => { + *runs1 = BitXor::bitxor(&*runs1, &*runs2); + } + (Run(runs1), Array(array)) => BitXorAssign::bitxor_assign(runs1, array), + (this @ Array(..), Run(runs1)) => { + let Array(array) = &this else { unreachable!() }; + BitXorAssign::bitxor_assign(runs1, array); + *this = rhs; + } + (Bitmap(bitmap), Run(runs)) => { + BitXorAssign::bitxor_assign(bitmap, &runs.to_bitmap()); + } + (this @ Run(..), Bitmap(bitmap)) => { + let Run(runs) = &this else { unreachable!() }; + BitXorAssign::bitxor_assign(bitmap, &runs.to_bitmap()); + *this = rhs; + } + } + } +} + +impl BitXorAssign<&Store> for Store { + fn bitxor_assign(&mut self, rhs: &Store) { + match (self, rhs) { + (&mut Array(ref mut vec1), Array(vec2)) => { + let this = mem::take(vec1); + *vec1 = BitXor::bitxor(&this, vec2); + } + (&mut Bitmap(ref mut bits1), Bitmap(bits2)) => { + BitXorAssign::bitxor_assign(bits1, bits2); + } + (this @ &mut Array(..), Bitmap(bits2)) => { + let mut lhs: Store = Bitmap(bits2.clone()); + BitXorAssign::bitxor_assign(&mut lhs, &*this); + *this = lhs; + } + (&mut Bitmap(ref mut bits1), Array(vec2)) => { + BitXorAssign::bitxor_assign(bits1, vec2); + } + (Run(runs1), Run(runs2)) => { + *runs1 = BitXor::bitxor(&*runs1, runs2); + } + (Run(runs1), Array(array)) => BitXorAssign::bitxor_assign(runs1, array), + (this @ Array(..), Run(runs1)) => { + let Array(array) = &this else { unreachable!() }; + let mut runs1 = runs1.clone(); + BitXorAssign::bitxor_assign(&mut runs1, array); + *this = Run(runs1); + } + (Bitmap(bitmap), Run(runs)) => { + BitXorAssign::bitxor_assign(bitmap, &runs.to_bitmap()); + } + (this @ Run(..), Bitmap(bitmap)) => { + let Run(runs) = &this else { unreachable!() }; + let mut new_bitmap = runs.to_bitmap(); + BitXorAssign::bitxor_assign(&mut new_bitmap, bitmap); + *this = Bitmap(new_bitmap); + } + } + } +} + +impl<'a> IntoIterator for &'a Store { + type Item = u16; + type IntoIter = Iter<'a>; + fn into_iter(self) -> Iter<'a> { + match self { + Array(vec) => Iter::Array(vec.iter()), + Bitmap(bits) => Iter::BitmapBorrowed(bits.iter()), + Run(intervals) => Iter::RunBorrowed(intervals.iter()), + } + } +} + +impl IntoIterator for Store { + type Item = u16; + type IntoIter = Iter<'static>; + fn into_iter(self) -> Iter<'static> { + match self { + Array(vec) => Iter::Vec(vec.into_iter()), + Bitmap(bits) => Iter::BitmapOwned(bits.into_iter()), + Run(intervals) => Iter::RunOwned(intervals.into_iter()), + } + } +} + +impl PartialEq for Store { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Array(vec1), Array(vec2)) => vec1 == vec2, + (Bitmap(bits1), Bitmap(bits2)) => { + bits1.len() == bits2.len() + && bits1.iter().zip(bits2.iter()).all(|(i1, i2)| i1 == i2) + } + (Run(intervals1), Run(intervals2)) => intervals1 == intervals2, + (Run(run), Array(array)) | (Array(array), Run(run)) => { + run.len() == array.len() && array.iter().all(|&i| run.contains(i)) + } + (Run(run), Bitmap(bitmap)) | (Bitmap(bitmap), Run(run)) => { + run.len() == bitmap.len() + && run.iter_intervals().all(|&iv| bitmap.contains_range(iv.start()..=iv.end())) + } + _ => false, + } + } +} + +impl Iter<'_> { + /// Advance the iterator to the first value greater than or equal to `n`. + pub(crate) fn advance_to(&mut self, n: u16) { + match self { + Iter::Array(inner) => { + let skip = inner.as_slice().partition_point(|&i| i < n); + if let Some(nth) = skip.checked_sub(1) { + inner.nth(nth); + } + } + Iter::Vec(inner) => { + let skip = inner.as_slice().partition_point(|&i| i < n); + if let Some(nth) = skip.checked_sub(1) { + inner.nth(nth); + } + } + Iter::BitmapBorrowed(inner) => inner.advance_to(n), + Iter::BitmapOwned(inner) => inner.advance_to(n), + Iter::RunOwned(inner) => inner.advance_to(n), + Iter::RunBorrowed(inner) => inner.advance_to(n), + } + } + + pub(crate) fn advance_back_to(&mut self, n: u16) { + match self { + Iter::Array(inner) => { + let slice = inner.as_slice(); + let from_front = slice.partition_point(|&i| i <= n); + let skip = slice.len() - from_front; + if let Some(nth) = skip.checked_sub(1) { + inner.nth_back(nth); + } + } + Iter::Vec(inner) => { + let slice = inner.as_slice(); + let from_front = slice.partition_point(|&i| i <= n); + let skip = slice.len() - from_front; + if let Some(nth) = skip.checked_sub(1) { + inner.nth_back(nth); + } + } + Iter::BitmapBorrowed(inner) => inner.advance_back_to(n), + Iter::BitmapOwned(inner) => inner.advance_back_to(n), + Iter::RunOwned(inner) => inner.advance_back_to(n), + Iter::RunBorrowed(inner) => inner.advance_back_to(n), + } + } + + pub(crate) fn next_range(&mut self) -> Option> { + match self { + Iter::Array(inner) => { + let slice = inner.as_slice(); + let len = array_store::first_contiguous_range_len(slice); + let mut range = None; + if len != 0 { + let first = slice[0]; + inner.nth(len - 1); + range = Some(first..=first + (len - 1) as u16); + } + range + } + Iter::Vec(inner) => { + let slice = inner.as_slice(); + let len = array_store::first_contiguous_range_len(slice); + let mut range = None; + if len != 0 { + let first = slice[0]; + inner.nth(len - 1); + range = Some(first..=first + (len - 1) as u16); + } + range + } + Iter::BitmapBorrowed(inner) => inner.next_range(), + Iter::BitmapOwned(inner) => inner.next_range(), + Iter::RunBorrowed(inner) => inner.next_range(), + Iter::RunOwned(inner) => inner.next_range(), + } + } + + pub(crate) fn next_range_back(&mut self) -> Option> { + match self { + Iter::Array(inner) => { + let slice = inner.as_slice(); + let len = array_store::last_contiguous_range_len(slice); + let mut range = None; + if len != 0 { + let last = slice[slice.len() - 1]; + inner.nth_back(len - 1); + range = Some(last - (len - 1) as u16..=last); + } + range + } + Iter::Vec(inner) => { + let slice = inner.as_slice(); + let len = array_store::last_contiguous_range_len(slice); + let mut range = None; + if len != 0 { + let last = slice[slice.len() - 1]; + inner.nth_back(len - 1); + range = Some(last - (len - 1) as u16..=last); + } + range + } + Iter::BitmapBorrowed(inner) => inner.next_range_back(), + Iter::BitmapOwned(inner) => inner.next_range_back(), + Iter::RunBorrowed(inner) => inner.next_range_back(), + Iter::RunOwned(inner) => inner.next_range_back(), + } + } + + pub(crate) fn peek(&self) -> Option { + match self { + Iter::Array(inner) => inner.as_slice().first().copied(), + Iter::Vec(inner) => inner.as_slice().first().copied(), + Iter::BitmapBorrowed(inner) => inner.peek(), + Iter::BitmapOwned(inner) => inner.peek(), + Iter::RunBorrowed(inner) => inner.peek(), + Iter::RunOwned(inner) => inner.peek(), + } + } + pub(crate) fn peek_back(&self) -> Option { + match self { + Iter::Array(inner) => inner.as_slice().last().copied(), + Iter::Vec(inner) => inner.as_slice().last().copied(), + Iter::BitmapBorrowed(inner) => inner.peek_back(), + Iter::BitmapOwned(inner) => inner.peek_back(), + Iter::RunBorrowed(inner) => inner.peek_back(), + Iter::RunOwned(inner) => inner.peek_back(), + } + } +} + +impl Iterator for Iter<'_> { + type Item = u16; + + fn next(&mut self) -> Option { + match self { + Iter::Array(inner) => inner.next().cloned(), + Iter::Vec(inner) => inner.next(), + Iter::BitmapBorrowed(inner) => inner.next(), + Iter::BitmapOwned(inner) => inner.next(), + Iter::RunOwned(inner) => inner.next(), + Iter::RunBorrowed(inner) => inner.next(), + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + Iter::Array(inner) => inner.size_hint(), + Iter::Vec(inner) => inner.size_hint(), + Iter::BitmapBorrowed(inner) => inner.size_hint(), + Iter::BitmapOwned(inner) => inner.size_hint(), + Iter::RunOwned(inner) => inner.size_hint(), + Iter::RunBorrowed(inner) => inner.size_hint(), + } + } + + fn count(self) -> usize + where + Self: Sized, + { + match self { + Iter::Array(inner) => inner.count(), + Iter::Vec(inner) => inner.count(), + Iter::BitmapBorrowed(inner) => inner.count(), + Iter::BitmapOwned(inner) => inner.count(), + Iter::RunOwned(inner) => inner.count(), + Iter::RunBorrowed(inner) => inner.count(), + } + } + + fn nth(&mut self, n: usize) -> Option { + match self { + Iter::Array(inner) => inner.nth(n).copied(), + Iter::Vec(inner) => inner.nth(n), + Iter::BitmapBorrowed(inner) => inner.nth(n), + Iter::BitmapOwned(inner) => inner.nth(n), + Iter::RunOwned(inner) => inner.nth(n), + Iter::RunBorrowed(inner) => inner.nth(n), + } + } +} + +impl DoubleEndedIterator for Iter<'_> { + fn next_back(&mut self) -> Option { + match self { + Iter::Array(inner) => inner.next_back().cloned(), + Iter::Vec(inner) => inner.next_back(), + Iter::BitmapBorrowed(inner) => inner.next_back(), + Iter::BitmapOwned(inner) => inner.next_back(), + Iter::RunOwned(inner) => inner.next_back(), + Iter::RunBorrowed(inner) => inner.next_back(), + } + } +} + +impl ExactSizeIterator for Iter<'_> {} diff --git a/vendor/roaring/src/bitmap/util.rs b/vendor/roaring/src/bitmap/util.rs new file mode 100644 index 0000000..80a4896 --- /dev/null +++ b/vendor/roaring/src/bitmap/util.rs @@ -0,0 +1,122 @@ +use core::ops::{Bound, RangeBounds, RangeInclusive}; + +/// Returns the container key and the index +/// in this container for a given integer. +#[inline] +pub fn split(value: u32) -> (u16, u16) { + ((value >> 16) as u16, value as u16) +} + +/// Returns the original integer from the container +/// key and the index of it in the container. +#[inline] +pub fn join(high: u16, low: u16) -> u32 { + (u32::from(high) << 16) + u32::from(low) +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum ConvertRangeError { + Empty, + StartGreaterThanEnd, + StartAndEndEqualExcluded, +} + +/// Convert a `RangeBounds` object to `RangeInclusive`, +pub fn convert_range_to_inclusive(range: R) -> Result, ConvertRangeError> +where + R: RangeBounds, +{ + let start_bound = range.start_bound().cloned(); + let end_bound = range.end_bound().cloned(); + match (start_bound, end_bound) { + (Bound::Excluded(s), Bound::Excluded(e)) if s == e => { + Err(ConvertRangeError::StartAndEndEqualExcluded) + } + (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e)) + if s > e => + { + Err(ConvertRangeError::StartGreaterThanEnd) + } + _ => { + let start = match start_bound { + Bound::Included(s) => s, + Bound::Excluded(s) => s.checked_add(1).ok_or(ConvertRangeError::Empty)?, + Bound::Unbounded => 0, + }; + + let end = match end_bound { + Bound::Included(e) => e, + Bound::Excluded(e) => e.checked_sub(1).ok_or(ConvertRangeError::Empty)?, + Bound::Unbounded => u32::MAX, + }; + + if start > end { + // This handles e.g. `x..x`: we've ruled out `start > end` overall, so a value must + // have been changed via exclusion. + Err(ConvertRangeError::Empty) + } else { + Ok(start..=end) + } + } + } +} + +#[cfg(test)] +mod test { + use super::{convert_range_to_inclusive, join, split, ConvertRangeError}; + use core::ops::Bound; + + #[test] + fn test_split_u32() { + assert_eq!((0x0000u16, 0x0000u16), split(0x0000_0000u32)); + assert_eq!((0x0000u16, 0x0001u16), split(0x0000_0001u32)); + assert_eq!((0x0000u16, 0xFFFEu16), split(0x0000_FFFEu32)); + assert_eq!((0x0000u16, 0xFFFFu16), split(0x0000_FFFFu32)); + assert_eq!((0x0001u16, 0x0000u16), split(0x0001_0000u32)); + assert_eq!((0x0001u16, 0x0001u16), split(0x0001_0001u32)); + assert_eq!((0xFFFFu16, 0xFFFEu16), split(0xFFFF_FFFEu32)); + assert_eq!((0xFFFFu16, 0xFFFFu16), split(0xFFFF_FFFFu32)); + } + + #[test] + fn test_join_u32() { + assert_eq!(0x0000_0000u32, join(0x0000u16, 0x0000u16)); + assert_eq!(0x0000_0001u32, join(0x0000u16, 0x0001u16)); + assert_eq!(0x0000_FFFEu32, join(0x0000u16, 0xFFFEu16)); + assert_eq!(0x0000_FFFFu32, join(0x0000u16, 0xFFFFu16)); + assert_eq!(0x0001_0000u32, join(0x0001u16, 0x0000u16)); + assert_eq!(0x0001_0001u32, join(0x0001u16, 0x0001u16)); + assert_eq!(0xFFFF_FFFEu32, join(0xFFFFu16, 0xFFFEu16)); + assert_eq!(0xFFFF_FFFFu32, join(0xFFFFu16, 0xFFFFu16)); + } + + #[test] + #[allow(clippy::reversed_empty_ranges)] + fn test_convert_range_to_inclusive() { + assert_eq!(Ok(1..=5), convert_range_to_inclusive(1..6)); + assert_eq!(Ok(1..=u32::MAX), convert_range_to_inclusive(1..)); + assert_eq!(Ok(0..=u32::MAX), convert_range_to_inclusive(..)); + assert_eq!(Ok(16..=16), convert_range_to_inclusive(16..=16)); + assert_eq!( + Ok(11..=19), + convert_range_to_inclusive((Bound::Excluded(10), Bound::Excluded(20))) + ); + + assert_eq!(Err(ConvertRangeError::Empty), convert_range_to_inclusive(0..0)); + assert_eq!(Err(ConvertRangeError::Empty), convert_range_to_inclusive(5..5)); + assert_eq!(Err(ConvertRangeError::StartGreaterThanEnd), convert_range_to_inclusive(1..0)); + assert_eq!(Err(ConvertRangeError::StartGreaterThanEnd), convert_range_to_inclusive(10..5)); + assert_eq!( + Err(ConvertRangeError::Empty), + convert_range_to_inclusive((Bound::Excluded(u32::MAX), Bound::Included(u32::MAX))) + ); + assert_eq!( + Err(ConvertRangeError::StartAndEndEqualExcluded), + convert_range_to_inclusive((Bound::Excluded(u32::MAX), Bound::Excluded(u32::MAX))) + ); + assert_eq!( + Err(ConvertRangeError::Empty), + convert_range_to_inclusive((Bound::Excluded(0), Bound::Included(0))) + ); + } +} diff --git a/vendor/roaring/src/lib.rs b/vendor/roaring/src/lib.rs new file mode 100644 index 0000000..f6c4453 --- /dev/null +++ b/vendor/roaring/src/lib.rs @@ -0,0 +1,107 @@ +//! This is a [Rust][] port of the [Roaring bitmap][] data structure, initially +//! defined as a [Java library][roaring-java] and described in [_Better bitmap +//! performance with Roaring bitmaps_][roaring-paper]. +//! +//! [Rust]: https://www.rust-lang.org/ +//! [Roaring bitmap]: https://roaringbitmap.org/ +//! [roaring-java]: https://github.com/lemire/RoaringBitmap +//! [roaring-paper]: https://arxiv.org/pdf/1402.6407v4 + +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(feature = "simd", feature(portable_simd))] +#![warn(missing_docs)] +#![warn(unsafe_op_in_unsafe_fn)] +#![warn(variant_size_differences)] +#![allow(unknown_lints)] // For clippy +#![allow(clippy::doc_overindented_list_items)] +#![deny(unnameable_types)] + +#[cfg(feature = "std")] +extern crate byteorder; + +#[macro_use] +extern crate alloc; + +use core::fmt; + +/// A compressed bitmap using the [Roaring bitmap compression scheme](https://roaringbitmap.org/). +pub mod bitmap; + +/// A compressed bitmap with u64 values. Implemented as a `BTreeMap` of `RoaringBitmap`s. +pub mod treemap; + +pub use bitmap::RoaringBitmap; +pub use treemap::RoaringTreemap; + +/// An error type that is returned when a `try_push` in a bitmap did not succeed. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct IntegerTooSmall; + +impl fmt::Display for IntegerTooSmall { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str("inserted integer is smaller than the largest integer") + } +} + +/// An error type that is returned when an iterator isn't sorted. +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct NonSortedIntegers { + valid_until: u64, +} + +impl NonSortedIntegers { + /// Returns the number of elements that were + pub fn valid_until(&self) -> u64 { + self.valid_until + } +} + +impl fmt::Display for NonSortedIntegers { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "integers are ordered up to the {}th element", self.valid_until()) + } +} + +#[cfg(feature = "std")] +impl std::error::Error for NonSortedIntegers {} + +/// A [`Iterator::collect`] blanket implementation that provides extra methods for [`RoaringBitmap`] +/// and [`RoaringTreemap`]. +/// +/// When merging multiple bitmap with the same operation it's usually faster to call the +/// method in this trait than to write your own for loop and merging the bitmaps yourself. +/// +/// # Examples +/// ``` +/// use roaring::{MultiOps, RoaringBitmap}; +/// +/// let bitmaps = [ +/// RoaringBitmap::from_iter(0..10), +/// RoaringBitmap::from_iter(10..20), +/// RoaringBitmap::from_iter(20..30), +/// ]; +/// +/// // Stop doing this +/// let naive = bitmaps.clone().into_iter().reduce(|a, b| a | b).unwrap_or_default(); +/// +/// // And start doing this instead, it will be much faster! +/// let iter = bitmaps.union(); +/// +/// assert_eq!(naive, iter); +/// ``` +pub trait MultiOps: IntoIterator { + /// The type of output from operations. + type Output; + + /// The `union` between all elements. + fn union(self) -> Self::Output; + + /// The `intersection` between all elements. + fn intersection(self) -> Self::Output; + + /// The `difference` between all elements. + fn difference(self) -> Self::Output; + + /// The `symmetric difference` between all elements. + fn symmetric_difference(self) -> Self::Output; +} diff --git a/vendor/roaring/src/treemap/arbitrary.rs b/vendor/roaring/src/treemap/arbitrary.rs new file mode 100644 index 0000000..6c8e096 --- /dev/null +++ b/vendor/roaring/src/treemap/arbitrary.rs @@ -0,0 +1,17 @@ +#[cfg(test)] +mod test { + use crate::{RoaringBitmap, RoaringTreemap}; + use proptest::collection::btree_map; + use proptest::prelude::*; + + impl RoaringTreemap { + prop_compose! { + pub(crate) fn arbitrary()(map in btree_map(0u32..=16, RoaringBitmap::arbitrary(), 0usize..=16)) -> RoaringTreemap { + // we’re NEVER supposed to start with a treemap containing empty bitmaps + // Since we can’t configure this in arbitrary we’re simply going to ignore the generated empty bitmaps + let map = map.into_iter().filter(|(_, v)| !v.is_empty()).collect(); + RoaringTreemap { map } + } + } + } +} diff --git a/vendor/roaring/src/treemap/cmp.rs b/vendor/roaring/src/treemap/cmp.rs new file mode 100644 index 0000000..3334f86 --- /dev/null +++ b/vendor/roaring/src/treemap/cmp.rs @@ -0,0 +1,137 @@ +use alloc::collections::btree_map; +use core::iter::Peekable; + +use crate::RoaringBitmap; +use crate::RoaringTreemap; + +pub(crate) struct Pairs<'a>( + Peekable>, + Peekable>, +); + +impl RoaringTreemap { + pub(crate) fn pairs<'a>(&'a self, other: &'a RoaringTreemap) -> Pairs<'a> { + Pairs(self.map.iter().peekable(), other.map.iter().peekable()) + } + + /// Returns true if the set has no elements in common with other. This is equivalent to + /// checking for an empty intersection. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb1 = RoaringTreemap::new(); + /// let mut rb2 = RoaringTreemap::new(); + /// + /// rb1.insert(1); + /// + /// assert_eq!(rb1.is_disjoint(&rb2), true); + /// + /// rb2.insert(1); + /// + /// assert_eq!(rb1.is_disjoint(&rb2), false); + /// + /// ``` + pub fn is_disjoint(&self, other: &Self) -> bool { + self.pairs(other) + .filter(|&(c1, c2)| c1.is_some() && c2.is_some()) + .all(|(c1, c2)| c1.unwrap().is_disjoint(c2.unwrap())) + } + + /// Returns `true` if this set is a subset of `other`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb1 = RoaringTreemap::new(); + /// let mut rb2 = RoaringTreemap::new(); + /// + /// rb1.insert(1); + /// + /// assert_eq!(rb1.is_subset(&rb2), false); + /// + /// rb2.insert(1); + /// + /// assert_eq!(rb1.is_subset(&rb2), true); + /// + /// rb1.insert(2); + /// + /// assert_eq!(rb1.is_subset(&rb2), false); + /// ``` + pub fn is_subset(&self, other: &Self) -> bool { + for pair in self.pairs(other) { + match pair { + (None, _) => (), + (_, None) => { + return false; + } + (Some(c1), Some(c2)) => { + if !c1.is_subset(c2) { + return false; + } + } + } + } + true + } + + /// Returns `true` if this set is a superset of `other`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb1 = RoaringTreemap::new(); + /// let mut rb2 = RoaringTreemap::new(); + /// + /// rb1.insert(1); + /// + /// assert_eq!(rb2.is_superset(&rb1), false); + /// + /// rb2.insert(1); + /// + /// assert_eq!(rb2.is_superset(&rb1), true); + /// + /// rb1.insert(2); + /// + /// assert_eq!(rb2.is_superset(&rb1), false); + /// ``` + pub fn is_superset(&self, other: &Self) -> bool { + other.is_subset(self) + } +} + +impl<'a> Iterator for Pairs<'a> { + type Item = (Option<&'a RoaringBitmap>, Option<&'a RoaringBitmap>); + + fn next(&mut self) -> Option { + enum Which { + Left, + Right, + Both, + None, + } + let which = match (self.0.peek(), self.1.peek()) { + (None, None) => Which::None, + (Some(_), None) => Which::Left, + (None, Some(_)) => Which::Right, + (Some(c1), Some(c2)) => match (c1.0, c2.0) { + (key1, key2) if key1 == key2 => Which::Both, + (key1, key2) if key1 < key2 => Which::Left, + (key1, key2) if key1 > key2 => Which::Right, + (_, _) => unreachable!(), + }, + }; + match which { + Which::Left => Some((self.0.next().map(|e| e.1), None)), + Which::Right => Some((None, self.1.next().map(|e| e.1))), + Which::Both => Some((self.0.next().map(|e| e.1), self.1.next().map(|e| e.1))), + Which::None => None, + } + } +} diff --git a/vendor/roaring/src/treemap/fmt.rs b/vendor/roaring/src/treemap/fmt.rs new file mode 100644 index 0000000..4a33008 --- /dev/null +++ b/vendor/roaring/src/treemap/fmt.rs @@ -0,0 +1,22 @@ +use core::fmt; + +use crate::RoaringTreemap; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl fmt::Debug for RoaringTreemap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.len() < 16 { + write!(f, "RoaringTreemap<{:?}>", self.iter().collect::>()) + } else { + write!( + f, + "RoaringTreemap<{:?} values between {:?} and {:?}>", + self.len(), + self.min().unwrap(), + self.max().unwrap() + ) + } + } +} diff --git a/vendor/roaring/src/treemap/inherent.rs b/vendor/roaring/src/treemap/inherent.rs new file mode 100644 index 0000000..8f27f9f --- /dev/null +++ b/vendor/roaring/src/treemap/inherent.rs @@ -0,0 +1,459 @@ +use alloc::collections::btree_map::{BTreeMap, Entry}; +use core::iter; +use core::ops::RangeBounds; + +use crate::IntegerTooSmall; +use crate::RoaringBitmap; +use crate::RoaringTreemap; + +use super::util; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl RoaringTreemap { + /// Creates an empty `RoaringTreemap`. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// let rb = RoaringTreemap::new(); + /// ``` + pub fn new() -> RoaringTreemap { + RoaringTreemap { map: BTreeMap::new() } + } + + /// Creates a full `RoaringTreemap`. + /// + /// # Examples + /// + /// ```rust,ignore + /// use roaring::RoaringTreemap; + /// let rb = RoaringTreemap::full(); + /// ``` + pub fn full() -> RoaringTreemap { + RoaringTreemap { map: (0..=u32::MAX).zip(iter::repeat(RoaringBitmap::full())).collect() } + } + + /// Adds a value to the set. Returns `true` if the value was not already present in the set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.insert(3), true); + /// assert_eq!(rb.insert(3), false); + /// assert_eq!(rb.contains(3), true); + /// ``` + pub fn insert(&mut self, value: u64) -> bool { + let (hi, lo) = util::split(value); + self.map.entry(hi).or_default().insert(lo) + } + + /// Inserts a range of values. + /// + /// Returns the number of inserted values. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// rb.insert_range(2..4); + /// assert!(rb.contains(2)); + /// assert!(rb.contains(3)); + /// assert!(!rb.contains(4)); + /// ``` + pub fn insert_range>(&mut self, range: R) -> u64 { + let (start, end) = match util::convert_range_to_inclusive(range) { + Some(range) => (*range.start(), *range.end()), + None => return 0, + }; + + let (start_hi, start_lo) = util::split(start); + let (end_hi, end_lo) = util::split(end); + + let mut counter = 0u64; + + // Split the input range by the leading 32 bits + for hi in start_hi..=end_hi { + let entry = self.map.entry(hi); + + // Calculate the sub-range from the lower 32 bits + counter += if hi == end_hi && hi == start_hi { + entry.or_default().insert_range(start_lo..=end_lo) + } else if hi == start_hi { + entry.or_default().insert_range(start_lo..=u32::MAX) + } else if hi == end_hi { + entry.or_default().insert_range(0..=end_lo) + } else { + // We insert a full bitmap if it doesn't already exist and return the size of it. + // But if the bitmap already exists at this spot we replace it with a full bitmap + // and specify that we didn't inserted the integers from the previous bitmap. + let full_bitmap = RoaringBitmap::full(); + match entry { + Entry::Vacant(entry) => entry.insert(full_bitmap).len(), + Entry::Occupied(mut entry) => { + full_bitmap.len() - entry.insert(full_bitmap).len() + } + } + }; + } + + counter + } + + /// Pushes `value` in the treemap only if it is greater than the current maximum value. + /// + /// Returns whether the value was inserted. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert!(rb.push(1)); + /// assert!(rb.push(3)); + /// assert_eq!(rb.push(3), false); + /// assert!(rb.push(5)); + /// + /// assert_eq!(rb.iter().collect::>(), vec![1, 3, 5]); + /// ``` + #[deprecated(since = "0.11.0", note = "use `try_push` instead")] + pub fn push(&mut self, value: u64) -> bool { + let (hi, lo) = util::split(value); + self.map.entry(hi).or_default().try_push(lo).is_ok() + } + + /// Pushes `value` in the treemap only if it is greater than the current maximum value. + /// + /// Returns an error if the value is not greater than the current maximum value. + /// + /// # Examples + /// + /// ```rust + /// use roaring::{RoaringTreemap, IntegerTooSmall}; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert!(rb.try_push(1).is_ok()); + /// assert!(rb.try_push(3).is_ok()); + /// assert_eq!(rb.try_push(3), Err(IntegerTooSmall)); + /// assert!(rb.try_push(5).is_ok()); + /// + /// assert_eq!(rb.iter().collect::>(), vec![1, 3, 5]); + /// ``` + pub fn try_push(&mut self, value: u64) -> Result<(), IntegerTooSmall> { + let (hi, lo) = util::split(value); + self.map.entry(hi).or_default().try_push(lo) + } + + /// Pushes `value` in the treemap only if it is greater than the current maximum value. + /// It is up to the caller to have validated index > self.max() + /// + /// # Panics + /// + /// If debug_assertions enabled and index is > self.max() + pub(crate) fn push_unchecked(&mut self, value: u64) { + let (hi, lo) = util::split(value); + // BTreeMap last_mut not stabilized see https://github.com/rust-lang/rust/issues/62924 + match self.map.iter_mut().next_back() { + Some((&key, bitmap)) if key == hi => bitmap.push_unchecked(lo), + Some((&key, _)) if cfg!(debug_assertions) && key > hi => { + panic!("last bitmap key > key of value") + } + _otherwise => { + // The tree is empty + let mut rb = RoaringBitmap::new(); + rb.push_unchecked(lo); + self.map.insert(hi, rb); + } + } + } + + /// Removes a value from the set. Returns `true` if the value was present in the set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// rb.insert(3); + /// assert_eq!(rb.remove(3), true); + /// assert_eq!(rb.remove(3), false); + /// assert_eq!(rb.contains(3), false); + /// ``` + pub fn remove(&mut self, value: u64) -> bool { + let (hi, lo) = util::split(value); + match self.map.entry(hi) { + Entry::Vacant(_) => false, + Entry::Occupied(mut ent) => { + if ent.get_mut().remove(lo) { + if ent.get().is_empty() { + ent.remove(); + } + true + } else { + false + } + } + } + } + + /// Removes a range of values. + /// Returns the number of removed values. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// rb.insert(2); + /// rb.insert(3); + /// assert_eq!(rb.remove_range(2..4), 2); + /// ``` + pub fn remove_range(&mut self, range: R) -> u64 + where + R: RangeBounds, + { + let (start, end) = match util::convert_range_to_inclusive(range) { + Some(range) => (*range.start(), *range.end()), + None => return 0, + }; + + let (start_container_key, start_index) = util::split(start); + let (end_container_key, end_index) = util::split(end); + + let mut keys_to_remove = Vec::new(); + let mut removed = 0; + + for (&key, rb) in &mut self.map { + if key >= start_container_key && key <= end_container_key { + let a = if key == start_container_key { start_index } else { 0 }; + let b = if key == end_container_key { end_index } else { u32::MAX }; + removed += rb.remove_range(a..=b); + if rb.is_empty() { + keys_to_remove.push(key); + } + } + } + + for key in keys_to_remove { + self.map.remove(&key); + } + + removed + } + + /// Returns `true` if this set contains the specified integer. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// rb.insert(1); + /// assert_eq!(rb.contains(0), false); + /// assert_eq!(rb.contains(1), true); + /// assert_eq!(rb.contains(100), false); + /// ``` + pub fn contains(&self, value: u64) -> bool { + let (hi, lo) = util::split(value); + match self.map.get(&hi) { + None => false, + Some(r) => r.contains(lo), + } + } + + /// Clears all integers in this set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// rb.insert(1); + /// assert_eq!(rb.contains(1), true); + /// rb.clear(); + /// assert_eq!(rb.contains(1), false); + /// ``` + pub fn clear(&mut self) { + self.map.clear(); + } + + /// Returns `true` if there are no integers in this set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.is_empty(), true); + /// + /// rb.insert(3); + /// assert_eq!(rb.is_empty(), false); + /// ``` + pub fn is_empty(&self) -> bool { + self.map.values().all(RoaringBitmap::is_empty) + } + + /// Returns `true` if there are every possible integers in this set. + /// + /// # Examples + /// + /// ```rust,ignore + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::full(); + /// assert!(!rb.is_empty()); + /// assert!(rb.is_full()); + /// ``` + pub fn is_full(&self) -> bool { + self.map.len() == (u32::MAX as usize + 1) && self.map.values().all(RoaringBitmap::is_full) + } + + /// Returns the number of distinct integers added to the set. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.len(), 0); + /// + /// rb.insert(3); + /// assert_eq!(rb.len(), 1); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.len(), 2); + /// ``` + pub fn len(&self) -> u64 { + self.map.values().map(RoaringBitmap::len).sum() + } + + /// Returns the minimum value in the set (if the set is non-empty). + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.min(), None); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.min(), Some(3)); + /// ``` + pub fn min(&self) -> Option { + self.map + .iter() + .find(|&(_, rb)| rb.min().is_some()) + .map(|(k, rb)| util::join(*k, rb.min().unwrap())) + } + + /// Returns the maximum value in the set (if the set is non-empty). + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.max(), None); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.max(), Some(4)); + /// ``` + pub fn max(&self) -> Option { + self.map + .iter() + .rev() + .find(|&(_, rb)| rb.max().is_some()) + .map(|(k, rb)| util::join(*k, rb.max().unwrap())) + } + + /// Returns the number of integers that are <= value. rank(u64::MAX) == len() + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.rank(0), 0); + /// + /// rb.insert(3); + /// rb.insert(4); + /// assert_eq!(rb.rank(3), 1); + /// assert_eq!(rb.rank(10), 2) + /// ``` + pub fn rank(&self, value: u64) -> u64 { + // if len becomes cached for RoaringTreemap: return len if len > value + + let (hi, lo) = util::split(value); + let mut iter = self.map.range(..=hi).rev(); + + iter.next() + .map(|(&k, bitmap)| if k == hi { bitmap.rank(lo) } else { bitmap.len() }) + .unwrap_or(0) + + iter.map(|(_, bitmap)| bitmap.len()).sum::() + } + + /// Returns the `n`th integer in the set or `None` if `n >= len()` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// assert_eq!(rb.select(0), None); + /// + /// rb.append(vec![0, 10, 100]); + /// + /// assert_eq!(rb.select(0), Some(0)); + /// assert_eq!(rb.select(1), Some(10)); + /// assert_eq!(rb.select(2), Some(100)); + /// assert_eq!(rb.select(3), None); + /// ``` + pub fn select(&self, mut n: u64) -> Option { + for (&key, bitmap) in &self.map { + let len = bitmap.len(); + if len > n { + return Some(((key as u64) << 32) | bitmap.select(n as u32).unwrap() as u64); + } + n -= len; + } + + None + } +} + +impl Default for RoaringTreemap { + fn default() -> RoaringTreemap { + RoaringTreemap::new() + } +} + +impl Clone for RoaringTreemap { + fn clone(&self) -> Self { + RoaringTreemap { map: self.map.clone() } + } + + fn clone_from(&mut self, other: &Self) { + self.map.clone_from(&other.map); + } +} diff --git a/vendor/roaring/src/treemap/iter.rs b/vendor/roaring/src/treemap/iter.rs new file mode 100644 index 0000000..b11f1c3 --- /dev/null +++ b/vendor/roaring/src/treemap/iter.rs @@ -0,0 +1,639 @@ +use alloc::collections::{btree_map, BTreeMap}; +use core::iter; +use core::ops::Add; + +use super::util; +use crate::bitmap::IntoIter as IntoIter32; +use crate::bitmap::Iter as Iter32; +use crate::{NonSortedIntegers, RoaringBitmap, RoaringTreemap}; + +struct To64Iter<'a> { + hi: u32, + inner: Iter32<'a>, +} + +impl To64Iter<'_> { + fn advance_to(&mut self, n: u32) { + self.inner.advance_to(n) + } + + fn advance_back_to(&mut self, n: u32) { + self.inner.advance_back_to(n) + } +} + +impl Iterator for To64Iter<'_> { + type Item = u64; + fn next(&mut self) -> Option { + self.inner.next().map(|n| util::join(self.hi, n)) + } + + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, move |b, lo| f(b, ((self.hi as u64) << 32) + (lo as u64))) + } +} + +impl DoubleEndedIterator for To64Iter<'_> { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|n| util::join(self.hi, n)) + } + + #[inline] + fn rfold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.rfold(init, move |b, lo| f(b, ((self.hi as u64) << 32) + (lo as u64))) + } +} + +fn to64iter(t: (u32, &RoaringBitmap)) -> To64Iter<'_> { + To64Iter { hi: t.0, inner: t.1.iter() } +} + +struct To64IntoIter { + hi: u32, + inner: IntoIter32, +} + +impl Iterator for To64IntoIter { + type Item = u64; + fn next(&mut self) -> Option { + self.inner.next().map(|n| util::join(self.hi, n)) + } + + #[inline] + fn fold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, move |b, lo| f(b, ((self.hi as u64) << 32) + (lo as u64))) + } +} + +impl DoubleEndedIterator for To64IntoIter { + fn next_back(&mut self) -> Option { + self.inner.next_back().map(|n| util::join(self.hi, n)) + } + + #[inline] + fn rfold(self, init: B, mut f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.rfold(init, move |b, lo| f(b, ((self.hi as u64) << 32) + (lo as u64))) + } +} + +fn to64intoiter(t: (u32, RoaringBitmap)) -> To64IntoIter { + To64IntoIter { hi: t.0, inner: t.1.into_iter() } +} + +type InnerIntoIter = iter::FlatMap< + btree_map::IntoIter, + To64IntoIter, + fn((u32, RoaringBitmap)) -> To64IntoIter, +>; + +/// An iterator for `RoaringTreemap`. +pub struct Iter<'a> { + outer: BitmapIter<'a>, + front: Option>, + back: Option>, +} + +/// An iterator for `RoaringTreemap`. +pub struct IntoIter { + inner: InnerIntoIter, + size_hint: u64, +} + +impl Iter<'_> { + fn new(map: &'_ BTreeMap) -> Iter<'_> { + let outer = BitmapIter::new(map); + Iter { outer, front: None, back: None } + } + + /// Advance the iterator to the first position where the item has a value >= `n` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// iter.advance_to(2); + /// + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn advance_to(&mut self, n: u64) { + let (key, index) = util::split(n); + + self.outer.advance_to(key); + + if self.front.is_none() { + let Some(next) = self.outer.next() else { + // if the current front iterator is empty or not yet initialized, + // but the outer bitmap iterator is empty, then consume the back + // iterator from the front if it is not also exhausted + if let Some(ref mut back) = self.back { + back.advance_to(index); + } + return; + }; + self.front = Some(to64iter(next)); + } + + if let Some(ref mut front) = self.front { + front.advance_to(index); + } + } + + /// Advance the back of the iterator to the first position where the item has a value <= `n` + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// iter.advance_back_to(1); + /// + /// assert_eq!(iter.next_back(), Some(1)); + /// assert_eq!(iter.next_back(), None); + /// ``` + pub fn advance_back_to(&mut self, n: u64) { + let (key, index) = util::split(n); + + self.outer.advance_back_to(key); + + if self.back.is_none() { + let Some(next_back) = self.outer.next_back() else { + // if the current back iterator is empty or not yet initialized, + // but the outer bitmap iterator is empty, then consume the front + // iterator from the back if it is not also exhausted + if let Some(ref mut front) = self.front { + front.advance_back_to(index); + } + return; + }; + self.back = Some(to64iter(next_back)); + } + + if let Some(ref mut back) = self.back { + back.advance_back_to(index); + } + } +} + +impl IntoIter { + fn new(map: BTreeMap) -> IntoIter { + let size_hint = map.values().map(|r| r.len()).sum(); + let i = map.into_iter().flat_map(to64intoiter as _); + IntoIter { inner: i, size_hint } + } +} + +impl Iterator for Iter<'_> { + type Item = u64; + + fn next(&mut self) -> Option { + if let Some(ref mut front) = &mut self.front { + if let Some(inner) = front.next() { + return Some(inner); + } + } + + let Some(outer_next) = self.outer.next() else { + // if the current front iterator is empty or not yet initialized, + // but the outer bitmap iterator is empty, then consume the back + // iterator from the front if it is not also exhausted + if let Some(ref mut back) = &mut self.back { + if let Some(next) = back.next() { + return Some(next); + } + } + return None; + }; + + self.front = Some(to64iter(outer_next)); + self.next() + } + + fn size_hint(&self) -> (usize, Option) { + let front_size_hint = self.front.as_ref().map_or(0, |f| f.size_hint().0); + let back_size_hint = self.back.as_ref().map_or(0, |b| b.size_hint().0); + + let size_hint = front_size_hint + .saturating_add(back_size_hint) + .saturating_add(self.outer.remaining() as usize); + + (size_hint, Some(size_hint)) + } +} + +impl DoubleEndedIterator for Iter<'_> { + fn next_back(&mut self) -> Option { + if let Some(ref mut back) = &mut self.back { + if let Some(inner) = back.next_back() { + return Some(inner); + } + } + + let Some(outer_next_back) = self.outer.next_back() else { + // if the current back iterator is empty or not yet initialized, + // but the outer bitmap iterator is empty, then consume the front + // iterator from the back if it is not also exhausted + if let Some(ref mut front) = &mut self.front { + if let Some(next_back) = front.next_back() { + return Some(next_back); + } + } + return None; + }; + + self.back = Some(to64iter(outer_next_back)); + self.next_back() + } +} + +#[cfg(target_pointer_width = "64")] +impl ExactSizeIterator for Iter<'_> { + fn len(&self) -> usize { + self.size_hint().0 + } +} + +impl Iterator for IntoIter { + type Item = u64; + + fn next(&mut self) -> Option { + self.size_hint = self.size_hint.saturating_sub(1); + self.inner.next() + } + + fn size_hint(&self) -> (usize, Option) { + if self.size_hint < usize::MAX as u64 { + (self.size_hint as usize, Some(self.size_hint as usize)) + } else { + (usize::MAX, None) + } + } + + #[inline] + fn fold(self, init: B, f: F) -> B + where + Self: Sized, + F: FnMut(B, Self::Item) -> B, + { + self.inner.fold(init, f) + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back(&mut self) -> Option { + self.size_hint = self.size_hint.saturating_sub(1); + self.inner.next_back() + } + + #[inline] + fn rfold(self, init: Acc, fold: Fold) -> Acc + where + Fold: FnMut(Acc, Self::Item) -> Acc, + { + self.inner.rfold(init, fold) + } +} + +#[cfg(target_pointer_width = "64")] +impl ExactSizeIterator for IntoIter { + fn len(&self) -> usize { + self.size_hint as usize + } +} + +impl RoaringTreemap { + /// Iterator over each value stored in the RoaringTreemap, guarantees values are ordered by + /// value. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// use core::iter::FromIterator; + /// + /// let bitmap = (1..3).collect::(); + /// let mut iter = bitmap.iter(); + /// + /// assert_eq!(iter.next(), Some(1)); + /// assert_eq!(iter.next(), Some(2)); + /// assert_eq!(iter.next(), None); + /// ``` + pub fn iter(&'_ self) -> Iter<'_> { + Iter::new(&self.map) + } + + /// Iterator over pairs of partition number and the corresponding RoaringBitmap. + /// The partition number is defined by the 32 most significant bits of the bit index. + /// + /// # Examples + /// + /// ```rust + /// use roaring::{RoaringBitmap, RoaringTreemap}; + /// use core::iter::FromIterator; + /// + /// let original = (0..6000).collect::(); + /// let mut bitmaps = original.bitmaps(); + /// + /// assert_eq!(bitmaps.next(), Some((0, &(0..6000).collect::()))); + /// assert_eq!(bitmaps.next(), None); + /// ``` + pub fn bitmaps(&'_ self) -> BitmapIter<'_> { + BitmapIter::new(&self.map) + } + + /// Construct a RoaringTreemap from an iterator of partition number and RoaringBitmap pairs. + /// The partition number is defined by the 32 most significant bits of the bit index. + /// Note that repeated partitions, if present, will replace previously set partitions. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// use core::iter::FromIterator; + /// + /// let original = (0..6000).collect::(); + /// let clone = RoaringTreemap::from_bitmaps(original.bitmaps().map(|(p, b)| (p, b.clone()))); + /// + /// assert_eq!(clone, original); + /// ``` + pub fn from_bitmaps>(iterator: I) -> Self { + RoaringTreemap { map: iterator.into_iter().collect() } + } +} + +impl<'a> IntoIterator for &'a RoaringTreemap { + type Item = u64; + type IntoIter = Iter<'a>; + + fn into_iter(self) -> Iter<'a> { + self.iter() + } +} + +impl IntoIterator for RoaringTreemap { + type Item = u64; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + IntoIter::new(self.map) + } +} + +impl From<[u64; N]> for RoaringTreemap { + fn from(arr: [u64; N]) -> Self { + RoaringTreemap::from_iter(arr) + } +} + +impl FromIterator for RoaringTreemap { + fn from_iter>(iterator: I) -> RoaringTreemap { + let mut rb = RoaringTreemap::new(); + rb.extend(iterator); + rb + } +} + +impl<'a> FromIterator<&'a u64> for RoaringTreemap { + fn from_iter>(iterator: I) -> RoaringTreemap { + let mut rb = RoaringTreemap::new(); + rb.extend(iterator); + rb + } +} + +impl Extend for RoaringTreemap { + fn extend>(&mut self, iterator: I) { + for value in iterator { + self.insert(value); + } + } +} + +impl<'a> Extend<&'a u64> for RoaringTreemap { + fn extend>(&mut self, iterator: I) { + for value in iterator { + self.insert(*value); + } + } +} + +impl RoaringTreemap { + /// Create the set from a sorted iterator. Values must be sorted and deduplicated. + /// + /// The values of the iterator must be ordered and strictly greater than the greatest value + /// in the set. If a value in the iterator doesn't satisfy this requirement, it is not added + /// and the append operation is stopped. + /// + /// Returns `Ok` with the requested `RoaringTreemap`, `Err` with the number of elements + /// we tried to append before an error occurred. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::from_sorted_iter(0..10).unwrap(); + /// + /// assert!(rb.iter().eq(0..10)); + /// ``` + pub fn from_sorted_iter>( + iterator: I, + ) -> Result { + let mut rt = RoaringTreemap::new(); + rt.append(iterator).map(|_| rt) + } + + /// Extend the set with a sorted iterator. + /// + /// The values of the iterator must be ordered and strictly greater than the greatest value + /// in the set. If a value in the iterator doesn't satisfy this requirement, it is not added + /// and the append operation is stopped. + /// + /// Returns `Ok` with the number of elements appended to the set, `Err` with + /// the number of elements we effectively appended before an error occurred. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let mut rb = RoaringTreemap::new(); + /// rb.append(0..10); + /// + /// assert!(rb.iter().eq(0..10)); + /// ``` + pub fn append>( + &mut self, + iterator: I, + ) -> Result { + let mut iterator = iterator.into_iter(); + let mut prev = match (iterator.next(), self.max()) { + (None, _) => return Ok(0), + (Some(first), Some(max)) if first <= max => { + return Err(NonSortedIntegers { valid_until: 0 }) + } + (Some(first), _) => first, + }; + + // It is now guaranteed that so long as the values of the iterator are + // monotonically increasing they must also be the greatest in the set. + + self.push_unchecked(prev); + + let mut count = 1; + for value in iterator { + if value <= prev { + return Err(NonSortedIntegers { valid_until: count }); + } else { + self.push_unchecked(value); + prev = value; + count += 1; + } + } + + Ok(count) + } +} + +/// An iterator of `RoaringBitmap`s for `RoaringTreemap`. +pub struct BitmapIter<'a> { + treemap: &'a BTreeMap, + range: btree_map::Range<'a, u32, RoaringBitmap>, + latest_front_idx: Option, + latest_back_idx: Option, +} + +impl<'a> BitmapIter<'a> { + fn new(treemap: &'a BTreeMap) -> Self { + let range = treemap.range(..); + Self { treemap, range, latest_back_idx: None, latest_front_idx: None } + } + + fn advance_to(&mut self, new_front_idx: u32) { + match self.latest_back_idx { + Some(latest_back_idx) => match self.latest_front_idx { + Some(last_idx) if last_idx >= new_front_idx => {} + _ => { + // if asked to advance to beyond the back iterator, + // update the self.range iterator to be empty + if new_front_idx >= latest_back_idx { + self.range = self.treemap.range(0..1); + self.range.next_back(); + } else { + // otherwise shrink the remaining range from the front + self.range = self.treemap.range(new_front_idx..latest_back_idx); + } + + // self.range = self.treemap.range(new_front_idx..latest_back_idx); + } + }, + None => match self.latest_front_idx { + Some(latest_idx) if latest_idx >= new_front_idx => {} + _ => { + self.range = self.treemap.range(new_front_idx..); + } + }, + } + } + + fn advance_back_to(&mut self, new_back_idx: u32) { + match self.latest_front_idx { + Some(latest_front_idx) => match self.latest_back_idx { + // do nothing if asked to advance back to a higher index than the back is already at + Some(latest_back_idx) if latest_back_idx <= new_back_idx => {} + _ => { + // if asked to advance back to beyond the front iterator, + // update the self.range iterator to be empty + if new_back_idx <= latest_front_idx { + self.range = self.treemap.range(0..1); + self.range.next_back(); + } else { + // otherwise shrink the remaining range from the back + self.range = self.treemap.range((latest_front_idx + 1)..new_back_idx); + } + } + }, + None => match self.latest_back_idx { + Some(latest_back_idx) if latest_back_idx <= new_back_idx => {} + _ => { + self.range = self.treemap.range(..=new_back_idx); + } + }, + } + } + + fn remaining(&self) -> u64 { + let range = self.range.clone(); + range.fold(0, |acc, (_, bitmap)| acc.add(bitmap.len())) + } +} + +impl<'a> Iterator for BitmapIter<'a> { + type Item = (u32, &'a RoaringBitmap); + + fn next(&mut self) -> Option { + match self.range.next().map(|(&p, b)| (p, b)) { + None => { + self.latest_front_idx = None; + None + } + Some((next_idx, next_map)) => { + self.latest_front_idx = Some(next_idx); + Some((next_idx, next_map)) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + self.range.size_hint() + } +} + +impl FromIterator<(u32, RoaringBitmap)> for RoaringTreemap { + fn from_iter>(iterator: I) -> RoaringTreemap { + Self::from_bitmaps(iterator) + } +} + +impl DoubleEndedIterator for BitmapIter<'_> { + fn next_back(&mut self) -> Option { + match self.range.next_back().map(|(&p, b)| (p, b)) { + None => { + self.latest_back_idx = None; + None + } + Some((next_back_idx, next_back_map)) => { + self.latest_back_idx = Some(next_back_idx); + Some((next_back_idx, next_back_map)) + } + } + } +} diff --git a/vendor/roaring/src/treemap/mod.rs b/vendor/roaring/src/treemap/mod.rs new file mode 100644 index 0000000..93ca126 --- /dev/null +++ b/vendor/roaring/src/treemap/mod.rs @@ -0,0 +1,42 @@ +use crate::RoaringBitmap; +use alloc::collections::BTreeMap; + +mod fmt; +mod multiops; +mod util; + +// Order of these modules matters as it determines the `impl` blocks order in +// the docs +mod arbitrary; +mod cmp; +mod inherent; +mod iter; +mod ops; +#[cfg(feature = "serde")] +mod serde; +#[cfg(feature = "std")] +mod serialization; + +pub use self::iter::{BitmapIter, IntoIter, Iter}; + +/// A compressed bitmap with u64 values. +/// Implemented as a `BTreeMap` of `RoaringBitmap`s. +/// +/// # Examples +/// +/// ```rust +/// use roaring::RoaringTreemap; +/// +/// let mut rb = RoaringTreemap::new(); +/// +/// // insert all primes less than 10 +/// rb.insert(2); +/// rb.insert(3); +/// rb.insert(5); +/// rb.insert(7); +/// println!("total bits set to true: {}", rb.len()); +/// ``` +#[derive(PartialEq, Eq)] +pub struct RoaringTreemap { + map: BTreeMap, +} diff --git a/vendor/roaring/src/treemap/multiops.rs b/vendor/roaring/src/treemap/multiops.rs new file mode 100644 index 0000000..3a0adba --- /dev/null +++ b/vendor/roaring/src/treemap/multiops.rs @@ -0,0 +1,376 @@ +use alloc::collections::{binary_heap::PeekMut, BTreeMap, BinaryHeap}; +use core::{borrow::Borrow, cmp::Ordering, mem}; + +use crate::{MultiOps, RoaringBitmap, RoaringTreemap}; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl MultiOps for I +where + I: IntoIterator, +{ + type Output = RoaringTreemap; + + fn union(self) -> Self::Output { + try_simple_multi_op_owned::<_, _, UnionOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } + + fn intersection(self) -> Self::Output { + try_ordered_multi_op_owned::<_, _, IntersectionOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } + + fn difference(self) -> Self::Output { + try_ordered_multi_op_owned::<_, _, DifferenceOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } + + fn symmetric_difference(self) -> Self::Output { + try_simple_multi_op_owned::<_, _, SymmetricDifferenceOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } +} + +impl MultiOps> for I +where + I: IntoIterator>, +{ + type Output = Result; + + fn union(self) -> Self::Output { + try_simple_multi_op_owned::<_, _, UnionOp>(self) + } + + fn intersection(self) -> Self::Output { + try_ordered_multi_op_owned::<_, _, IntersectionOp>(self) + } + + fn difference(self) -> Self::Output { + try_ordered_multi_op_owned::<_, _, DifferenceOp>(self) + } + + fn symmetric_difference(self) -> Self::Output { + try_simple_multi_op_owned::<_, _, SymmetricDifferenceOp>(self) + } +} + +#[inline] +fn try_simple_multi_op_owned(treemaps: I) -> Result +where + I: IntoIterator>, +{ + let treemaps = treemaps.into_iter().collect::, _>>()?; + + let mut heap: BinaryHeap<_> = treemaps + .into_iter() + .filter_map(|treemap| { + let mut iter = treemap.map.into_iter(); + iter.next().map(|(key, bitmap)| PeekedRoaringBitmap { key, bitmap, iter }) + }) + .collect(); + + let mut bitmaps = Vec::new(); + let mut map = BTreeMap::new(); + + while let Some(mut peek) = heap.peek_mut() { + let (key, bitmap) = match peek.iter.next() { + Some((next_key, next_bitmap)) => { + let key = peek.key; + peek.key = next_key; + let bitmap = mem::replace(&mut peek.bitmap, next_bitmap); + (key, bitmap) + } + None => { + let popped = PeekMut::pop(peek); + (popped.key, popped.bitmap) + } + }; + + if let Some((first_key, _)) = bitmaps.first() { + if *first_key != key { + let current_key = *first_key; + let computed_bitmap = O::op_owned(bitmaps.drain(..).map(|(_, rb)| rb)); + if !computed_bitmap.is_empty() { + map.insert(current_key, computed_bitmap); + } + } + } + + bitmaps.push((key, bitmap)); + } + + if let Some((first_key, _)) = bitmaps.first() { + let current_key = *first_key; + let computed_bitmap = O::op_owned(bitmaps.drain(..).map(|(_, rb)| rb)); + if !computed_bitmap.is_empty() { + map.insert(current_key, computed_bitmap); + } + } + + Ok(RoaringTreemap { map }) +} + +#[inline] +fn try_ordered_multi_op_owned(treemaps: I) -> Result +where + I: IntoIterator>, +{ + let mut treemaps = treemaps.into_iter(); + let mut treemap = match treemaps.next().transpose()? { + Some(treemap) => treemap, + None => return Ok(RoaringTreemap::new()), + }; + let mut treemaps = treemaps.collect::, _>>()?; + + // for each key in the first treemap we're going to find and + // accumulate all the corresponding bitmaps + let keys: Vec<_> = treemap.map.keys().copied().collect(); + for k in keys { + // the unwrap is safe since we're iterating on our keys + let current_bitmap = treemap.map.remove(&k).unwrap(); + let new_bitmap = + O::op_owned(core::iter::once(current_bitmap).chain( + treemaps.iter_mut().map(|treemap| treemap.map.remove(&k).unwrap_or_default()), + )); + if !new_bitmap.is_empty() { + treemap.map.insert(k, new_bitmap); + } + } + + Ok(treemap) +} + +#[inline] +fn try_ordered_multi_op_ref<'a, E: 'a, I, O: Op>(treemaps: I) -> Result +where + I: IntoIterator>, +{ + let mut treemaps = treemaps.into_iter(); + let treemap = match treemaps.next().transpose()? { + Some(treemap) => treemap, + None => return Ok(RoaringTreemap::new()), + }; + let treemaps = treemaps.collect::, _>>()?; + + let mut ret = RoaringTreemap::new(); + + // for each keys in the first treemap we're going find and accumulate all the corresponding bitmaps + let keys: Vec<_> = treemap.map.keys().copied().collect(); + let empty_bitmap = RoaringBitmap::new(); + for k in keys { + // the unwrap is safe since we're iterating on our keys + let current_bitmap = treemap.map.get(&k).unwrap(); + let new_bitmap = O::op_ref( + core::iter::once(current_bitmap) + .chain(treemaps.iter().map(|treemap| treemap.map.get(&k).unwrap_or(&empty_bitmap))), + ); + if !new_bitmap.is_empty() { + ret.map.insert(k, new_bitmap); + } + } + + Ok(ret) +} + +#[inline] +fn try_simple_multi_op_ref<'a, E: 'a, I, O: Op>(treemaps: I) -> Result +where + I: IntoIterator>, +{ + let treemaps = treemaps.into_iter().collect::, E>>()?; + + let mut heap: BinaryHeap<_> = treemaps + .into_iter() + .filter_map(|treemap| { + let mut iter = treemap.map.iter(); + iter.next().map(|(&key, bitmap)| PeekedRoaringBitmap { key, bitmap, iter }) + }) + .collect(); + + let mut bitmaps = Vec::new(); + let mut map = BTreeMap::new(); + + while let Some(mut peek) = heap.peek_mut() { + let (key, bitmap) = match peek.iter.next() { + Some((&next_key, next_bitmap)) => { + let key = peek.key; + peek.key = next_key; + let bitmap = mem::replace(&mut peek.bitmap, next_bitmap); + (key, bitmap) + } + None => { + let popped = PeekMut::pop(peek); + (popped.key, popped.bitmap) + } + }; + + if let Some((first_key, _)) = bitmaps.first() { + if *first_key != key { + let current_key = *first_key; + let computed_bitmap = O::op_ref(bitmaps.drain(..).map(|(_, rb)| rb)); + if !computed_bitmap.is_empty() { + map.insert(current_key, computed_bitmap); + } + } + } + + bitmaps.push((key, bitmap)); + } + + if let Some((first_key, _)) = bitmaps.first() { + let current_key = *first_key; + let computed_bitmap = O::op_ref(bitmaps.drain(..).map(|(_, rb)| rb)); + if !computed_bitmap.is_empty() { + map.insert(current_key, computed_bitmap); + } + } + + Ok(RoaringTreemap { map }) +} + +trait Op { + fn op_owned>(iter: I) -> RoaringBitmap; + fn op_ref<'a, I: IntoIterator>(iter: I) -> RoaringBitmap; +} + +enum UnionOp {} + +impl Op for UnionOp { + fn op_owned>(iter: J) -> RoaringBitmap { + iter.union() + } + + fn op_ref<'a, J: IntoIterator>(iter: J) -> RoaringBitmap { + iter.union() + } +} + +enum IntersectionOp {} + +impl Op for IntersectionOp { + fn op_owned>(iter: J) -> RoaringBitmap { + iter.intersection() + } + + fn op_ref<'a, J: IntoIterator>(iter: J) -> RoaringBitmap { + iter.intersection() + } +} + +enum DifferenceOp {} + +impl Op for DifferenceOp { + fn op_owned>(iter: J) -> RoaringBitmap { + iter.difference() + } + + fn op_ref<'a, J: IntoIterator>(iter: J) -> RoaringBitmap { + iter.difference() + } +} + +enum SymmetricDifferenceOp {} + +impl Op for SymmetricDifferenceOp { + fn op_owned>(iter: J) -> RoaringBitmap { + iter.symmetric_difference() + } + + fn op_ref<'a, J: IntoIterator>(iter: J) -> RoaringBitmap { + iter.symmetric_difference() + } +} + +impl<'a, I> MultiOps<&'a RoaringTreemap> for I +where + I: IntoIterator, +{ + type Output = RoaringTreemap; + + fn union(self) -> Self::Output { + try_simple_multi_op_ref::<_, _, UnionOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } + + fn intersection(self) -> Self::Output { + try_ordered_multi_op_ref::<_, _, IntersectionOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } + + fn difference(self) -> Self::Output { + try_ordered_multi_op_ref::<_, _, DifferenceOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } + + fn symmetric_difference(self) -> Self::Output { + try_simple_multi_op_ref::<_, _, SymmetricDifferenceOp>( + self.into_iter().map(Ok::<_, core::convert::Infallible>), + ) + .unwrap() + } +} + +impl<'a, I, E: 'a> MultiOps> for I +where + I: IntoIterator>, +{ + type Output = Result; + + fn union(self) -> Self::Output { + try_simple_multi_op_ref::<_, _, UnionOp>(self) + } + + fn intersection(self) -> Self::Output { + try_ordered_multi_op_ref::<_, _, IntersectionOp>(self) + } + + fn difference(self) -> Self::Output { + try_ordered_multi_op_ref::<_, _, DifferenceOp>(self) + } + + fn symmetric_difference(self) -> Self::Output { + try_simple_multi_op_ref::<_, _, SymmetricDifferenceOp>(self) + } +} + +struct PeekedRoaringBitmap { + key: u32, + bitmap: R, + iter: I, +} + +impl, I> Ord for PeekedRoaringBitmap { + fn cmp(&self, other: &Self) -> Ordering { + self.key.cmp(&other.key).reverse() + } +} + +impl, I> PartialOrd for PeekedRoaringBitmap { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl, I> Eq for PeekedRoaringBitmap {} + +impl, I> PartialEq for PeekedRoaringBitmap { + fn eq(&self, other: &Self) -> bool { + self.key == other.key + } +} diff --git a/vendor/roaring/src/treemap/ops.rs b/vendor/roaring/src/treemap/ops.rs new file mode 100644 index 0000000..9bf9a5a --- /dev/null +++ b/vendor/roaring/src/treemap/ops.rs @@ -0,0 +1,544 @@ +use alloc::collections::btree_map::Entry; +use core::mem; +use core::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign}; + +use crate::RoaringTreemap; + +#[cfg(not(feature = "std"))] +use alloc::vec::Vec; + +impl RoaringTreemap { + /// Computes the len of the union with the specified other treemap without creating a new + /// treemap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the union. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let rb2: RoaringTreemap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.union_len(&rb2), (rb1 | rb2).len()); + /// ``` + pub fn union_len(&self, other: &RoaringTreemap) -> u64 { + self.len().wrapping_add(other.len()).wrapping_sub(self.intersection_len(other)) + } + + /// Computes the len of the intersection with the specified other treemap without creating a + /// new treemap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the intersection. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let rb2: RoaringTreemap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.intersection_len(&rb2), (rb1 & rb2).len()); + /// ``` + pub fn intersection_len(&self, other: &RoaringTreemap) -> u64 { + self.pairs(other) + .map(|pair| match pair { + (Some(..), None) => 0, + (None, Some(..)) => 0, + (Some(lhs), Some(rhs)) => lhs.intersection_len(rhs), + (None, None) => 0, + }) + .sum() + } + + /// Computes the len of the difference with the specified other treemap without creating a new + /// treemap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the difference. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let rb2: RoaringTreemap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.difference_len(&rb2), (rb1 - rb2).len()); + /// ``` + pub fn difference_len(&self, other: &RoaringTreemap) -> u64 { + self.len() - self.intersection_len(other) + } + + /// Computes the len of the symmetric difference with the specified other treemap without + /// creating a new bitmap. + /// + /// This is faster and more space efficient when you're only interested in the cardinality of + /// the symmetric difference. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let rb2: RoaringTreemap = (3..5).collect(); + /// + /// + /// assert_eq!(rb1.symmetric_difference_len(&rb2), (rb1 ^ rb2).len()); + /// ``` + pub fn symmetric_difference_len(&self, other: &RoaringTreemap) -> u64 { + let intersection_len = self.intersection_len(other); + + self.len() + .wrapping_add(other.len()) + .wrapping_sub(intersection_len) + .wrapping_sub(intersection_len) + } +} + +impl BitOr for RoaringTreemap { + type Output = RoaringTreemap; + + /// An `union` between two sets. + fn bitor(mut self, rhs: RoaringTreemap) -> RoaringTreemap { + BitOrAssign::bitor_assign(&mut self, rhs); + self + } +} + +impl BitOr<&RoaringTreemap> for RoaringTreemap { + type Output = RoaringTreemap; + + /// An `union` between two sets. + fn bitor(mut self, rhs: &RoaringTreemap) -> RoaringTreemap { + BitOrAssign::bitor_assign(&mut self, rhs); + self + } +} + +impl BitOr for &RoaringTreemap { + type Output = RoaringTreemap; + + /// An `union` between two sets. + fn bitor(self, rhs: RoaringTreemap) -> RoaringTreemap { + BitOr::bitor(rhs, self) + } +} + +impl BitOr<&RoaringTreemap> for &RoaringTreemap { + type Output = RoaringTreemap; + + /// An `union` between two sets. + fn bitor(self, rhs: &RoaringTreemap) -> RoaringTreemap { + if self.len() <= rhs.len() { + BitOr::bitor(rhs.clone(), self) + } else { + BitOr::bitor(self.clone(), rhs) + } + } +} + +impl BitOrAssign for RoaringTreemap { + /// An `union` between two sets. + fn bitor_assign(&mut self, mut rhs: RoaringTreemap) { + // We make sure that we apply the union operation on the biggest map. + if self.len() < rhs.len() { + mem::swap(self, &mut rhs); + } + + for (key, other_rb) in rhs.map { + match self.map.entry(key) { + Entry::Vacant(ent) => { + ent.insert(other_rb); + } + Entry::Occupied(mut ent) => { + BitOrAssign::bitor_assign(ent.get_mut(), other_rb); + } + } + } + } +} + +impl BitOrAssign<&RoaringTreemap> for RoaringTreemap { + /// An `union` between two sets. + fn bitor_assign(&mut self, rhs: &RoaringTreemap) { + for (key, other_rb) in &rhs.map { + match self.map.entry(*key) { + Entry::Vacant(ent) => { + ent.insert(other_rb.clone()); + } + Entry::Occupied(mut ent) => { + BitOrAssign::bitor_assign(ent.get_mut(), other_rb); + } + } + } + } +} + +impl BitAnd for RoaringTreemap { + type Output = RoaringTreemap; + + /// An `intersection` between two sets. + fn bitand(mut self, rhs: RoaringTreemap) -> RoaringTreemap { + BitAndAssign::bitand_assign(&mut self, rhs); + self + } +} + +impl BitAnd<&RoaringTreemap> for RoaringTreemap { + type Output = RoaringTreemap; + + /// An `intersection` between two sets. + fn bitand(mut self, rhs: &RoaringTreemap) -> RoaringTreemap { + BitAndAssign::bitand_assign(&mut self, rhs); + self + } +} + +impl BitAnd for &RoaringTreemap { + type Output = RoaringTreemap; + + /// An `intersection` between two sets. + fn bitand(self, rhs: RoaringTreemap) -> RoaringTreemap { + BitAnd::bitand(rhs, self) + } +} + +impl BitAnd<&RoaringTreemap> for &RoaringTreemap { + type Output = RoaringTreemap; + + /// An `intersection` between two sets. + fn bitand(self, rhs: &RoaringTreemap) -> RoaringTreemap { + if rhs.len() < self.len() { + BitAnd::bitand(self.clone(), rhs) + } else { + BitAnd::bitand(rhs.clone(), self) + } + } +} + +impl BitAndAssign for RoaringTreemap { + /// An `intersection` between two sets. + fn bitand_assign(&mut self, mut rhs: RoaringTreemap) { + // We make sure that we apply the intersection operation on the smallest map. + if rhs.len() < self.len() { + mem::swap(self, &mut rhs); + } + + BitAndAssign::bitand_assign(self, &rhs) + } +} + +impl BitAndAssign<&RoaringTreemap> for RoaringTreemap { + /// An `intersection` between two sets. + fn bitand_assign(&mut self, rhs: &RoaringTreemap) { + let mut keys_to_remove: Vec = Vec::new(); + for (key, self_rb) in &mut self.map { + match rhs.map.get(key) { + Some(other_rb) => { + BitAndAssign::bitand_assign(self_rb, other_rb); + if self_rb.is_empty() { + keys_to_remove.push(*key); + } + } + None => keys_to_remove.push(*key), + } + } + + for key in keys_to_remove { + self.map.remove(&key); + } + } +} + +impl Sub for RoaringTreemap { + type Output = RoaringTreemap; + + /// A `difference` between two sets. + fn sub(mut self, rhs: RoaringTreemap) -> RoaringTreemap { + SubAssign::sub_assign(&mut self, rhs); + self + } +} + +impl Sub<&RoaringTreemap> for RoaringTreemap { + type Output = RoaringTreemap; + + /// A `difference` between two sets. + fn sub(mut self, rhs: &RoaringTreemap) -> RoaringTreemap { + SubAssign::sub_assign(&mut self, rhs); + self + } +} + +impl Sub for &RoaringTreemap { + type Output = RoaringTreemap; + + /// A `difference` between two sets. + fn sub(self, rhs: RoaringTreemap) -> RoaringTreemap { + Sub::sub(self.clone(), rhs) + } +} + +impl Sub<&RoaringTreemap> for &RoaringTreemap { + type Output = RoaringTreemap; + + /// A `difference` between two sets. + fn sub(self, rhs: &RoaringTreemap) -> RoaringTreemap { + Sub::sub(self.clone(), rhs) + } +} + +impl SubAssign for RoaringTreemap { + /// A `difference` between two sets. + fn sub_assign(&mut self, rhs: RoaringTreemap) { + SubAssign::sub_assign(self, &rhs) + } +} + +impl SubAssign<&RoaringTreemap> for RoaringTreemap { + /// A `difference` between two sets. + fn sub_assign(&mut self, rhs: &RoaringTreemap) { + for (key, rhs_rb) in &rhs.map { + match self.map.entry(*key) { + Entry::Vacant(_entry) => (), + Entry::Occupied(mut entry) => { + SubAssign::sub_assign(entry.get_mut(), rhs_rb); + if entry.get().is_empty() { + entry.remove_entry(); + } + } + } + } + } +} + +impl BitXor for RoaringTreemap { + type Output = RoaringTreemap; + + /// A `symmetric difference` between two sets. + fn bitxor(mut self, rhs: RoaringTreemap) -> RoaringTreemap { + BitXorAssign::bitxor_assign(&mut self, rhs); + self + } +} + +impl BitXor<&RoaringTreemap> for RoaringTreemap { + type Output = RoaringTreemap; + + /// A `symmetric difference` between two sets. + fn bitxor(mut self, rhs: &RoaringTreemap) -> RoaringTreemap { + BitXorAssign::bitxor_assign(&mut self, rhs); + self + } +} + +impl BitXor for &RoaringTreemap { + type Output = RoaringTreemap; + + /// A `symmetric difference` between two sets. + fn bitxor(self, rhs: RoaringTreemap) -> RoaringTreemap { + BitXor::bitxor(rhs, self) + } +} + +impl BitXor<&RoaringTreemap> for &RoaringTreemap { + type Output = RoaringTreemap; + + /// A `symmetric difference` between two sets. + fn bitxor(self, rhs: &RoaringTreemap) -> RoaringTreemap { + if self.len() < rhs.len() { + BitXor::bitxor(self, rhs.clone()) + } else { + BitXor::bitxor(self.clone(), rhs) + } + } +} + +impl BitXorAssign for RoaringTreemap { + /// A `symmetric difference` between two sets. + fn bitxor_assign(&mut self, rhs: RoaringTreemap) { + for (key, other_rb) in rhs.map { + match self.map.entry(key) { + Entry::Vacant(entry) => { + entry.insert(other_rb); + } + Entry::Occupied(mut entry) => { + BitXorAssign::bitxor_assign(entry.get_mut(), other_rb); + if entry.get().is_empty() { + entry.remove_entry(); + } + } + } + } + } +} + +impl BitXorAssign<&RoaringTreemap> for RoaringTreemap { + /// A `symmetric difference` between two sets. + fn bitxor_assign(&mut self, rhs: &RoaringTreemap) { + for (key, other_rb) in &rhs.map { + match self.map.entry(*key) { + Entry::Vacant(entry) => { + entry.insert(other_rb.clone()); + } + Entry::Occupied(mut entry) => { + BitXorAssign::bitxor_assign(entry.get_mut(), other_rb); + if entry.get().is_empty() { + entry.remove_entry(); + } + } + } + } + } +} + +#[cfg(test)] +mod test { + use crate::{MultiOps, RoaringTreemap}; + use proptest::prelude::*; + + // fast count tests + proptest! { + #[test] + fn union_len_eq_len_of_materialized_union( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary() + ) { + prop_assert_eq!(a.union_len(&b), (a | b).len()); + } + + #[test] + fn intersection_len_eq_len_of_materialized_intersection( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary() + ) { + prop_assert_eq!(a.intersection_len(&b), (a & b).len()); + } + + #[test] + fn difference_len_eq_len_of_materialized_difference( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary() + ) { + prop_assert_eq!(a.difference_len(&b), (a - b).len()); + } + + #[test] + fn symmetric_difference_len_eq_len_of_materialized_symmetric_difference( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary() + ) { + prop_assert_eq!(a.symmetric_difference_len(&b), (a ^ b).len()); + } + + #[test] + fn all_union_give_the_same_result( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary(), + c in RoaringTreemap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign |= &b; + ref_assign |= &c; + + let mut own_assign = a.clone(); + own_assign |= b.clone(); + own_assign |= c.clone(); + + let ref_inline = &a | &b | &c; + let own_inline = a.clone() | b.clone() | c.clone(); + + let ref_multiop = [&a, &b, &c].union(); + let own_multiop = [a, b.clone(), c.clone()].union(); + + for roar in &[own_assign, ref_inline, own_inline, ref_multiop, own_multiop] { + prop_assert_eq!(&ref_assign, roar); + } + } + + #[test] + fn all_intersection_give_the_same_result( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary(), + c in RoaringTreemap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign &= &b; + ref_assign &= &c; + + let mut own_assign = a.clone(); + own_assign &= b.clone(); + own_assign &= c.clone(); + + let ref_inline = &a & &b & &c; + let own_inline = a.clone() & b.clone() & c.clone(); + + let ref_multiop = [&a, &b, &c].intersection(); + let own_multiop = [a, b.clone(), c.clone()].intersection(); + + for roar in &[own_assign, ref_inline, own_inline, ref_multiop, own_multiop] { + prop_assert_eq!(&ref_assign, roar); + } + } + + #[test] + fn all_difference_give_the_same_result( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary(), + c in RoaringTreemap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign -= &b; + ref_assign -= &c; + + let mut own_assign = a.clone(); + own_assign -= b.clone(); + own_assign -= c.clone(); + + let ref_inline = &a - &b - &c; + let own_inline = a.clone() - b.clone() - c.clone(); + + let ref_multiop = [&a, &b, &c].difference(); + let own_multiop = [a, b.clone(), c.clone()].difference(); + + for roar in &[own_assign, ref_inline, own_inline, ref_multiop, own_multiop] { + prop_assert_eq!(&ref_assign, roar); + } + } + + #[test] + fn all_symmetric_difference_give_the_same_result( + a in RoaringTreemap::arbitrary(), + b in RoaringTreemap::arbitrary(), + c in RoaringTreemap::arbitrary() + ) { + let mut ref_assign = a.clone(); + ref_assign ^= &b; + ref_assign ^= &c; + + let mut own_assign = a.clone(); + own_assign ^= b.clone(); + own_assign ^= c.clone(); + + let ref_inline = &a ^ &b ^ &c; + let own_inline = a.clone() ^ b.clone() ^ c.clone(); + + let ref_multiop = [&a, &b, &c].symmetric_difference(); + let own_multiop = [a, b.clone(), c.clone()].symmetric_difference(); + + for roar in &[own_assign, ref_inline, own_inline, ref_multiop, own_multiop] { + prop_assert_eq!(&ref_assign, roar); + } + } + } +} diff --git a/vendor/roaring/src/treemap/serde.rs b/vendor/roaring/src/treemap/serde.rs new file mode 100644 index 0000000..6cec735 --- /dev/null +++ b/vendor/roaring/src/treemap/serde.rs @@ -0,0 +1,82 @@ +use serde::de::SeqAccess; +use serde::de::Visitor; +use serde::Deserialize; +use serde::Deserializer; +use serde::Serialize; + +use crate::RoaringTreemap; + +impl<'de> Deserialize<'de> for RoaringTreemap { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TreemapVisitor; + + impl<'de> Visitor<'de> for TreemapVisitor { + type Value = RoaringTreemap; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("roaring bitmap") + } + + fn visit_bytes(self, bytes: &[u8]) -> Result + where + E: serde::de::Error, + { + RoaringTreemap::deserialize_from(bytes).map_err(serde::de::Error::custom) + } + + // in some case bytes will be serialized as a sequence thus we need to accept both + // even if it means non optimal performance + fn visit_seq(self, mut seq: A) -> Result + where + A: SeqAccess<'de>, + { + let mut bytes: Vec = Vec::new(); + while let Some(el) = seq.next_element()? { + bytes.push(el); + } + RoaringTreemap::deserialize_from(&*bytes).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_bytes(TreemapVisitor) + } +} + +impl Serialize for RoaringTreemap { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut buf = Vec::new(); + self.serialize_into(&mut buf).map_err(serde::ser::Error::custom)?; + + serializer.serialize_bytes(&buf) + } +} + +#[cfg(test)] +mod test { + use crate::RoaringTreemap; + use proptest::prelude::*; + + proptest! { + #[test] + fn test_serde_json( + treemap in RoaringTreemap::arbitrary(), + ) { + let json = serde_json::to_vec(&treemap).unwrap(); + prop_assert_eq!(treemap, serde_json::from_slice(&json).unwrap()); + } + + #[test] + fn test_postcard( + treemap in RoaringTreemap::arbitrary(), + ) { + let buffer = postcard::to_allocvec(&treemap).unwrap(); + prop_assert_eq!(treemap, postcard::from_bytes(&buffer).unwrap()); + } + } +} diff --git a/vendor/roaring/src/treemap/serialization.rs b/vendor/roaring/src/treemap/serialization.rs new file mode 100644 index 0000000..2ab50f8 --- /dev/null +++ b/vendor/roaring/src/treemap/serialization.rs @@ -0,0 +1,135 @@ +use super::RoaringTreemap; +use crate::RoaringBitmap; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::{io, mem::size_of}; + +impl RoaringTreemap { + /// Return the size in bytes of the serialized output. + /// This is compatible with the official C/C++, Java and Go implementations. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let mut bytes = Vec::with_capacity(rb1.serialized_size()); + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringTreemap::deserialize_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn serialized_size(&self) -> usize { + self.map + .values() + .fold(size_of::(), |acc, bitmap| acc + size_of::() + bitmap.serialized_size()) + } + + /// Serialize this bitmap. + /// This is compatible with the official C/C++, Java and Go implementations. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let mut bytes = vec![]; + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringTreemap::deserialize_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn serialize_into(&self, mut writer: W) -> io::Result<()> { + writer.write_u64::(self.map.len() as u64)?; + + for (key, bitmap) in &self.map { + writer.write_u32::(*key)?; + bitmap.serialize_into(&mut writer)?; + } + + Ok(()) + } + + /// Deserialize a bitmap into memory. + /// + /// This is compatible with the official C/C++, Java and Go implementations. + /// This method checks that all of the internal values are valid. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let mut bytes = vec![]; + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringTreemap::deserialize_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn deserialize_from(reader: R) -> io::Result { + RoaringTreemap::deserialize_from_impl(reader, |reader| { + RoaringBitmap::deserialize_from(reader) + }) + } + + /// Deserialize a bitmap into memory. + /// + /// This is compatible with the official C/C++, Java and Go implementations. + /// This method is memory safe but will not check if the data is a valid bitmap. + /// + /// # Examples + /// + /// ```rust + /// use roaring::RoaringTreemap; + /// + /// let rb1: RoaringTreemap = (1..4).collect(); + /// let mut bytes = vec![]; + /// rb1.serialize_into(&mut bytes).unwrap(); + /// let rb2 = RoaringTreemap::deserialize_unchecked_from(&bytes[..]).unwrap(); + /// + /// assert_eq!(rb1, rb2); + /// ``` + pub fn deserialize_unchecked_from(reader: R) -> io::Result { + RoaringTreemap::deserialize_from_impl(reader, |reader| { + RoaringBitmap::deserialize_unchecked_from(reader) + }) + } + + fn deserialize_from_impl(mut reader: R, mut deserialize_bitmap: F) -> io::Result + where + R: io::Read, + F: FnMut(&mut R) -> io::Result, + { + let size = reader.read_u64::()?; + + let mut s = Self::new(); + + for _ in 0..size { + let key = reader.read_u32::()?; + let bitmap = deserialize_bitmap(&mut reader)?; + + s.map.insert(key, bitmap); + } + + Ok(s) + } +} + +#[cfg(test)] +mod test { + use crate::RoaringTreemap; + use proptest::prelude::*; + + proptest! { + #[test] + fn test_serialization( + treemap in RoaringTreemap::arbitrary(), + ) { + let mut buffer = Vec::new(); + treemap.serialize_into(&mut buffer).unwrap(); + prop_assert_eq!(treemap, RoaringTreemap::deserialize_from(buffer.as_slice()).unwrap()); + } + } +} diff --git a/vendor/roaring/src/treemap/util.rs b/vendor/roaring/src/treemap/util.rs new file mode 100644 index 0000000..55839c6 --- /dev/null +++ b/vendor/roaring/src/treemap/util.rs @@ -0,0 +1,72 @@ +use core::ops::{Bound, RangeBounds, RangeInclusive}; + +#[inline] +pub fn split(value: u64) -> (u32, u32) { + ((value >> 32) as u32, value as u32) +} + +#[inline] +pub fn join(high: u32, low: u32) -> u64 { + (u64::from(high) << 32) | u64::from(low) +} + +/// Convert a `RangeBounds` object to `RangeInclusive`, +pub fn convert_range_to_inclusive(range: R) -> Option> +where + R: RangeBounds, +{ + let start: u64 = match range.start_bound() { + Bound::Included(&i) => i, + Bound::Excluded(&u64::MAX) => return None, + Bound::Excluded(&i) => i + 1, + Bound::Unbounded => 0, + }; + let end: u64 = match range.end_bound() { + Bound::Included(&i) => i, + Bound::Excluded(&0) => return None, + Bound::Excluded(&i) => i - 1, + Bound::Unbounded => u64::MAX, + }; + if end < start { + return None; + } + Some(start..=end) +} + +#[cfg(test)] +mod test { + use super::{convert_range_to_inclusive, join, split}; + + #[test] + fn test_split_u64() { + assert_eq!((0x0000_0000u32, 0x0000_0000u32), split(0x0000_0000_0000_0000u64)); + assert_eq!((0x0000_0000u32, 0x0000_0001u32), split(0x0000_0000_0000_0001u64)); + assert_eq!((0x0000_0000u32, 0xFFFF_FFFEu32), split(0x0000_0000_FFFF_FFFEu64)); + assert_eq!((0x0000_0000u32, 0xFFFF_FFFFu32), split(0x0000_0000_FFFF_FFFFu64)); + assert_eq!((0x0000_0001u32, 0x0000_0000u32), split(0x0000_0001_0000_0000u64)); + assert_eq!((0x0000_0001u32, 0x0000_0001u32), split(0x0000_0001_0000_0001u64)); + assert_eq!((0xFFFF_FFFFu32, 0xFFFF_FFFEu32), split(0xFFFF_FFFF_FFFF_FFFEu64)); + assert_eq!((0xFFFF_FFFFu32, 0xFFFF_FFFFu32), split(0xFFFF_FFFF_FFFF_FFFFu64)); + } + + #[test] + fn test_join_u64() { + assert_eq!(0x0000_0000_0000_0000u64, join(0x0000_0000u32, 0x0000_0000u32)); + assert_eq!(0x0000_0000_0000_0001u64, join(0x0000_0000u32, 0x0000_0001u32)); + assert_eq!(0x0000_0000_FFFF_FFFEu64, join(0x0000_0000u32, 0xFFFF_FFFEu32)); + assert_eq!(0x0000_0000_FFFF_FFFFu64, join(0x0000_0000u32, 0xFFFF_FFFFu32)); + assert_eq!(0x0000_0001_0000_0000u64, join(0x0000_0001u32, 0x0000_0000u32)); + assert_eq!(0x0000_0001_0000_0001u64, join(0x0000_0001u32, 0x0000_0001u32)); + assert_eq!(0xFFFF_FFFF_FFFF_FFFEu64, join(0xFFFF_FFFFu32, 0xFFFF_FFFEu32)); + assert_eq!(0xFFFF_FFFF_FFFF_FFFFu64, join(0xFFFF_FFFFu32, 0xFFFF_FFFFu32)); + } + + #[test] + fn test_convert_range_to_inclusive() { + assert_eq!(Some(1..=5), convert_range_to_inclusive(1..6)); + assert_eq!(Some(1..=u64::MAX), convert_range_to_inclusive(1..)); + assert_eq!(Some(0..=u64::MAX), convert_range_to_inclusive(..)); + assert_eq!(None, convert_range_to_inclusive(5..5)); + assert_eq!(Some(16..=16), convert_range_to_inclusive(16..=16)) + } +} diff --git a/vendor/roaring/tests/bitmapwithoutruns.bin b/vendor/roaring/tests/bitmapwithoutruns.bin new file mode 100644 index 0000000..a99fd50 Binary files /dev/null and b/vendor/roaring/tests/bitmapwithoutruns.bin differ diff --git a/vendor/roaring/tests/bitmapwithruns.bin b/vendor/roaring/tests/bitmapwithruns.bin new file mode 100644 index 0000000..5ed2437 Binary files /dev/null and b/vendor/roaring/tests/bitmapwithruns.bin differ diff --git a/vendor/roaring/tests/clone.rs b/vendor/roaring/tests/clone.rs new file mode 100644 index 0000000..c5e9c15 --- /dev/null +++ b/vendor/roaring/tests/clone.rs @@ -0,0 +1,55 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +#[allow(clippy::redundant_clone)] +fn array() { + let original = (0..2000).collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn bitmap() { + let original = (0..6000).collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn arrays() { + let original = (0..2000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_001_000) + .collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn bitmaps() { + let original = (0..6000) + .chain(1_000_000..1_012_000) + .chain(2_000_000..2_010_000) + .collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn runs() { + let mut original = + RoaringBitmap::from_iter((0..6000).chain(1_000_000..1_012_000).chain(2_000_000..2_010_000)); + original.optimize(); + let clone = original.clone(); + + assert_eq!(clone, original); +} diff --git a/vendor/roaring/tests/difference_with.rs b/vendor/roaring/tests/difference_with.rs new file mode 100644 index 0000000..a3b6743 --- /dev/null +++ b/vendor/roaring/tests/difference_with.rs @@ -0,0 +1,129 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (0..1000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn no_difference() { + let mut bitmap1 = (1..3).collect::(); + let bitmap2 = (1..3).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, RoaringBitmap::new()); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (0..1000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (0..6000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..9000).collect::(); + let bitmap3 = (0..3000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (9000..12000).collect::(); + let bitmap3 = (0..9000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..6000).collect::(); + let bitmap3 = (0..3000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = (0..2000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_001_000) + .collect::(); + let bitmap2 = (1000..3000) + .chain(1_001_000..1_003_000) + .chain(2_000_000..2_001_000) + .collect::(); + let bitmap3 = (0..1000).chain(1_000_000..1_001_000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays_removing_one_whole_container() { + let mut bitmap1 = (0..2000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_001_000) + .collect::(); + let bitmap2 = (0..3000) + .chain(1_001_000..1_003_000) + .chain(2_000_000..2_001_000) + .collect::(); + let bitmap3 = (1_000_000..1_001_000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = (0..6000) + .chain(1_000_000..1_012_000) + .chain(2_000_000..2_010_000) + .collect::(); + let bitmap2 = (3000..9000) + .chain(1_006_000..1_018_000) + .chain(2_000_000..2_010_000) + .collect::(); + let bitmap3 = (0..3000).chain(1_000_000..1_006_000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/intersect_with.rs b/vendor/roaring/tests/intersect_with.rs new file mode 100644 index 0000000..2f3296b --- /dev/null +++ b/vendor/roaring/tests/intersect_with.rs @@ -0,0 +1,101 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (1000..2000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn no_intersection() { + let mut bitmap1 = (0..2).collect::(); + let bitmap2 = (3..4).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, RoaringBitmap::new()); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (1000..2000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (6000..12000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..9000).collect::(); + let bitmap3 = (3000..6000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (7000..9000).collect::(); + let bitmap3 = (7000..9000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = (0..2000) + .chain(1_000_000..1_002_000) + .chain(3_000_000..3_001_000) + .collect::(); + let bitmap2 = (1000..3000) + .chain(1_001_000..1_003_000) + .chain(2_000_000..2_001_000) + .collect::(); + let bitmap3 = (1000..2000).chain(1_001_000..1_002_000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = (0..6000) + .chain(1_000_000..1_012_000) + .chain(3_000_000..3_010_000) + .collect::(); + let bitmap2 = (3000..9000) + .chain(1_006_000..1_018_000) + .chain(2_000_000..2_010_000) + .collect::(); + let bitmap3 = (3000..6000).chain(1_006_000..1_012_000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/is_disjoint.rs b/vendor/roaring/tests/is_disjoint.rs new file mode 100644 index 0000000..51a22d0 --- /dev/null +++ b/vendor/roaring/tests/is_disjoint.rs @@ -0,0 +1,70 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array() { + let bitmap1 = (0..2000).collect::(); + let bitmap2 = (4000..6000).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn array_not() { + let bitmap1 = (0..4000).collect::(); + let bitmap2 = (2000..6000).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmap() { + let bitmap1 = (0..6000).collect::(); + let bitmap2 = (10000..16000).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmap_not() { + let bitmap1 = (0..10000).collect::(); + let bitmap2 = (5000..15000).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn arrays() { + let bitmap1 = (0..2000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_002_000) + .collect::(); + let bitmap2 = (100_000..102_000).chain(1_100_000..1_102_000).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn arrays_not() { + let bitmap1 = (0..2_000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_002_000) + .collect::(); + let bitmap2 = (100_000..102_000).chain(1_001_000..1_003_000).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmaps() { + let bitmap1 = (0..6000) + .chain(1_000_000..1_006_000) + .chain(2_000_000..2_006_000) + .collect::(); + let bitmap2 = (100_000..106_000).chain(1_100_000..1_106_000).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmaps_not() { + let bitmap1 = (0..6000) + .chain(1_000_000..1_006_000) + .chain(2_000_000..2_006_000) + .collect::(); + let bitmap2 = (100_000..106_000).chain(1_004_000..1_008_000).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} diff --git a/vendor/roaring/tests/is_subset.rs b/vendor/roaring/tests/is_subset.rs new file mode 100644 index 0000000..1d19ac8 --- /dev/null +++ b/vendor/roaring/tests/is_subset.rs @@ -0,0 +1,82 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array_not() { + let sup = (0..2000).collect::(); + let sub = (1000..3000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn array() { + let sup = (0..4000).collect::(); + let sub = (2000..3000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn array_bitmap_not() { + let sup = (0..2000).collect::(); + let sub = (1000..15000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmap_not() { + let sup = (0..6000).collect::(); + let sub = (4000..10000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmap() { + let sup = (0..20000).collect::(); + let sub = (5000..15000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn bitmap_array_not() { + let sup = (0..20000).collect::(); + let sub = (19000..21000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmap_array() { + let sup = (0..20000).collect::(); + let sub = (18000..20000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn arrays_not() { + let sup = (0..2000).chain(1_000_000..1_002_000).collect::(); + let sub = (100_000..102_000).chain(1_100_000..1_102_000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn arrays() { + let sup = (0..3000).chain(100_000..103_000).collect::(); + let sub = (0..2000).chain(100_000..102_000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn bitmaps_not() { + let sup = (0..6000) + .chain(1_000_000..1_006_000) + .chain(2_000_000..2_010_000) + .collect::(); + let sub = (100_000..106_000).chain(1_100_000..1_106_000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmaps() { + let sup = (0..1_000_000).chain(2_000_000..2_010_000).collect::(); + let sub = (0..10_000).chain(500_000..510_000).collect::(); + assert!(sub.is_subset(&sup)); +} diff --git a/vendor/roaring/tests/iter.rs b/vendor/roaring/tests/iter.rs new file mode 100644 index 0000000..ea3d557 --- /dev/null +++ b/vendor/roaring/tests/iter.rs @@ -0,0 +1,245 @@ +use proptest::arbitrary::any; +use proptest::collection::btree_set; +use proptest::proptest; + +use roaring::RoaringBitmap; + +#[test] +fn range() { + let original = (0..2000).collect::(); + let clone = RoaringBitmap::from_iter(&original); + let clone2 = RoaringBitmap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn array() { + let original = (0..5).collect::(); + let clone = RoaringBitmap::from([0, 1, 2, 3, 4]); + + assert_eq!(clone, original); +} + +#[test] +fn bitmap() { + let original = (0..100_000).collect::(); + let clone = RoaringBitmap::from_iter(&original); + let clone2 = RoaringBitmap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn arrays() { + let original = (0..2000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_001_000) + .collect::(); + let clone = RoaringBitmap::from_iter(&original); + let clone2 = RoaringBitmap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn bitmaps() { + let original = (0..100_000) + .chain(1_000_000..1_012_000) + .chain(2_000_000..2_010_000) + .collect::(); + let clone = RoaringBitmap::from_iter(&original); + let clone2 = RoaringBitmap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +proptest! { + #[test] + fn iter(values in btree_set(any::(), ..=10_000)) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + // Iterator::eq != PartialEq::eq - cannot use assert_eq macro + assert!(values.into_iter().eq(bitmap)); + } +} + +proptest! { + #[test] + fn fold(values in btree_set(any::(), ..=10_000)) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + let mut val_iter = values.into_iter(); + // `Iterator::all` uses currently unimplementable `try_fold`, we test `fold` + #[allow(clippy::unnecessary_fold)] + let r = bitmap.into_iter().fold(true, |b, i| { + b && i == val_iter.next().unwrap() + }); + assert!(r) + } +} + +proptest! { + #[test] + fn nth(values in btree_set(any::(), ..=10_000), nth in 0..10_005usize) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + let mut orig_iter = bitmap.iter().fuse(); + let mut iter = bitmap.iter(); + + for _ in 0..nth { + if orig_iter.next().is_none() { + break; + } + } + let expected = orig_iter.next(); + assert_eq!(expected, iter.nth(nth)); + let expected_next = orig_iter.next(); + assert_eq!(expected_next, iter.next()); + + let mut val_iter = values.into_iter(); + assert_eq!(expected, val_iter.nth(nth)); + assert_eq!(expected_next, val_iter.next()); + } +} + +#[test] +fn huge_nth() { + let bitmap = RoaringBitmap::new(); + let mut iter = bitmap.iter(); + assert_eq!(None, iter.nth(usize::MAX)); +} + +proptest! { + #[test] + fn count(values in btree_set(any::(), ..=10_000), skip in 0..10_005usize) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + let mut iter = bitmap.iter(); + + if let Some(n) = skip.checked_sub(1) { + iter.nth(n); + } + let expected_count = values.len().saturating_sub(skip); + let size_hint = iter.size_hint(); + assert_eq!(expected_count, size_hint.0); + assert_eq!(Some(expected_count), size_hint.1); + assert_eq!(expected_count, iter.count()); + } +} + +#[test] +fn rev_array() { + let values = 0..100; + let bitmap = values.clone().collect::(); + + assert!(values.into_iter().rev().eq(bitmap.iter().rev())); +} + +#[test] +fn rev_bitmap() { + let values = 0..=100_000; + let bitmap = values.clone().collect::(); + + assert!(values.into_iter().rev().eq(bitmap.iter().rev())); +} + +proptest! { + #[test] + fn rev_iter(values in btree_set(any::(), ..=10_000)) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + + assert!(values.into_iter().rev().eq(bitmap.iter().rev())); + } +} + +#[test] +fn from_iter() { + // This test verifies that the public API allows conversion from iterators + // with u32 as well as &u32 elements. + let vals = vec![1, 5, 10000]; + let a = RoaringBitmap::from_iter(vals.iter()); + let b = RoaringBitmap::from_iter(vals); + assert_eq!(a, b); +} + +#[derive(Clone, Debug)] +pub struct OutsideInIter(bool, T); + +impl Iterator for OutsideInIter +where + I: DoubleEndedIterator, +{ + type Item = T; + + fn next(&mut self) -> Option { + let res = if self.0 { self.1.next() } else { self.1.next_back() }; + self.0 = !self.0; + res + } +} + +pub fn outside_in(into_iter: I) -> OutsideInIter +where + U: DoubleEndedIterator, + I: IntoIterator, +{ + OutsideInIter(true, into_iter.into_iter()) +} + +// Sanity check that outside_in does what we expect +#[test] +fn outside_in_iterator() { + let values = 0..10; + assert!(outside_in(values).eq(vec![0, 9, 1, 8, 2, 7, 3, 6, 4, 5])); +} + +#[test] +fn interleaved_array() { + let values = 0..100; + let bitmap = values.clone().collect::(); + + assert!(outside_in(values).eq(outside_in(bitmap))); +} + +#[test] +fn interleaved_bitmap() { + let values = 0..=4097; + let bitmap = values.clone().collect::(); + + assert!(outside_in(values).eq(outside_in(bitmap))); +} + +#[test] +fn run_nth_max() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..0x1_0000); + let mut iter = bitmap.iter(); + assert_eq!(iter.nth(0x0_FFFF), Some(0x0_FFFF)); + assert_eq!(iter.len(), 0); + #[allow(clippy::iter_nth_zero)] + { + assert_eq!(iter.nth(0), None); + } + assert_eq!(iter.next(), None); +} + +#[test] +fn run_nth_back_max() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..0x1_0000); + let mut iter = bitmap.iter(); + assert_eq!(iter.nth_back(0x0_FFFF), Some(0)); + assert_eq!(iter.len(), 0); + assert_eq!(iter.nth_back(0), None); + assert_eq!(iter.next_back(), None); +} + +proptest! { + #[test] + fn interleaved_iter(values in btree_set(any::(), 50_000..=100_000)) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + + assert!(outside_in(values).eq(outside_in(bitmap))); + } +} diff --git a/vendor/roaring/tests/iter_advance_to.rs b/vendor/roaring/tests/iter_advance_to.rs new file mode 100644 index 0000000..9e4c30c --- /dev/null +++ b/vendor/roaring/tests/iter_advance_to.rs @@ -0,0 +1,313 @@ +use roaring::RoaringBitmap; + +#[test] +fn iter_basic() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.iter(); + i.advance_to(10); + for n in 11..=14 { + assert_eq!(i.next(), Some(n)) + } + assert_eq!(i.next(), None); +} + +#[test] +fn to_missing_container() { + let bm = RoaringBitmap::from([1, 0x2_0001, 0x2_0002]); + let mut i = bm.iter(); + i.advance_to(0x1_0000); + assert_eq!(i.next(), Some(0x2_0001)); + assert_eq!(i.next(), Some(0x2_0002)); + assert_eq!(i.next(), None); +} + +#[test] +fn iter_back_basic() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.iter(); + i.advance_back_to(10); + assert_eq!(i.next(), Some(1)); + assert_eq!(i.next(), Some(2)); + assert_eq!(i.next_back(), Some(4)); + assert_eq!(i.next_back(), Some(3)); + + assert_eq!(i.next(), None); + assert_eq!(i.next_back(), None); +} + +#[test] +fn iter_advance_past_end() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.iter(); + i.advance_to(15); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None); +} + +#[test] +fn iter_multi_container() { + let bm = RoaringBitmap::from([1, 2, 3, 100000, 100001]); + let mut i = bm.iter(); + i.advance_to(3); + assert_eq!(i.size_hint(), (3, Some(3))); + assert_eq!(i.next(), Some(3)); + assert_eq!(i.size_hint(), (2, Some(2))); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.size_hint(), (1, Some(1))); + assert_eq!(i.next(), Some(100001)); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None); + assert_eq!(i.size_hint(), (0, Some(0))); +} + +#[test] +fn iter_empty() { + let bm = RoaringBitmap::new(); + let mut i = bm.iter(); + i.advance_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +} + +#[test] +fn iter_back_empty() { + let bm = RoaringBitmap::new(); + let mut i = bm.iter(); + i.advance_back_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +} + +#[test] +fn into_iter_basic() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.into_iter(); + i.advance_to(10); + let mut expected_size_hint = 4; + assert_eq!(i.size_hint(), (expected_size_hint, Some(expected_size_hint))); + for n in 11..=14 { + assert_eq!(i.next(), Some(n)); + expected_size_hint -= 1; + assert_eq!(i.size_hint(), (expected_size_hint, Some(expected_size_hint))); + } + assert_eq!(i.next(), None); +} + +#[test] +fn into_iter_multi_container() { + let bm = RoaringBitmap::from([1, 2, 3, 100000, 100001]); + let mut i = bm.into_iter(); + i.advance_to(3); + assert_eq!(i.size_hint(), (3, Some(3))); + assert_eq!(i.next(), Some(3)); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.next(), Some(100001)); + assert_eq!(i.next(), None); +} + +#[test] +fn into_iter_empty() { + let bm = RoaringBitmap::new(); + let mut i = bm.into_iter(); + i.advance_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +} + +#[test] +fn into_iter_back_empty() { + let bm = RoaringBitmap::new(); + let mut i = bm.into_iter(); + i.advance_back_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +} + +#[test] +fn advance_to_with_tail_iter() { + let bm = RoaringBitmap::from([1, 2, 3, 100000, 100001]); + let mut i = bm.iter(); + i.next_back(); + i.advance_to(100000); + assert_eq!(i.size_hint(), (1, Some(1))); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None); +} + +#[test] +fn advance_to_end() { + let bitmap = RoaringBitmap::from([u32::MAX]); + let mut iter = bitmap.iter(); + iter.advance_to(u32::MAX); + assert_eq!(Some(u32::MAX), iter.next()); + assert_eq!(None, iter.next()); +} + +#[test] +fn advance_bitset() { + let mut bitmap = RoaringBitmap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_to(0x1_0000 - 4); + // 0x1_0000 + 5 is not in the bitmap, so the next value will be the first value less than that + iter.advance_back_to(0x1_0000 + 5); + assert_eq!(iter.next(), Some(0x1_0000 - 4)); + assert_eq!(iter.next_back(), Some(0x1_0000 + 4)); + + assert_eq!(iter.next(), Some(0x1_0000 - 2)); + assert_eq!(iter.next(), Some(0x1_0000)); + assert_eq!(iter.next(), Some(0x1_0000 + 2)); + assert_eq!(iter.next(), None); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn advance_bitset_current_word() { + let mut bitmap = RoaringBitmap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_to(4); + iter.advance_back_to(0x2_0000 - 4); + for i in (4..=(0x2_0000 - 4)).step_by(2) { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_bitset_to_end_word() { + let mut bitmap = RoaringBitmap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_to(0x1_0000 - 4); + for i in ((0x1_0000 - 4)..=0x2_0000).step_by(2) { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_bitset_back_to_start_word() { + let mut bitmap = RoaringBitmap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_back_to(0x1_0000 - 4); + for i in (0..=(0x1_0000 - 4)).step_by(2) { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_run_past_the_end() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0x35B00); + let mut iter = bitmap.iter(); + iter.advance_to(0x35B01); + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_run_back_before_start() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(500..=0x35B00); + let mut iter = bitmap.iter(); + iter.advance_back_to(499); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn advance_run_back_reduces_forward_iter() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0x4000); + let mut iter = bitmap.iter(); + iter.advance_back_to(1); + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_run_front_and_back_past_each_other() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0x4000); + let mut iter = bitmap.iter(); + iter.advance_back_to(100); + iter.advance_to(300); + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_run_both_sides_past_each_other() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..0x1000); + let mut iter = bitmap.iter(); + iter.advance_back_to(100); + iter.advance_to(0xFFFF); + assert_eq!(iter.len(), 0); + assert_eq!(iter.nth_back(0), None); +} + +#[test] +fn advance_run_with_nth() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(36141..=224407); + let mut iter = bitmap.iter(); + iter.advance_back_to(101779); + assert_eq!(iter.nth(100563), None); +} + +#[test] +fn advance_to_with_next_len() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(100..0x4000); + let mut iter = bitmap.iter(); + iter.advance_back_to(100); + assert_eq!(iter.next(), Some(100)); + assert_eq!(iter.len(), 0); + assert_eq!(iter.nth_back(0), None); +} + +#[test] +fn tmp() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(196363..=262143); + let mut iter = bitmap.iter(); + assert_eq!(iter.next_back(), Some(262143)); + iter.advance_to(228960); + assert_eq!(iter.nth(36643), None); +} + +#[test] +fn advance_bitset_front_and_back_past_each_other() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0x4000); + bitmap.remove_run_compression(); + let mut iter = bitmap.iter(); + iter.advance_back_to(100); + iter.advance_to(300); + assert_eq!(iter.next(), None); +} + +#[test] +fn combine_with_nth() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0xFFFF); + bitmap.remove_run_compression(); + let mut iter = bitmap.iter(); + + // Use nth to skip to a specific position + assert_eq!(iter.nth(100), Some(100)); + iter.advance_back_to(50); + assert_eq!(iter.next_back(), None); +} diff --git a/vendor/roaring/tests/iter_next_range.rs b/vendor/roaring/tests/iter_next_range.rs new file mode 100644 index 0000000..5800c45 --- /dev/null +++ b/vendor/roaring/tests/iter_next_range.rs @@ -0,0 +1,558 @@ +use roaring::RoaringBitmap; + +#[test] +fn next_range_basic() { + let bm = RoaringBitmap::from([1, 2, 4, 5]); + let mut iter = bm.iter(); + + // First consecutive range: 1..=2 + assert_eq!(iter.next_range(), Some(1..=2)); + + // Iterator should now point at 4 + assert_eq!(iter.next(), Some(4)); + + // Second consecutive range: 5..=5 (single element) + assert_eq!(iter.next_range(), Some(5..=5)); + + // Iterator should now be exhausted + assert_eq!(iter.next(), None); + assert_eq!(iter.next_range(), None); +} + +#[test] +fn next_range_back_basic() { + let bm = RoaringBitmap::from([1, 2, 4, 5]); + let mut iter = bm.iter(); + + // Last consecutive range from back: 4..=5 + assert_eq!(iter.next_range_back(), Some(4..=5)); + + // Iterator back should now point at 2 + assert_eq!(iter.next_back(), Some(2)); + + // Previous consecutive range from back: 1..=1 (single element) + assert_eq!(iter.next_range_back(), Some(1..=1)); + + // Iterator should now be exhausted from back + assert_eq!(iter.next_back(), None); + assert_eq!(iter.next_range_back(), None); +} + +#[test] +fn next_range_single_elements() { + // All single-element ranges + let bm = RoaringBitmap::from([1, 3, 5, 7]); + let mut iter = bm.iter(); + + assert_eq!(iter.next_range(), Some(1..=1)); + assert_eq!(iter.next(), Some(3)); + + assert_eq!(iter.next_range(), Some(5..=5)); + assert_eq!(iter.next(), Some(7)); + + assert_eq!(iter.next_range(), None); + assert_eq!(iter.next(), None); +} + +#[test] +fn next_range_long_consecutive() { + // Long consecutive sequence + let bm = RoaringBitmap::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + let mut iter = bm.iter(); + + // Should get the entire range + assert_eq!(iter.next_range(), Some(1..=10)); + + // Iterator should be exhausted after consuming the range + assert_eq!(iter.next(), None); + assert_eq!(iter.next_range(), None); +} + +#[test] +fn next_range_partial_consumption() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 5, 10, 11, 12]); + let mut iter = bm.iter(); + + // Consume some elements first + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), Some(2)); + + // Should get remaining range from current position + assert_eq!(iter.next_range(), Some(3..=5)); + + // Continue with next range + assert_eq!(iter.next(), Some(10)); + assert_eq!(iter.next_range(), Some(11..=12)); +} + +#[test] +fn next_range_back_partial_consumption() { + let bm = RoaringBitmap::from([1, 2, 3, 10, 11, 12]); + let mut iter = bm.iter(); + + // Consume some elements from back first + assert_eq!(iter.next_back(), Some(12)); + assert_eq!(iter.next_back(), Some(11)); + + // Should get remaining range from back position + assert_eq!(iter.next_range_back(), Some(10..=10)); + + // Continue with previous range + assert_eq!(iter.next_back(), Some(3)); + assert_eq!(iter.next_range_back(), Some(1..=2)); +} + +#[test] +fn next_range_empty_bitmap() { + let bm = RoaringBitmap::new(); + let mut iter = bm.iter(); + + assert_eq!(iter.next_range(), None); + assert_eq!(iter.next_range_back(), None); +} + +#[test] +fn next_range_single_element_bitmap() { + let bm = RoaringBitmap::from([42]); + let mut iter = bm.iter(); + + assert_eq!(iter.next_range(), Some(42..=42)); + assert_eq!(iter.next(), None); + + // Reset for back test + let mut iter = bm.iter(); + assert_eq!(iter.next_range_back(), Some(42..=42)); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn next_range_mixed_operations() { + let bm = RoaringBitmap::from([1, 2, 3, 10, 11, 12, 20]); + let mut iter = bm.iter(); + + // Mix forward and backward operations + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next_back(), Some(20)); + + // Get remaining range from front (from current position 2) + assert_eq!(iter.next_range(), Some(2..=3)); + + // Get remaining range from back (should be 10..=12) + assert_eq!(iter.next_range_back(), Some(10..=12)); + + // Both ranges consumed, iterator should be empty + assert_eq!(iter.next(), None); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn next_range_multi_container() { + // Test across container boundaries + let bm = RoaringBitmap::from([1, 2, 0x1_0000, 0x1_0001, 0x1_0002]); + let mut iter = bm.iter(); + + // First container range + assert_eq!(iter.next_range(), Some(1..=2)); + + // Second container range + assert_eq!(iter.next(), Some(0x1_0000)); + assert_eq!(iter.next_range(), Some(0x1_0001..=0x1_0002)); + + assert_eq!(iter.next(), None); +} + +#[test] +fn next_range_u32_max_boundary() { + // Test behavior at u32::MAX boundary + let bm = RoaringBitmap::from([u32::MAX - 2, u32::MAX - 1, u32::MAX]); + let mut iter = bm.iter(); + + // Should handle u32::MAX correctly with RangeInclusive + assert_eq!(iter.next_range(), Some((u32::MAX - 2)..=u32::MAX)); + + assert_eq!(iter.next(), None); +} + +#[test] +fn next_range_advance_to_integration() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 5, 10, 11, 12, 13]); + let mut iter = bm.iter(); + + // Advance to middle of a consecutive range + iter.advance_to(3); + + // Should get remaining part of the range + assert_eq!(iter.next_range(), Some(3..=5)); + + // Continue with next range + assert_eq!(iter.next(), Some(10)); + assert_eq!(iter.next_range(), Some(11..=13)); +} + +#[test] +fn next_range_advance_back_to_integration() { + let bm = RoaringBitmap::from([1, 2, 3, 4, 5, 10, 11, 12, 13]); + let mut iter = bm.iter(); + + // Advance back to middle of a consecutive range + iter.advance_back_to(12); + + // Should get range from start to current back position + assert_eq!(iter.next_range_back(), Some(10..=12)); + + // Continue with previous range + assert_eq!(iter.next_back(), Some(5)); + assert_eq!(iter.next_range_back(), Some(1..=4)); +} + +// Test IntoIter variants +#[test] +fn into_iter_next_range_basic() { + let bm = RoaringBitmap::from([1, 2, 4, 5]); + let mut iter = bm.into_iter(); + + assert_eq!(iter.next_range(), Some(1..=2)); + assert_eq!(iter.next(), Some(4)); + assert_eq!(iter.next_range(), Some(5..=5)); +} + +#[test] +fn into_iter_next_range_back_basic() { + let bm = RoaringBitmap::from([1, 2, 4, 5]); + let mut iter = bm.into_iter(); + + assert_eq!(iter.next_range_back(), Some(4..=5)); + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.next_range_back(), Some(1..=1)); +} + +#[test] +fn next_range_exhausted_iterator() { + let bm = RoaringBitmap::from([1, 2, 3]); + let mut iter = bm.iter(); + + // Consume all elements + iter.next(); + iter.next(); + iter.next(); + + // Iterator should be exhausted + assert_eq!(iter.next_range(), None); + assert_eq!(iter.next_range_back(), None); +} + +#[test] +fn next_range_overlapping_calls() { + let bm = RoaringBitmap::from([1, 2, 3, 10, 11]); + let mut iter = bm.iter(); + + // Get first range + assert_eq!(iter.next_range(), Some(1..=3)); + + // Iterator advanced past first range, get second range + assert_eq!(iter.next_range(), Some(10..=11)); + + // No more ranges + assert_eq!(iter.next_range(), None); +} + +#[test] +fn next_range_very_sparse() { + // Very sparse bitmap + let bm = RoaringBitmap::from([0, 1000, 2000, 3000]); + let mut iter = bm.iter(); + + // Each element should be its own range + assert_eq!(iter.next_range(), Some(0..=0)); + assert_eq!(iter.next(), Some(1000)); + + assert_eq!(iter.next_range(), Some(2000..=2000)); + assert_eq!(iter.next(), Some(3000)); + + assert_eq!(iter.next_range(), None); +} + +#[test] +fn next_range_dense_bitmap() { + // Dense bitmap with large consecutive ranges + let mut bm = RoaringBitmap::new(); + // Add ranges: 0-99, 200-299, 500-599 + for i in 0..100 { + bm.insert(i); + } + for i in 200..300 { + bm.insert(i); + } + for i in 500..600 { + bm.insert(i); + } + + let mut iter = bm.iter(); + + assert_eq!(iter.next_range(), Some(0..=99)); + assert_eq!(iter.next(), Some(200)); + + assert_eq!(iter.next_range(), Some(201..=299)); + assert_eq!(iter.next(), Some(500)); + + assert_eq!(iter.next_range(), Some(501..=599)); + assert_eq!(iter.next(), None); +} + +#[test] +fn next_range_multi_container_range() { + // Single element bitmap + let mut bm = RoaringBitmap::new(); + bm.insert_range(0..=0x4_0000); + let mut iter = bm.iter(); + + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next_range(), Some(2..=0x4_0000)); + + assert_eq!(iter.next_range(), None); + assert_eq!(iter.next(), None); +} + +// Tests for bitmap store - these should trigger the todo!() implementations +#[test] +fn next_range_bitmap_store_forced() { + // Create a sparse pattern that exceeds ARRAY_LIMIT but is inefficient as runs + let mut bm = RoaringBitmap::new(); + + // Add alternating ranges to create many gaps - inefficient as runs + for i in (0..20000).step_by(4) { + bm.insert(i); // bit at i + bm.insert(i + 1); // bit at i+1 + // gaps at i+2, i+3 + } + + // Force removal of run compression to ensure bitmap store + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // First consecutive range should be 0..=1 + assert_eq!(iter.next_range(), Some(0..=1)); + + // Iterator should now point at 4 + assert_eq!(iter.next(), Some(4)); + + // Second consecutive range: 5..=5 (single element) + assert_eq!(iter.next_range(), Some(5..=5)); +} + +#[test] +fn next_range_back_bitmap_store_forced() { + // Create a sparse pattern that exceeds ARRAY_LIMIT but is inefficient as runs + let mut bm = RoaringBitmap::new(); + + // Add alternating ranges to create many gaps + for i in (0..20000).step_by(4) { + bm.insert(i); + bm.insert(i + 1); + } + + // Force removal of run compression + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // Last consecutive range from back should be the last pair + // The last elements should be 19996, 19997 + assert_eq!(iter.next_range_back(), Some(19996..=19997)); +} + +#[test] +fn next_range_bitmap_store_dense_with_gaps() { + // Create a dense bitmap with strategic gaps to force bitmap store + let mut bm = RoaringBitmap::new(); + + // Add most elements but with regular gaps to make runs inefficient + for i in 0..10000 { + if i % 3 != 0 { + // Skip every 3rd element + bm.insert(i); + } + } + + // Force bitmap representation + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // First consecutive range should be 1..=2 + assert_eq!(iter.next_range(), Some(1..=2)); + + // Next element should be 4 + assert_eq!(iter.next(), Some(4)); + + // Next range should be 5..=5 + assert_eq!(iter.next_range(), Some(5..=5)); +} + +#[test] +fn next_range_bitmap_store_partial_consumption() { + // Create bitmap that forces bitmap store + let mut bm = RoaringBitmap::new(); + + // Add elements in groups of 2 with gaps + for i in (1000..8000).step_by(3) { + bm.insert(i); + bm.insert(i + 1); + } + + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // Consume first few elements + assert_eq!(iter.next(), Some(1000)); + assert_eq!(iter.next(), Some(1001)); + + // Should get next range starting at 1003 + assert_eq!(iter.next_range(), Some(1003..=1004)); +} + +#[test] +fn next_range_bitmap_store_mixed_operations() { + let mut bm = RoaringBitmap::new(); + + // Create pattern that forces bitmap store + for i in (0..10000).step_by(3) { + bm.insert(i); + bm.insert(i + 1); + } + + bm.remove_run_compression(); + + // The pattern will be: 0,1 gap 3,4 gap 6,7 gap ... 9996,9997 gap 9999 + // Last iteration: i=9999, so we insert 9999 and 10000 + // But 10000 might be in a different container, so let's find the actual last element + let last_element = bm.iter().next_back().unwrap(); + + let mut iter = bm.iter(); + + // Mix forward and backward operations + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next_back(), Some(last_element)); + + // Get remaining range from front + assert_eq!(iter.next_range(), Some(1..=1)); + + // Continue to next range + assert_eq!(iter.next(), Some(3)); + assert_eq!(iter.next_range(), Some(4..=4)); +} + +#[test] +fn next_range_bitmap_store_single_elements() { + // Create very sparse bitmap that forces bitmap store + let mut bm = RoaringBitmap::new(); + + // Add individual elements spread far apart + for i in (0..20000).step_by(5) { + bm.insert(i); + } + + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // Each element should be its own single-element range + assert_eq!(iter.next_range(), Some(0..=0)); + assert_eq!(iter.next(), Some(5)); + assert_eq!(iter.next_range(), Some(10..=10)); + assert_eq!(iter.next(), Some(15)); + assert_eq!(iter.next_range(), Some(20..=20)); +} + +#[test] +fn next_range_bitmap_store_alternating_pattern() { + // Create alternating pattern that's inefficient for run encoding + let mut bm = RoaringBitmap::new(); + + // Every other bit set in a large range + for i in (0..10000).step_by(2) { + bm.insert(i); + } + + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // Each bit should be its own range due to alternating pattern + assert_eq!(iter.next_range(), Some(0..=0)); + assert_eq!(iter.next(), Some(2)); + assert_eq!(iter.next_range(), Some(4..=4)); + assert_eq!(iter.next(), Some(6)); + assert_eq!(iter.next_range(), Some(8..=8)); +} + +#[test] +fn next_range_bitmap_store_with_small_clusters() { + // Create small clusters of bits separated by gaps + let mut bm = RoaringBitmap::new(); + + // Add clusters of 3 bits separated by gaps of 5 + for base in (0..15000).step_by(8) { + bm.insert(base); + bm.insert(base + 1); + bm.insert(base + 2); + // gap of 5 (base+3, base+4, base+5, base+6, base+7) + } + + bm.remove_run_compression(); + + let mut iter = bm.iter(); + + // First cluster: 0..=2 + assert_eq!(iter.next_range(), Some(0..=2)); + + // Next cluster starts at 8 + assert_eq!(iter.next(), Some(8)); + assert_eq!(iter.next_range(), Some(9..=10)); + + // Next cluster starts at 16 + assert_eq!(iter.next(), Some(16)); + assert_eq!(iter.next_range(), Some(17..=18)); +} + +#[test] +fn range_partial_consume() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0x3FFF); + let mut iter = bitmap.iter(); + iter.next(); + assert_eq!(iter.next_range_back(), Some(1..=0x3FFF)); +} + +#[test] +fn range_with_initial_next() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(69311..=180090); + let mut iter = bitmap.iter(); + assert_eq!(iter.next(), Some(69311)); + assert_eq!(iter.next_range_back(), Some(69312..=180090)); +} + +#[test] +fn range_with_gap() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0x2_0000..=0x2_FFFF); + bitmap.remove(0x2_1000); + bitmap.remove_run_compression(); + let mut iter = bitmap.iter(); + assert_eq!(iter.next_range(), Some(0x2_0000..=0x2_0FFF)); + assert_eq!(iter.next(), Some(0x2_1001)); +} + +#[test] +fn range_back_after_next() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(0..=0x3_FFFF); + bitmap.remove(0x0_3000); + let mut iter = bitmap.iter(); + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next_range_back(), Some(0x0_3001..=0x3_FFFF)); +} diff --git a/vendor/roaring/tests/iter_range.rs b/vendor/roaring/tests/iter_range.rs new file mode 100644 index 0000000..7953c39 --- /dev/null +++ b/vendor/roaring/tests/iter_range.rs @@ -0,0 +1,95 @@ +use proptest::collection::btree_set; +use proptest::prelude::*; +use roaring::RoaringBitmap; +use std::ops::Bound; + +#[test] +fn range_array() { + let mut rb = RoaringBitmap::new(); + rb.insert(0); + rb.insert(1); + rb.insert(10); + rb.insert(100_000); + rb.insert(999_999); + rb.insert(1_000_000); + + let expected = vec![1, 10, 100_000, 999_999]; + let actual: Vec = rb.range(1..=999_999).collect(); + assert_eq!(expected, actual); +} + +#[test] +fn range_bitmap() { + let rb = RoaringBitmap::from_sorted_iter(10..5000).unwrap(); + + let expected = vec![10, 11, 12]; + let actual: Vec = rb.range(0..13).collect(); + assert_eq!(expected, actual); +} + +#[test] +fn empty_range() { + let rb = RoaringBitmap::from_sorted_iter(10..5000).unwrap(); + + let mut it = rb.range(0..0); + assert_eq!(it.next(), None); + let mut it = rb.range(..0); + assert_eq!(it.next(), None); + it = rb.range(13..13); + assert_eq!(it.next(), None); + it = rb.range((Bound::Excluded(1), Bound::Included(1))); + assert_eq!(it.next(), None); + it = rb.range(u32::MAX..u32::MAX); + assert_eq!(it.next(), None); + it = rb.range((Bound::Excluded(u32::MAX), Bound::Included(u32::MAX))); + assert_eq!(it.next(), None); + it = rb.range((Bound::Excluded(u32::MAX), Bound::Unbounded)); + assert_eq!(it.next(), None); +} + +#[test] +#[should_panic(expected = "range start is greater than range end")] +fn invalid_range() { + let rb = RoaringBitmap::from_sorted_iter(10..5000).unwrap(); + #[allow(clippy::reversed_empty_ranges)] + let _ = rb.range(13..0); +} + +#[test] +#[should_panic(expected = "range start and end are equal and excluded")] +fn invalid_range_equal_excluded() { + let rb = RoaringBitmap::from_sorted_iter(10..5000).unwrap(); + let _ = rb.range((Bound::Excluded(13), Bound::Excluded(13))); +} + +#[test] +#[should_panic(expected = "range start is greater than range end")] +fn into_invalid_range() { + let rb = RoaringBitmap::from_sorted_iter(10..5000).unwrap(); + #[allow(clippy::reversed_empty_ranges)] + let _ = rb.into_range(13..0); +} + +#[test] +#[should_panic(expected = "range start and end are equal and excluded")] +fn into_invalid_range_equal_excluded() { + let rb = RoaringBitmap::from_sorted_iter(10..5000).unwrap(); + let _ = rb.into_range((Bound::Excluded(13), Bound::Excluded(13))); +} + +proptest! { + #[test] + fn proptest_range( + values in btree_set(..=262_143_u32, ..=1000), + range_a in 0u32..262_143, + range_b in 0u32..262_143, + ){ + let range = range_a.min(range_b)..=range_a.max(range_b); + + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + let expected: Vec = values.range(range.clone()).copied().collect(); + let actual: Vec = bitmap.range(range.clone()).collect(); + + assert_eq!(expected, actual); + } +} diff --git a/vendor/roaring/tests/lib.rs b/vendor/roaring/tests/lib.rs new file mode 100644 index 0000000..568de01 --- /dev/null +++ b/vendor/roaring/tests/lib.rs @@ -0,0 +1,152 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn smoke() { + let mut bitmap = RoaringBitmap::new(); + assert_eq!(bitmap.len(), 0); + assert!(bitmap.is_empty()); + bitmap.remove(0); + assert_eq!(bitmap.len(), 0); + assert!(bitmap.is_empty()); + bitmap.insert(1); + assert!(bitmap.contains(1)); + assert_eq!(bitmap.len(), 1); + assert!(!bitmap.is_empty()); + bitmap.insert(u32::MAX - 2); + assert!(bitmap.contains(u32::MAX - 2)); + assert_eq!(bitmap.len(), 2); + bitmap.insert(u32::MAX); + assert!(bitmap.contains(u32::MAX)); + assert_eq!(bitmap.len(), 3); + bitmap.insert(2); + assert!(bitmap.contains(2)); + assert_eq!(bitmap.len(), 4); + bitmap.remove(2); + assert!(!bitmap.contains(2)); + assert_eq!(bitmap.len(), 3); + assert!(!bitmap.contains(0)); + assert!(bitmap.contains(1)); + assert!(!bitmap.contains(100)); + assert!(bitmap.contains(u32::MAX - 2)); + assert!(!bitmap.contains(u32::MAX - 1)); + assert!(bitmap.contains(u32::MAX)); +} + +#[test] +fn remove_range() { + let ranges = [0u32, 1, 63, 64, 65, 100, 4096 - 1, 4096, 4096 + 1, 65536 - 1, 65536, 65536 + 1]; + for (i, &a) in ranges.iter().enumerate() { + for &b in &ranges[i..] { + let mut bitmap = (0..=65536).collect::(); + assert_eq!(bitmap.remove_range(a..b), u64::from(b - a)); + assert_eq!(bitmap, (0..a).chain(b..=65536).collect::()); + } + } +} + +#[test] +#[allow(clippy::range_plus_one)] // remove_range needs an exclusive range +fn remove_range_array() { + let mut bitmap = (0..1000).collect::(); + for i in 0..1000 { + assert_eq!(bitmap.remove_range(i..i), 0); + assert_eq!(bitmap.remove_range(i..i + 1), 1); + } + + // insert 0, 2, 4, .. + // remove [0, 2), [2, 4), .. + let mut bitmap = (0..1000).map(|x| x * 2).collect::(); + for i in 0..1000 { + assert_eq!(bitmap.remove_range(i * 2..(i + 1) * 2), 1); + } + + // remove [0, 2), [2, 4), .. + let mut bitmap = (0..1000).collect::(); + for i in 0..1000 / 2 { + assert_eq!(bitmap.remove_range(i * 2..(i + 1) * 2), 2); + } +} + +#[test] +#[allow(clippy::range_plus_one)] // remove_range needs an exclusive range +fn remove_range_bitmap() { + let mut bitmap = (0..4096 + 1000).collect::(); + for i in 0..1000 { + assert_eq!(bitmap.remove_range(i..i), 0); + assert_eq!(bitmap.remove_range(i..i + 1), 1); + } + + // insert 0, 2, 4, .. + // remove [0, 2), [2, 4), .. + let mut bitmap = ((0..4096 + 1000).map(|x| x * 2)).collect::(); + for i in 0..1000 { + assert_eq!(bitmap.remove_range(i * 2..(i + 1) * 2), 1); + } + + // remove [0, 2), [2, 4), .. + let mut bitmap = (0..4096 + 1000).collect::(); + for i in 0..1000 / 2 { + assert_eq!(bitmap.remove_range(i * 2..(i + 1) * 2), 2); + } + + // remove [1, 3), [3, 5), .. + let mut bitmap = (0..4096 + 1000).collect::(); + for i in 0..1000 / 2 { + assert_eq!(bitmap.remove_range(i * 2 + 1..(i + 1) * 2 + 1), 2); + } +} + +#[test] +fn to_bitmap() { + let bitmap = (0..5000).collect::(); + assert_eq!(bitmap.len(), 5000); + for i in 1..5000 { + assert!(bitmap.contains(i)); + } + assert!(!bitmap.contains(5001)); +} + +#[test] +fn to_array() { + let mut bitmap = (0..5000).collect::(); + for i in 3000..5000 { + bitmap.remove(i); + } + assert_eq!(bitmap.len(), 3000); + for i in 0..3000 { + assert!(bitmap.contains(i)); + } + for i in 3000..5000 { + assert!(!bitmap.contains(i)); + } +} + +#[test] +fn optimize_array() { + let mut bitmap = RoaringBitmap::from_iter(0..1000); + assert!(bitmap.optimize()); + let mut bitmap = RoaringBitmap::from_iter(0..5000); + assert!(bitmap.optimize()); +} + +#[test] +fn optimize_bitmap() { + let mut bitmap = RoaringBitmap::from_iter(0..5000); + assert!(bitmap.optimize()); +} + +#[test] +fn remove_run_compression() { + let mut bitmap = RoaringBitmap::from_iter(0..5000); + assert!(bitmap.optimize()); + assert!(bitmap.remove_run_compression()); +} + +#[test] +fn optimize_run() { + let mut bitmap = RoaringBitmap::from_iter(0..1000); + assert!(bitmap.optimize()); + // Calling optimize a second time should return false as no changes will be made + assert!(!bitmap.optimize()); +} diff --git a/vendor/roaring/tests/ops.rs b/vendor/roaring/tests/ops.rs new file mode 100644 index 0000000..eb1ce14 --- /dev/null +++ b/vendor/roaring/tests/ops.rs @@ -0,0 +1,95 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn or() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = (1..6).collect::(); + + assert_eq!(rb3, &rb1 | &rb2); + assert_eq!(rb3, &rb1 | rb2.clone()); + assert_eq!(rb3, rb1.clone() | &rb2); + assert_eq!(rb3, rb1.clone() | rb2.clone()); + assert_eq!(rb3.len(), rb1.union_len(&rb2)); + + rb1 |= &rb2; + rb1 |= rb2; + + assert_eq!(rb3, rb1); +} + +#[test] +fn and() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = (3..4).collect::(); + + assert_eq!(rb3, &rb1 & &rb2); + assert_eq!(rb3, &rb1 & rb2.clone()); + assert_eq!(rb3, rb1.clone() & &rb2); + assert_eq!(rb3, rb1.clone() & rb2.clone()); + assert_eq!(rb3.len(), rb1.intersection_len(&rb2)); + + rb1 &= &rb2; + rb1 &= rb2; + + assert_eq!(rb3, rb1); +} + +#[test] +fn sub() { + let mut rb1 = (1..4000).collect::(); + let rb2 = (3..5000).collect::(); + let rb3 = (1..3).collect::(); + + assert_eq!(rb3, &rb1 - &rb2); + assert_eq!(rb3, &rb1 - rb2.clone()); + assert_eq!(rb3, rb1.clone() - &rb2); + assert_eq!(rb3, rb1.clone() - rb2.clone()); + assert_eq!(rb3.len(), rb1.difference_len(&rb2)); + + rb1 -= &rb2; + rb1 -= rb2; + + assert_eq!(rb3, rb1); +} + +// See issue #327 +#[test] +fn subtraction_preserves_zero_element() { + let mut a = RoaringBitmap::from([0, 35, 80, 104, 138, 214, 235, 258]); + let b = RoaringBitmap::from([9, 35, 42, 51, 111, 134, 231, 239]); + + a -= b; + + // The bug: element 0 should still be present but was being removed + assert!(a.contains(0), "Element 0 should be present after subtraction"); + + // Verify the complete result + let expected: Vec = vec![0, 80, 104, 138, 214, 235, 258]; + let actual: Vec = a.iter().collect(); + assert_eq!(actual, expected, "Subtraction result should match expected values"); +} + +#[test] +fn xor() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = (1..3).chain(4..6).collect::(); + let rb4 = (0..0).collect::(); + + assert_eq!(rb3, &rb1 ^ &rb2); + assert_eq!(rb3, &rb1 ^ rb2.clone()); + assert_eq!(rb3, rb1.clone() ^ &rb2); + assert_eq!(rb3, rb1.clone() ^ rb2.clone()); + assert_eq!(rb3.len(), rb1.symmetric_difference_len(&rb2)); + + rb1 ^= &rb2; + + assert_eq!(rb3, rb1); + + rb1 ^= rb3; + + assert_eq!(rb4, rb1); +} diff --git a/vendor/roaring/tests/push.rs b/vendor/roaring/tests/push.rs new file mode 100644 index 0000000..aac60da --- /dev/null +++ b/vendor/roaring/tests/push.rs @@ -0,0 +1,57 @@ +extern crate roaring; +use roaring::{RoaringBitmap, RoaringTreemap}; + +/// macro created to reduce code duplication +macro_rules! test_from_sorted_iter { + ($values: expr, $class: ty) => {{ + let rb1 = <$class>::from_iter($values.clone()); + let rb2 = <$class>::from_sorted_iter($values).unwrap(); + + for (x, y) in rb1.iter().zip(rb2.iter()) { + assert_eq!(x, y); + } + assert_eq!(rb1.len(), rb2.len()); + assert_eq!(rb1.min(), rb2.min()); + assert_eq!(rb1.max(), rb2.max()); + assert_eq!(rb1.is_empty(), rb2.is_empty()); + assert_eq!(rb1, rb2); + }}; +} + +#[test] +fn append() { + test_from_sorted_iter!((0..1_000_000).map(|x| 13 * x).collect::>(), RoaringBitmap); + test_from_sorted_iter!(vec![1, 2, 4, 5, 7, 8, 9], RoaringBitmap); +} + +#[test] +fn append_empty() { + assert_eq!(RoaringBitmap::new().append(vec![]), Ok(0u64)) +} + +#[test] +fn append_error() { + match [100u32].iter().cloned().collect::().append(vec![10, 20, 0]) { + Ok(_) => { + panic!("The 0th element in the iterator was < the max of the bitmap") + } + Err(non_sorted_error) => { + assert_eq!(non_sorted_error.valid_until(), 0) + } + } + + match [100u32].iter().cloned().collect::().append(vec![200, 201, 201]) { + Ok(_) => { + panic!("The 3rd element in the iterator was < 2nd") + } + Err(non_sorted_error) => { + assert_eq!(non_sorted_error.valid_until(), 2) + } + } +} + +#[test] +fn append_tree() { + test_from_sorted_iter!((0..1_000_000).map(|x| 13 * x).collect::>(), RoaringTreemap); + test_from_sorted_iter!(vec![1, 2, 4, 5, 7, 8, 9], RoaringTreemap); +} diff --git a/vendor/roaring/tests/range_checks.rs b/vendor/roaring/tests/range_checks.rs new file mode 100644 index 0000000..7903eed --- /dev/null +++ b/vendor/roaring/tests/range_checks.rs @@ -0,0 +1,77 @@ +use proptest::collection::hash_set; +use proptest::prelude::*; +use roaring::RoaringBitmap; + +#[test] +fn u32_max() { + let mut bitmap = RoaringBitmap::new(); + bitmap.insert(u32::MAX); + assert!(bitmap.contains_range(u32::MAX..=u32::MAX)); + assert!(!bitmap.contains_range(u32::MAX - 1..=u32::MAX)); + + bitmap.insert_range(4_000_000_000..); + assert!(bitmap.contains_range(4_000_000_000..)); + assert!(bitmap.contains_range(4_000_000_000..u32::MAX)); + assert!(bitmap.contains_range(4_000_000_000..=u32::MAX)); + assert!(bitmap.contains_range(4_100_000_000..=u32::MAX)); +} + +proptest! { + #[test] + fn proptest_range( + start in ..=262_143_u32, + len in ..=262_143_u32, + extra in hash_set(..=462_143_u32, ..=100), + ){ + let end = start + len; + let range = start..end; + let inverse_empty_range = (start+len)..start; + + let mut bitmap = RoaringBitmap::new(); + bitmap.insert_range(range.clone()); + assert!(bitmap.contains_range(range.clone())); + assert!(bitmap.contains_range(inverse_empty_range.clone())); + assert_eq!(bitmap.range_cardinality(range.clone()) as usize, range.len()); + + for &val in &extra { + bitmap.insert(val); + assert!(bitmap.contains_range(range.clone())); + assert!(bitmap.contains_range(inverse_empty_range.clone())); + assert_eq!(bitmap.range_cardinality(range.clone()) as usize, range.len()); + } + + for (i, &val) in extra.iter().filter(|x| range.contains(x)).enumerate() { + bitmap.remove(val); + assert!(!bitmap.contains_range(range.clone())); + assert!(bitmap.contains_range(inverse_empty_range.clone())); + assert_eq!(bitmap.range_cardinality(range.clone()) as usize, range.len() - i - 1); + } + } + + #[test] + fn proptest_range_boundaries( + // Ensure we can always subtract one from start + start in 1..=262_143_u32, + len in 0..=262_143_u32, + ) { + let mut bitmap = RoaringBitmap::new(); + let end = start + len; + let half = start + len / 2; + bitmap.insert_range(start..end); + + assert!(bitmap.contains_range(start..end)); + + assert!(bitmap.contains_range(start+1..end)); + assert!(bitmap.contains_range(start..end - 1)); + assert!(bitmap.contains_range(start+1..end - 1)); + + assert!(!bitmap.contains_range(start - 1..end)); + assert!(!bitmap.contains_range(start - 1..end - 1)); + assert!(!bitmap.contains_range(start..end + 1)); + assert!(!bitmap.contains_range(start + 1..end + 1)); + assert!(!bitmap.contains_range(start - 1..end + 1)); + + assert!(!bitmap.contains_range(start - 1..half)); + assert!(!bitmap.contains_range(half..end + 1)); + } +} diff --git a/vendor/roaring/tests/rank.rs b/vendor/roaring/tests/rank.rs new file mode 100644 index 0000000..9488377 --- /dev/null +++ b/vendor/roaring/tests/rank.rs @@ -0,0 +1,74 @@ +extern crate roaring; + +use proptest::collection::{btree_set, vec}; +use proptest::prelude::*; +use roaring::RoaringBitmap; + +#[test] +fn rank() { + let mut bitmap = RoaringBitmap::from_sorted_iter(0..2000).unwrap(); + bitmap.insert_range(200_000..210_000); + + // No matching container + assert_eq!(bitmap.rank(80_000), 2000); + assert_eq!(bitmap.rank(u32::MAX), 12_000); + + // Array container at key + assert_eq!(bitmap.rank(0), 1); + assert_eq!(bitmap.rank(100), 101); + assert_eq!(bitmap.rank(2000), 2000); + + // Bitmap container at key + assert_eq!(bitmap.rank(200_000), 2001); + assert_eq!(bitmap.rank(210_000), 12_000); +} + +#[test] +fn rank_array() { + let bitmap = RoaringBitmap::from_sorted_iter(0..2000).unwrap(); + + // No matching container + assert_eq!(bitmap.rank(u32::MAX), 2000); + + // Has container (array) + assert_eq!(bitmap.rank(0), 1); + assert_eq!(bitmap.rank(100), 101); + assert_eq!(bitmap.rank(2000), 2000); + assert_eq!(bitmap.rank(3000), 2000); +} + +#[test] +fn rank_bitmap() { + let bitmap = RoaringBitmap::from_sorted_iter(0..5000).unwrap(); + + // key: 0, bit: 0 + assert_eq!(bitmap.rank(0), 1); + + // key: 0, bit: 63 (mask of all ones) + assert_eq!(bitmap.rank(63), 64); + + // key: 1023, bit: 0 + assert_eq!(bitmap.rank(65535), 5000); + + // key: 1023, bit: 63 (mask of all ones) + assert_eq!(bitmap.rank(65472), 5000); + + assert_eq!(bitmap.rank(1), 2); + assert_eq!(bitmap.rank(100), 101); + assert_eq!(bitmap.rank(1000), 1001); + assert_eq!(bitmap.rank(4999), 5000); +} + +proptest! { + #[test] + fn proptest_rank( + values in btree_set(..=262_143_u32, ..=1000), + checks in vec(..=262_143_u32, ..=100) + ){ + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + for i in checks { + let expected = values.iter().take_while(|&&x| x <= i).count() as u64; + assert_eq!(bitmap.rank(i), expected); + } + } +} diff --git a/vendor/roaring/tests/select.rs b/vendor/roaring/tests/select.rs new file mode 100644 index 0000000..6abaee3 --- /dev/null +++ b/vendor/roaring/tests/select.rs @@ -0,0 +1,52 @@ +extern crate roaring; + +use proptest::collection::btree_set; +use proptest::prelude::*; +use roaring::RoaringBitmap; + +#[test] +fn select() { + let bitmap = (0..2000).collect::(); + + assert_eq!(bitmap.select(0), Some(0)); +} + +#[test] +fn select_array() { + let bitmap = (0..2000).collect::(); + + assert_eq!(bitmap.select(0), Some(0)); + assert_eq!(bitmap.select(100), Some(100)); + assert_eq!(bitmap.select(1000), Some(1000)); + assert_eq!(bitmap.select(1999), Some(1999)); + assert_eq!(bitmap.select(2000), None); +} + +#[test] +fn select_bitmap() { + let bitmap = (0..100_000).collect::(); + + assert_eq!(bitmap.select(0), Some(0)); + assert_eq!(bitmap.select(63), Some(63)); + assert_eq!(bitmap.select(1000), Some(1000)); + assert_eq!(bitmap.select(65535), Some(65535)); +} + +#[test] +fn select_empty() { + let bitmap = RoaringBitmap::new(); + + assert_eq!(bitmap.select(0), None); + assert_eq!(bitmap.select(1024), None); + assert_eq!(bitmap.select(u32::MAX), None); +} + +proptest! { + #[test] + fn proptest_select(values in btree_set(any::(), 1000)) { + let bitmap = RoaringBitmap::from_sorted_iter(values.iter().cloned()).unwrap(); + for (i, value) in values.iter().cloned().enumerate() { + prop_assert_eq!(bitmap.select(i as u32), Some(value)); + } + } +} diff --git a/vendor/roaring/tests/serialization.rs b/vendor/roaring/tests/serialization.rs new file mode 100644 index 0000000..f4adc8d --- /dev/null +++ b/vendor/roaring/tests/serialization.rs @@ -0,0 +1,748 @@ +#![cfg(feature = "std")] + +extern crate roaring; + +use roaring::RoaringBitmap; + +// Test data from https://github.com/RoaringBitmap/RoaringFormatSpec/tree/master/testdata +static BITMAP_WITHOUT_RUNS: &[u8] = include_bytes!("bitmapwithoutruns.bin"); +static BITMAP_WITH_RUNS: &[u8] = include_bytes!("bitmapwithruns.bin"); + +fn test_data_bitmap() -> RoaringBitmap { + (0..100) + .map(|i| i * 1000) + .chain((100_000..200_000).map(|i| i * 3)) + .chain(700_000..800_000) + .collect::() +} + +fn serialize_and_deserialize(bitmap: &RoaringBitmap) -> RoaringBitmap { + let mut buffer = vec![]; + bitmap.serialize_into(&mut buffer).unwrap(); + assert_eq!(buffer.len(), bitmap.serialized_size()); + RoaringBitmap::deserialize_from(&buffer[..]).unwrap() +} + +#[test] +fn test_deserialize_without_runs_from_provided_data() { + assert_eq!(RoaringBitmap::deserialize_from(BITMAP_WITHOUT_RUNS).unwrap(), test_data_bitmap()); +} + +#[test] +fn test_deserialize_with_runs_from_provided_data() { + let mut expected = test_data_bitmap(); + // Call optimize to create run containers + expected.optimize(); + assert_eq!(RoaringBitmap::deserialize_from(&mut &BITMAP_WITH_RUNS[..]).unwrap(), expected); +} + +#[test] +fn test_serialize_into_provided_data() { + let bitmap = test_data_bitmap(); + let mut buffer = vec![]; + bitmap.serialize_into(&mut buffer).unwrap(); + assert!(BITMAP_WITHOUT_RUNS == &buffer[..]); +} + +#[test] +fn test_serialize_with_runs_into_provided_data() { + let mut bitmap = test_data_bitmap(); + // Call optimize to create run containers + bitmap.optimize(); + let mut buffer = vec![]; + bitmap.serialize_into(&mut buffer).unwrap(); + assert!(BITMAP_WITH_RUNS == &buffer[..]); +} + +#[test] +fn test_empty() { + let original = RoaringBitmap::new(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_one() { + let original = (1..2).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_array() { + let original = (1000..3000).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_array_boundary() { + let original = (1000..5096).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_bitmap_boundary() { + let original = (1000..5097).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_bitmap_high16bits() { + let mut bitmap = RoaringBitmap::new(); + for i in 0..1 << 16 { + let value = i << 16; + bitmap.insert(value); + } + + let mut buffer = vec![]; + bitmap.serialize_into(&mut buffer).unwrap(); + + let new = RoaringBitmap::deserialize_from(&buffer[..]); + assert!(new.is_ok()); + assert_eq!(bitmap, new.unwrap()); +} + +#[test] +fn test_bitmap() { + let original = (1000..6000).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_arrays() { + let original = (1000..3000).chain(70000..74000).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_bitmaps() { + let original = (1000..6000).chain(70000..77000).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_mixed() { + let original = (1000..3000).chain(70000..77000).collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_strange() { + const ARRAY: &[u32] = &[ + 6619162, 6619180, 6619181, 6619217, 6619218, 6619257, 6619258, 6619259, 6619260, 6619261, + 6619262, 6619263, 6619264, 6619265, 6619266, 6619292, 6619294, 6619322, 6619461, 6619485, + 6619490, 6619500, 6619594, 6619619, 6619620, 6619623, 6619630, 6619632, 6619700, 6619701, + 6619702, 6619703, 6619813, 6619896, 6619967, 6620022, 6620034, 6620038, 6620110, 6620182, + 6620189, 6620194, 6620200, 6620262, 6620289, 6620321, 6620353, 6620354, 6620355, 6620356, + 6620384, 6620403, 6620431, 6620501, 6620529, 6620596, 6620674, 6620691, 6620770, 6620813, + 6620889, 6620890, 6620891, 6620892, 6620893, 6620894, 6620895, 6620928, 6620929, 6620948, + 6621023, 6621035, 6621046, 6621183, 6621224, 6621227, 6621261, 6621274, 6621345, 6621346, + 6621347, 6621348, 6621349, 6621350, 6621351, 6621352, 6621353, 6621354, 6621355, 6621356, + 6621357, 6621358, 6621359, 6621360, 6621361, 6621362, 6621363, 6621364, 6621365, 6621395, + 6621442, 6621457, 6621518, 6621519, 6621520, 6621521, 6621522, 6621523, 6621524, 6621525, + 6621526, 6621527, 6621538, 6621539, 6621540, 6621541, 6621542, 6621543, 6621544, 6621545, + 6621546, 6621547, 6621548, 6621553, 6621666, 6621715, 6621724, 6621738, 6621844, 6621845, + 6621859, 6621875, 6621891, 6621912, 6621964, 6621969, 6621998, 6621999, 6622037, 6622068, + 6622125, 6622126, 6622137, 6622196, 6622327, 6622328, 6622331, 6622333, 6622355, 6622374, + 6622390, 6622410, 6622411, 6622412, 6622417, 6622418, 6622419, 6622420, 6622421, 6622422, + 6622423, 6622424, 6622425, 6622426, 6622427, 6622428, 6622429, 6622430, 6622431, 6622432, + 6622433, 6622434, 6622518, 6622519, 6622551, 6622571, 6622588, 6622597, 6622599, 6622619, + 6622638, 6622703, 6622704, 6622705, 6622714, 6622734, 6622778, 6622833, 6622834, 6622849, + 6622872, 6622891, 6622964, 6622986, 6623000, 6623004, 6623037, 6623053, 6623054, 6623128, + 6623153, 6623233, 6623243, 6623247, 6623249, 6623267, 6623271, 6623302, 6623339, 6623341, + 6623342, 6623350, 6623353, 6623419, 6623437, 6623513, 6623603, 6623632, 6623656, 6623683, + 6623684, 6623685, 6623686, 6623687, 6623688, 6623689, 6623690, 6623691, 6623692, 6623693, + 6623694, 6623765, 6623767, 6623769, 6623776, 6623785, 6623816, 6623824, 6623840, 6623888, + 6623949, 6623974, 6623979, 6624005, 6624019, 6624053, 6624054, 6624069, 6624079, 6624085, + 6624122, 6624140, 6624144, 6624265, 6624275, 6624276, 6624277, 6624278, 6624350, 6624365, + 6624371, 6624379, 6624384, 6624389, 6624390, 6624415, 6624433, 6624483, 6624492, 6624495, + 6624509, 6624537, 6624563, 6624622, 6624628, 6624748, 6624766, 6624801, 6624813, 6624870, + 6624874, 6624887, 6624936, 6624961, 6625015, 6625042, 6625064, 6625065, 6625066, 6625072, + 6625113, 6625114, 6625115, 6625116, 6625117, 6625118, 6625132, 6625209, 6625235, 6625250, + 6625282, 6625308, 6625404, 6625410, 6625411, 6625415, 6625445, 6625472, 6625501, 6625502, + 6625544, 6625578, 6625581, 6625627, 6625654, 6625771, 6625772, 6625773, 6625774, 6625775, + 6625776, 6625829, 6625831, 6625841, 6625863, 6625872, 6625885, 6625925, 6625933, 6625950, + 6626001, 6626026, 6626038, 6626089, 6626148, 6626273, 6626326, 6626327, 6626328, 6626329, + 6626330, 6626331, 6626332, 6626333, 6626334, 6626335, 6626336, 6626337, 6626423, 6626436, + 6626477, 6626570, 6626571, 6626572, 6626573, 6626583, 6626585, 6626607, 6626608, 6626609, + 6626610, 6626611, 6626612, 6626613, 6626614, 6626615, 6626687, 6626688, 6626689, 6626690, + 6626705, 6626751, 6626835, 6626843, 6626891, 6626903, 6626925, 6626999, 6627003, 6627071, + 6627077, 6627085, 6627118, 6627182, 6627183, 6627184, 6627185, 6627186, 6627187, 6627188, + 6627189, 6627190, 6627191, 6627192, 6627234, 6627241, 6627270, 6627304, 6627305, 6627306, + 6627307, 6627308, 6627309, 6627310, 6627311, 6627312, 6627313, 6627314, 6627315, 6627316, + 6627317, 6627332, 6627333, 6627334, 6627335, 6627358, 6627453, 6627507, 6627542, 6627543, + 6627544, 6627545, 6627560, 6627571, 6627580, 6627636, 6627637, 6627638, 6627639, 6627640, + 6627641, 6627642, 6627643, 6627644, 6627645, 6627707, 6627708, 6627709, 6627710, 6627711, + 6627712, 6627713, 6627714, 6627715, 6627716, 6627717, 6627718, 6627746, 6627747, 6627748, + 6627749, 6627760, 6627769, 6627809, 6627861, 6627989, 6627995, 6628007, 6628009, 6628034, + 6628035, 6628036, 6628037, 6628038, 6628039, 6628040, 6628041, 6628105, 6628124, 6628132, + 6628149, 6628228, 6628229, 6628386, 6628387, 6628406, 6628440, 6628503, 6628546, 6628711, + 6628714, 6628715, 6628716, 6628721, 6628760, 6628761, 6628804, 6628920, 6629022, 6629086, + 6629088, 6629100, 6629102, 6629164, 6629167, 6629168, 6629177, 6629180, 6629181, 6629182, + 6629183, 6629204, 6629222, 6629228, 6629245, 6629270, 6629271, 6629272, 6629273, 6629274, + 6629275, 6629276, 6629277, 6629278, 6629279, 6629280, 6629281, 6629282, 6629283, 6629291, + 6629292, 6629345, 6629503, 6629555, 6629556, 6629594, 6629595, 6629596, 6629597, 6629614, + 6629647, 6629648, 6629649, 6629650, 6629673, 6629692, 6629701, 6629713, 6629719, 6629720, + 6629721, 6629722, 6629723, 6629724, 6629725, 6629728, 6629753, 6629786, 6629789, 6629809, + 6629812, 6629819, 6629879, 6629890, 6629980, 6629981, 6629982, 6629983, 6629984, 6629985, + 6629986, 6629987, 6629988, 6629989, 6629990, 6629991, 6629992, 6630012, 6630026, 6630076, + 6630110, 6630190, 6630191, 6630195, 6630221, 6630227, 6630237, 6630245, 6630340, 6630341, + 6630342, 6630343, 6630482, 6630524, 6630531, 6630532, 6630535, 6630543, 6630571, 6630591, + 6630607, 6630611, 6630615, 6630624, 6630634, 6630643, 6630665, 6630666, 6630667, 6630668, + 6630669, 6630670, 6630671, 6630672, 6630673, 6630674, 6630675, 6630676, 6630677, 6630731, + 6630743, 6630745, 6630753, 6630797, 6630849, 6630850, 6630851, 6630852, 6630853, 6630854, + 6630855, 6630856, 6630857, 6630858, 6630859, 6630860, 6630884, 6630893, 6630896, 6630902, + 6630910, 6630918, 6630922, 6630923, 6630979, 6630986, 6630998, 6631010, 6631060, 6631061, + 6631062, 6631063, 6631064, 6631065, 6631066, 6631067, 6631068, 6631069, 6631070, 6631071, + 6631099, 6631130, 6631141, 6631148, 6631158, 6631176, 6631181, 6631183, 6631238, 6631261, + 6631289, 6631294, 6631410, 6631453, 6631458, 6631470, 6631581, 6631603, 6631627, 6631650, + 6631709, 6631711, 6631734, 6631789, 6631793, 6631815, 6631834, 6631897, 6631950, 6631995, + 6631997, 6632005, 6632007, 6632199, 6632223, 6632224, 6632295, 6632365, 6632440, 6632441, + 6632466, 6632473, 6632491, 6632492, 6632495, 6632496, 6632497, 6632498, 6632499, 6632500, + 6632501, 6632502, 6632503, 6632504, 6632505, 6632506, 6632510, 6632514, 6632524, 6632541, + 6632565, 6632646, 6632647, 6632648, 6632649, 6632650, 6632651, 6632652, 6632653, 6632654, + 6632655, 6632662, 6632746, 6632822, 6632831, 6632840, 6632859, 6632901, 6632902, 6632908, + 6632911, 6632912, 6632913, 6632914, 6632915, 6632916, 6632917, 6632918, 6632919, 6632920, + 6632921, 6632924, 6632927, 6632983, 6632987, 6632991, 6632994, 6633069, 6633071, 6633103, + 6633110, 6633126, 6633155, 6633172, 6633249, 6633275, 6633407, 6633446, 6633537, 6633560, + 6633576, 6633680, 6633735, 6633752, 6633791, 6633845, 6633846, 6633847, 6633848, 6633855, + 6633860, 6633867, 6633885, 6633894, 6633898, 6633903, 6633929, 6633980, 6633995, 6634093, + 6634114, 6634167, 6634170, 6634215, 6634270, 6634399, 6634410, 6634546, 6634588, 6634599, + 6634821, 6634822, 6634823, 6634824, 6634825, 6634826, 6634901, 6634911, 6634913, 6634914, + 6634915, 6634920, 6634921, 6634924, 6634996, 6635018, 6635037, 6635082, 6635117, 6635140, + 6635163, 6635165, 6635167, 6635170, 6635172, 6635223, 6635241, 6635295, 6635296, 6635361, + 6635365, 6635416, 6635417, 6635418, 6635419, 6635420, 6635421, 6635422, 6635447, 6635603, + 6635682, 6635732, 6635735, 6635738, 6635765, 6635793, 6635815, 6635832, 6635840, 6635856, + 6636059, 6636060, 6636071, 6636124, 6636125, 6636163, 6636164, 6636165, 6636166, 6636167, + 6636168, 6636169, 6636170, 6636171, 6636172, 6636173, 6636174, 6636212, 6636248, 6636272, + 6636284, 6636367, 6636403, 6636412, 6636414, 6636453, 6636454, 6636455, 6636456, 6636457, + 6636458, 6636459, 6636460, 6636461, 6636462, 6636463, 6636464, 6636465, 6636466, 6636467, + 6636468, 6636469, 6636470, 6636471, 6636472, 6636473, 6636474, 6636475, 6636476, 6636477, + 6636478, 6636479, 6636480, 6636481, 6636482, 6636483, 6636534, 6636666, 6636735, 6636746, + 6636757, 6636797, 6636846, 6636863, 6636864, 6636913, 6636980, 6636981, 6636982, 6636983, + 6636984, 6636985, 6636986, 6636987, 6636988, 6636989, 6636998, 6637054, 6637055, 6637056, + 6637057, 6637058, 6637059, 6637060, 6637061, 6637062, 6637063, 6637065, 6637068, 6637071, + 6637076, 6637113, 6637218, 6637240, 6637429, 6637453, 6637468, 6637526, 6637563, 6637581, + 6637587, 6637615, 6637619, 6637656, 6637680, 6637681, 6637682, 6637713, 6637757, 6637813, + 6637895, 6637899, 6637912, 6637917, 6637948, 6637949, 6638051, 6638052, 6638075, 6638093, + 6638229, 6638250, 6638315, 6638334, 6638335, 6638336, 6638337, 6638372, 6638373, 6638383, + 6638384, 6638386, 6638387, 6638401, 6638415, 6638545, 6638546, 6638560, 6638561, 6638562, + 6638563, 6638564, 6638565, 6638566, 6638567, 6638568, 6638569, 6638570, 6638571, 6638575, + 6638608, 6638609, 6638631, 6638673, 6638675, 6638683, 6638687, 6638694, 6638697, 6638701, + 6638706, 6638735, 6638736, 6638737, 6638738, 6638761, 6638769, 6638809, 6638810, 6638864, + 6638873, 6638874, 6638875, 6638876, 6638877, 6638878, 6638879, 6638880, 6638881, 6638882, + 6638883, 6638936, 6638966, 6639029, 6639058, 6639066, 6639196, 6639236, 6639266, 6639267, + 6639268, 6639269, 6639273, 6639282, 6639293, 6639295, 6639299, 6639303, 6639444, 6639467, + 6639491, 6639560, 6639573, 6639574, 6639575, 6639576, 6639577, 6639578, 6639602, 6639619, + 6639636, 6639677, 6639693, 6639694, 6639709, 6639763, 6639770, 6639810, 6639898, 6639920, + 6639983, 6639991, 6640019, 6640020, 6640021, 6640022, 6640023, 6640024, 6640025, 6640026, + 6640027, 6640028, 6640029, 6640030, 6640031, 6640032, 6640033, 6640034, 6640035, 6640036, + 6640037, 6640081, 6640134, 6640139, 6640140, 6640141, 6640142, 6640143, 6640144, 6640145, + 6640146, 6640147, 6640148, 6640149, 6640150, 6640151, 6640152, 6640153, 6640239, 6640272, + 6640273, 6640274, 6640275, 6640276, 6640282, 6640287, 6640404, 6640419, 6640420, 6640421, + 6640422, 6640442, 6640510, 6640512, 6640527, 6640528, 6640532, 6640566, 6640585, 6640588, + 6640678, 6640708, 6640736, 6640738, 6640767, 6640768, 6640844, 6640856, 6640881, 6640928, + 6641043, 6641082, 6641090, 6641116, 6641117, 6641125, 6641126, 6641127, 6641198, 6641213, + 6641217, 6641222, 6641226, 6641247, 6641326, 6641365, 6641373, 6641394, 6641456, 6641459, + 6641464, 6641515, 6641527, 6641536, 6641572, 6641573, 6641574, 6641575, 6641576, 6641577, + 6641578, 6641579, 6641580, 6641581, 6641582, 6641583, 6641584, 6641585, 6641586, 6641590, + 6641593, 6641604, 6641612, 6641733, 6641734, 6641735, 6641736, 6641737, 6641738, 6641762, + 6641771, 6641793, 6641811, 6641830, 6641862, 6642040, 6642073, 6642083, 6642084, 6642085, + 6642086, 6642087, 6642088, 6642089, 6642090, 6642091, 6642092, 6642093, 6642094, 6642159, + 6642167, 6642172, 6642173, 6642177, 6642183, 6642269, 6642270, 6642271, 6642304, 6642306, + 6642308, 6642338, 6642384, 6642459, 6642545, 6642558, 6642559, 6642560, 6642561, 6642562, + 6642563, 6642564, 6642565, 6642566, 6642567, 6642568, 6642569, 6642570, 6642571, 6642572, + 6642732, 6642752, 6642754, 6642761, 6642849, 6642850, 6643035, 6643047, 6643075, 6643093, + 6643107, 6643113, 6643130, 6643154, 6643161, 6643169, 6643170, 6643171, 6643172, 6643173, + 6643174, 6643175, 6643176, 6643177, 6643178, 6643179, 6643180, 6643181, 6643230, 6643241, + 6643261, 6643351, 6643353, 6643354, 6643355, 6643370, 6643379, 6643537, 6643538, 6643563, + 6643572, 6643655, 6643656, 6643661, 6643662, 6643663, 6643664, 6643665, 6643666, 6643667, + 6643668, 6643669, 6643670, 6643671, 6643672, 6643675, 6643766, 6643806, 6643837, 6643838, + 6643839, 6643879, 6643899, 6643900, 6643902, 6643984, 6644030, 6644032, 6644043, 6644050, + 6644051, 6644052, 6644053, 6644054, 6644055, 6644056, 6644057, 6644058, 6644059, 6644060, + 6644061, 6644066, 6644067, 6644075, 6644085, 6644089, 6644109, 6644154, 6644155, 6644164, + 6644165, 6644172, 6644173, 6644174, 6644175, 6644176, 6644177, 6644178, 6644179, 6644180, + 6644181, 6644182, 6644183, 6644184, 6644185, 6644201, 6644250, 6644260, 6644263, 6644345, + 6644427, 6644428, 6644432, 6644522, 6644551, 6644584, 6644619, 6644620, 6644621, 6644661, + 6644680, 6644681, 6644777, 6644779, 6644785, 6644789, 6644802, 6644803, 6644900, 6644919, + 6644930, 6645031, 6645133, 6645171, 6645197, 6645235, 6645236, 6645237, 6645238, 6645239, + 6645240, 6645241, 6645242, 6645243, 6645244, 6645245, 6645246, 6645247, 6645248, 6645250, + 6645251, 6645267, 6645268, 6645269, 6645270, 6645271, 6645272, 6645273, 6645274, 6645289, + 6645303, 6645307, 6645308, 6645309, 6645310, 6645311, 6645312, 6645313, 6645314, 6645315, + 6645316, 6645317, 6645318, 6645319, 6645344, 6645362, 6645365, 6645412, 6645413, 6645414, + 6645415, 6645416, 6645417, 6645418, 6645419, 6645420, 6645421, 6645422, 6645427, 6645435, + 6645438, 6645458, 6645479, 6645498, 6645499, 6645500, 6645501, 6645523, 6645536, 6645645, + 6645646, 6645647, 6645648, 6645649, 6645650, 6645651, 6645652, 6645653, 6645654, 6645655, + 6645656, 6645657, 6645658, 6645659, 6645660, 6645661, 6645662, 6645663, 6645664, 6645665, + 6645692, 6645709, 6645710, 6645711, 6645712, 6645751, 6645852, 6645908, 6645909, 6645910, + 6645930, 6645931, 6645932, 6645933, 6645935, 6645936, 6645950, 6646040, 6646050, 6646060, + 6646064, 6646065, 6646069, 6646082, 6646103, 6646202, 6646240, 6646241, 6646242, 6646243, + 6646244, 6646245, 6646246, 6646247, 6646248, 6646249, 6646266, 6646267, 6646269, 6646275, + 6646276, 6646277, 6646278, 6646279, 6646280, 6646281, 6646282, 6646283, 6646284, 6646302, + 6646303, 6646304, 6646305, 6646390, 6646391, 6646392, 6646393, 6646394, 6646395, 6646396, + 6646397, 6646398, 6646399, 6646400, 6646414, 6646420, 6646436, 6646473, 6646494, 6646529, + 6646536, 6646537, 6646538, 6646539, 6646540, 6646541, 6646569, 6646570, 6646571, 6646572, + 6646573, 6646574, 6646575, 6646576, 6646577, 6646578, 6646585, 6646661, 6646682, 6646771, + 6646845, 6646855, 6646865, 6646866, 6646867, 6646868, 6646869, 6646870, 6646871, 6646872, + 6646873, 6646874, 6646875, 6646876, 6646877, 6646882, 6646932, 6646941, 6646974, 6647028, + 6647119, 6647124, 6647165, 6647193, 6647207, 6647226, 6647230, 6647268, 6647269, 6647270, + 6647271, 6647322, 6647364, 6647375, 6647489, 6647508, 6647518, 6647560, 6647573, 6647590, + 6647629, 6647770, 6647781, 6647783, 6647903, 6647977, 6647978, 6647979, 6647980, 6647981, + 6647982, 6647983, 6647984, 6647985, 6647986, 6647987, 6647988, 6647989, 6647990, 6647991, + 6647992, 6647993, 6648069, 6648083, 6648084, 6648085, 6648086, 6648111, 6648179, 6648184, + 6648203, 6648218, 6648243, 6648335, 6648342, 6648389, 6648391, 6648481, 6648548, 6648587, + 6648588, 6648589, 6648590, 6648591, 6648592, 6648593, 6648594, 6648595, 6648596, 6648597, + 6648598, 6648599, 6648600, 6648601, 6648602, 6648603, 6648604, 6648605, 6648606, 6648607, + 6648608, 6648609, 6648687, 6648688, 6648689, 6648690, 6648691, 6648692, 6648693, 6648694, + 6648695, 6648696, 6648697, 6648698, 6648699, 6648700, 6648763, 6648781, 6648788, 6648845, + 6648846, 6648847, 6648848, 6648849, 6648850, 6648851, 6648852, 6648853, 6648854, 6648857, + 6648866, 6648966, 6648967, 6648992, 6649011, 6649012, 6649015, 6649032, 6649047, 6649064, + 6649065, 6649066, 6649067, 6649068, 6649069, 6649070, 6649071, 6649072, 6649073, 6649074, + 6649075, 6649076, 6649077, 6649084, 6649087, 6649156, 6649159, 6649374, 6649410, 6649495, + 6649505, 6649673, 6649683, 6649684, 6649718, 6649733, 6649758, 6649773, 6649784, 6649809, + 6649872, 6649931, 6649935, 6650007, 6650014, 6650016, 6650071, 6650072, 6650073, 6650074, + 6650075, 6650076, 6650077, 6650106, 6650107, 6650108, 6650109, 6650110, 6650111, 6650112, + 6650113, 6650118, 6650119, 6650120, 6650121, 6650122, 6650123, 6650124, 6650180, 6650181, + 6650182, 6650183, 6650184, 6650185, 6650186, 6650187, 6650188, 6650189, 6650190, 6650220, + 6650221, 6650269, 6650270, 6650271, 6650272, 6650299, 6650303, 6650364, 6650380, 6650390, + 6650392, 6650435, 6650469, 6650471, 6650523, 6650524, 6650525, 6650526, 6650527, 6650528, + 6650529, 6650530, 6650531, 6650532, 6650533, 6650534, 6650535, 6650536, 6650537, 6650538, + 6650582, 6650673, 6650693, 6650711, 6650712, 6650767, 6650886, 6650921, 6650955, 6650970, + 6650977, 6651003, 6651039, 6651060, 6651061, 6651062, 6651063, 6651064, 6651065, 6651066, + 6651067, 6651068, 6651073, 6651087, 6651088, 6651089, 6651090, 6651091, 6651138, 6651175, + 6651262, 6651270, 6651271, 6651272, 6651273, 6651297, 6651315, 6651316, 6651317, 6651319, + 6651321, 6651342, 6651351, 6651432, 6651468, 6651469, 6651470, 6651506, 6651549, 6651561, + 6651592, 6651604, 6651616, 6651627, 6651646, 6651682, 6651687, 6651719, 6651720, 6651729, + 6651734, 6651754, 6651795, 6651837, 6651856, 6651881, 6651934, 6651935, 6651936, 6651937, + 6651939, 6651948, 6651949, 6651950, 6651951, 6651954, 6651967, 6651970, 6651989, 6651995, + 6652053, 6652115, 6652140, 6652147, 6652151, 6652154, 6652161, 6652185, 6652220, 6652221, + 6652222, 6652223, 6652224, 6652225, 6652226, 6652227, 6652229, 6652230, 6652242, 6652282, + 6652370, 6652376, 6652385, 6652471, 6652472, 6652473, 6652474, 6652481, 6652482, 6652502, + 6652549, 6652552, 6652651, 6652652, 6652653, 6652654, 6652671, 6652683, 6652687, 6652688, + 6652689, 6652690, 6652691, 6652692, 6652700, 6652741, 6652754, 6652790, 6652895, 6653068, + 6653122, 6653171, 6653189, 6653191, 6653202, 6653264, 6653268, 6653274, 6653279, 6653288, + 6653396, 6653413, 6653414, 6653415, 6653416, 6653417, 6653441, 6653442, 6653443, 6653444, + 6653445, 6653484, 6653534, 6653536, 6653583, 6653628, 6653677, 6653683, 6653736, 6653811, + 6653865, 6653866, 6653867, 6653868, 6653869, 6653870, 6653871, 6653872, 6653873, 6653896, + 6653922, 6653923, 6653924, 6653925, 6653926, 6653927, 6653928, 6653929, 6653930, 6653931, + 6653932, 6653933, 6653936, 6653941, 6654031, 6654050, 6654055, 6654155, 6654166, 6654254, + 6654257, 6654258, 6654259, 6654260, 6654290, 6654316, 6654317, 6654325, 6654342, 6654408, + 6654409, 6654410, 6654411, 6654412, 6654413, 6654414, 6654415, 6654416, 6654417, 6654418, + 6654419, 6654469, 6654470, 6654471, 6654472, 6654511, 6654564, 6654565, 6654566, 6654567, + 6654568, 6654569, 6654570, 6654571, 6654572, 6654719, 6654746, 6654799, 6654815, 6654829, + 6654831, 6654837, 6654853, 6654854, 6654855, 6654856, 6654857, 6654858, 6654859, 6654860, + 6654861, 6654862, 6654863, 6654864, 6654865, 6654866, 6654908, 6654912, 6654949, 6654951, + 6654952, 6654954, 6654956, 6654959, 6654961, 6655039, 6655040, 6655041, 6655042, 6655043, + 6655044, 6655045, 6655046, 6655047, 6655048, 6655049, 6655050, 6655051, 6655052, 6655053, + 6655054, 6655055, 6655059, 6655060, 6655096, 6655127, 6655128, 6655129, 6655130, 6655131, + 6655132, 6655133, 6655134, 6655135, 6655136, 6655137, 6655138, 6655139, 6655195, 6655217, + 6655230, 6655385, 6655386, 6655424, 6655425, 6655426, 6655427, 6655428, 6655429, 6655430, + 6655431, 6655432, 6655433, 6655434, 6655450, 6655536, 6655562, 6655566, 6655600, 6655627, + 6655793, 6655830, 6655856, 6655943, 6655978, 6656053, 6656184, 6656201, 6656205, 6656301, + 6656304, 6656315, 6656316, 6656343, 6656419, 6656424, 6656442, 6656447, 6656535, 6656536, + 6656537, 6656538, 6656539, 6656540, 6656542, 6656558, 6656583, 6656680, 6656696, 6656774, + 6656828, 6656829, 6656830, 6656831, 6656834, 6656865, 6656906, 6656935, 6656964, 6657189, + 6657198, 6657215, 6657229, 6657238, 6657242, 6657284, 6657290, 6657298, 6657303, 6657420, + 6657426, 6657429, 6657430, 6657509, 6657560, 6657574, 6657589, 6657591, 6657617, 6657631, + 6657644, 6657649, 6657653, 6657694, 6657741, 6657747, 6657797, 6657874, 6657875, 6657876, + 6657877, 6657878, 6657885, 6657897, 6657898, 6657899, 6657900, 6657901, 6657902, 6657903, + 6657904, 6657905, 6657906, 6657951, 6658009, 6658039, 6658040, 6658041, 6658043, 6658061, + 6658126, 6658130, 6658158, 6658267, 6658268, 6658271, 6658272, 6658273, 6658274, 6658275, + 6658276, 6658277, 6658278, 6658279, 6658280, 6658281, 6658282, 6658283, 6658284, 6658285, + 6658286, 6658287, 6658288, 6658289, 6658290, 6658291, 6658333, 6658400, 6658422, 6658433, + 6658477, 6658515, 6658516, 6658517, 6658518, 6658519, 6658604, 6658688, 6658689, 6658701, + 6658702, 6658703, 6658704, 6658706, 6658743, 6658764, 6658767, 6658796, 6658885, 6658912, + 6658920, 6659115, 6659130, 6659208, 6659209, 6659282, 6659289, 6659326, 6659345, 6659346, + 6659347, 6659348, 6659349, 6659350, 6659351, 6659352, 6659353, 6659354, 6659355, 6659356, + 6659371, 6659430, 6659497, 6659528, 6659539, 6659564, 6659591, 6659638, 6659662, 6659663, + 6659664, 6659665, 6659666, 6659667, 6659668, 6659669, 6659670, 6659671, 6659672, 6659673, + 6659674, 6659675, 6659676, 6659677, 6659678, 6659679, 6659680, 6659681, 6659682, 6659683, + 6659684, 6659685, 6659686, 6659687, 6659688, 6659689, 6659690, 6659691, 6659692, 6659693, + 6659694, 6659695, 6659696, 6659697, 6659698, 6659713, 6659715, 6659753, 6659844, 6659845, + 6659846, 6659847, 6659848, 6659849, 6659850, 6659851, 6659852, 6659867, 6659893, 6659977, + 6659978, 6659979, 6659980, 6659981, 6659982, 6659983, 6659984, 6659985, 6659986, 6659987, + 6659988, 6660062, 6660079, 6660083, 6660173, 6660184, 6660185, 6660186, 6660212, 6660242, + 6660248, 6660265, 6660277, 6660278, 6660302, 6660304, 6660311, 6660355, 6660357, 6660358, + 6660362, 6660366, 6660368, 6660369, 6660386, 6660408, 6660409, 6660484, 6660492, 6660529, + 6660530, 6660531, 6660734, 6660755, 6660756, 6660762, 6660770, 6660862, 6660863, 6660868, + 6660869, 6660870, 6660871, 6660872, 6660873, 6660989, 6661021, 6661026, 6661030, 6661074, + 6661075, 6661076, 6661079, 6661176, 6661188, 6661272, 6661276, 6661278, 6661282, 6661291, + 6661331, 6661398, 6661412, 6661452, 6661466, 6661475, 6661477, 6661490, 6661492, 6661512, + 6661579, 6661646, 6661711, 6661712, 6661713, 6661714, 6661715, 6661716, 6661717, 6661718, + 6661719, 6661727, 6661736, 6661778, 6661779, 6661780, 6661781, 6661853, 6661860, 6661900, + 6661980, 6662016, 6662017, 6662018, 6662019, 6662020, 6662021, 6662022, 6662023, 6662024, + 6662027, 6662028, 6662062, 6662083, 6662104, 6662119, 6662143, 6662144, 6662371, 6662474, + 6662540, 6662558, 6662572, 6662573, 6662574, 6662575, 6662576, 6662577, 6662653, 6662666, + 6662721, 6662740, 6662798, 6662856, 6663006, 6663021, 6663046, 6663047, 6663048, 6663049, + 6663050, 6663051, 6663052, 6663053, 6663054, 6663055, 6663056, 6663057, 6663058, 6663059, + 6663060, 6663061, 6663062, 6663063, 6663064, 6663065, 6663066, 6663067, 6663068, 6663069, + 6663070, 6663071, 6663072, 6663073, 6663074, 6663084, 6663085, 6663086, 6663087, 6663088, + 6663089, 6663090, 6663091, 6663092, 6663093, 6663094, 6663095, 6663096, 6663097, 6663098, + 6663152, 6663251, 6663252, 6663255, 6663256, 6663257, 6663258, 6663259, 6663260, 6663261, + 6663262, 6663297, 6663298, 6663300, 6663302, 6663319, 6663340, 6663345, 6663368, 6663369, + 6663370, 6663371, 6663372, 6663373, 6663374, 6663391, 6663412, 6663462, 6663463, 6663527, + 6663568, 6663569, 6663570, 6663571, 6663572, 6663573, 6663574, 6663575, 6663576, 6663577, + 6663578, 6663579, 6663601, 6663602, 6663603, 6663604, 6663605, 6663606, 6663607, 6663608, + 6663609, 6663610, 6663658, 6663659, 6663666, 6663669, 6663696, 6663697, 6663744, 6663777, + 6663778, 6663779, 6663780, 6663781, 6663782, 6663783, 6663784, 6663785, 6663786, 6663787, + 6663788, 6663789, 6663790, 6663791, 6663792, 6663793, 6663794, 6663795, 6663796, 6663797, + 6663798, 6663799, 6663800, 6663801, 6663809, 6663810, 6663838, 6663843, 6663975, 6663989, + 6663990, 6663991, 6663994, 6663995, 6663996, 6663998, 6664001, 6664003, 6664004, 6664035, + 6664055, 6664142, 6664143, 6664159, 6664188, 6664197, 6664203, 6664254, 6664354, 6664368, + 6664487, 6664530, 6664561, 6664562, 6664563, 6664564, 6664565, 6664566, 6664567, 6664568, + 6664569, 6664570, 6664571, 6664572, 6664573, 6664574, 6664575, 6664576, 6664577, 6664578, + 6664579, 6664580, 6664581, 6664582, 6664583, 6664629, 6664631, 6664641, 6664646, 6664670, + 6664686, 6664687, 6664688, 6664705, 6664770, 6664798, 6664799, 6664800, 6664801, 6664802, + 6664803, 6664804, 6664805, 6664806, 6664863, 6664864, 6664909, 6664910, 6664983, 6665030, + 6665147, 6665157, 6665174, 6665175, 6665176, 6665180, 6665183, 6665190, 6665244, 6665245, + 6665249, 6665250, 6665251, 6665252, 6665253, 6665254, 6665255, 6665256, 6665268, 6665428, + 6665447, 6665485, 6665486, 6665487, 6665488, 6665489, 6665490, 6665491, 6665499, 6665578, + 6665579, 6665640, 6665641, 6665642, 6665643, 6665644, 6665645, 6665646, 6665647, 6665648, + 6665649, 6665650, 6665651, 6665652, 6665653, 6665654, 6665704, 6665711, 6665712, 6665719, + 6665786, 6665818, 6665896, 6665963, 6665986, 6666041, 6666042, 6666051, 6666096, 6666097, + 6666098, 6666107, 6666116, 6666129, 6666138, 6666164, 6666168, 6666325, 6666339, 6666359, + 6666365, 6666366, 6666367, 6666368, 6666369, 6666370, 6666371, 6666372, 6666381, 6666455, + 6666515, 6666526, 6666527, 6666545, 6666546, 6666547, 6666548, 6666549, 6666550, 6666551, + 6666552, 6666553, 6666554, 6666555, 6666556, 6666557, 6666558, 6666559, 6666587, 6666588, + 6666589, 6666590, 6666591, 6666592, 6666619, 6666624, 6666625, 6666626, 6666627, 6666628, + 6666629, 6666630, 6666636, 6666678, 6666708, 6666716, 6666752, 6666753, 6666776, 6666777, + 6666778, 6666779, 6666780, 6666781, 6666782, 6666783, 6666784, 6666785, 6666786, 6666787, + 6666788, 6666789, 6666790, 6666791, 6666873, 6666895, 6666921, 6666922, 6666923, 6666924, + 6666925, 6666926, 6666927, 6666928, 6666929, 6666930, 6666931, 6666932, 6666933, 6666934, + 6666935, 6666936, 6666937, 6666938, 6666939, 6666940, 6666941, 6666942, 6666998, 6667028, + 6667044, 6667045, 6667046, 6667047, 6667048, 6667084, 6667106, 6667116, 6667181, 6667235, + 6667236, 6667237, 6667238, 6667239, 6667240, 6667241, 6667242, 6667243, 6667244, 6667245, + 6667246, 6667247, 6667248, 6667249, 6667250, 6667251, 6667252, 6667253, 6667254, 6667255, + 6667256, 6667257, 6667258, 6667259, 6667260, 6667261, 6667262, 6667263, 6667264, 6667341, + 6667342, 6667343, 6667344, 6667345, 6667346, 6667347, 6667349, 6667350, 6667351, 6667352, + 6667353, 6667354, 6667355, 6667356, 6667357, 6667358, 6667374, 6667381, 6667391, 6667444, + 6667458, 6667459, 6667460, 6667461, 6667462, 6667463, 6667464, 6667465, 6667466, 6667467, + 6667468, 6667469, 6667496, 6667561, 6667592, 6667621, 6667622, 6667682, 6667683, 6667684, + 6667685, 6667686, 6667687, 6667700, 6667727, 6667728, 6667729, 6667730, 6667731, 6667732, + 6667733, 6667734, 6667735, 6667736, 6667737, 6667738, 6667739, 6667740, 6667741, 6667748, + 6667752, 6667767, 6667768, 6667769, 6667770, 6667771, 6667772, 6667773, 6667774, 6667775, + 6667776, 6667777, 6667778, 6667779, 6667780, 6667781, 6667782, 6667783, 6667784, 6667785, + 6667794, 6667811, 6667812, 6667853, 6667883, 6667884, 6667887, 6667896, 6667906, 6668079, + 6668240, 6668266, 6668281, 6668347, 6668348, 6668351, 6668369, 6668370, 6668371, 6668372, + 6668456, 6668471, 6668492, 6668503, 6668507, 6668508, 6668521, 6668542, 6668635, 6668651, + 6668658, 6668700, 6668701, 6668708, 6668833, 6668930, 6668931, 6668932, 6668933, 6668934, + 6668935, 6668936, 6668937, 6668938, 6668939, 6668946, 6668972, 6668998, 6669023, 6669026, + 6669032, 6669033, 6669034, 6669035, 6669076, 6669120, 6669143, 6669150, 6669166, 6669224, + 6669279, 6669295, 6669367, 6669373, 6669374, 6669375, 6669376, 6669377, 6669378, 6669379, + 6669380, 6669381, 6669382, 6669441, 6669590, 6669603, 6669654, 6669655, 6669715, 6669773, + 6669778, 6669787, 6669811, 6669812, 6669868, 6669869, 6669886, 6669980, 6669981, 6669982, + 6669983, 6669984, 6669985, 6669986, 6670014, 6670015, 6670016, 6670017, 6670060, 6670066, + 6670074, 6670077, 6670078, 6670079, 6670111, 6670145, 6670147, 6670172, 6670182, 6670252, + 6670266, 6670268, 6670352, 6670420, 6670422, 6670522, 6670623, 6670641, 6670649, 6670650, + 6670655, 6670696, 6670705, 6670709, 6670713, 6670727, 6670788, 6670808, 6670891, 6670892, + 6670893, 6670894, 6670895, 6670896, 6670897, 6670898, 6670899, 6670900, 6670901, 6670902, + 6670903, 6670920, 6670921, 6670922, 6670923, 6670924, 6670947, 6670970, 6671006, 6671007, + 6671022, 6671089, 6671134, 6671135, 6671136, 6671137, 6671138, 6671139, 6671140, 6671162, + 6671201, 6671205, 6671223, 6671277, 6671365, 6671419, 6671423, 6671427, 6671431, 6671435, + 6671439, 6671443, 6671447, 6671451, 6671455, 6671459, 6671463, 6671467, 6671471, 6671473, + 6671477, 6671481, 6671485, 6671489, 6671496, 6671497, 6671498, 6671499, 6671500, 6671501, + 6671502, 6671503, 6671504, 6671505, 6671506, 6671507, 6671508, 6671526, 6671540, 6671575, + 6671581, 6671639, 6671695, 6671697, 6671737, 6671753, 6671793, 6671830, 6671842, 6671943, + 6671990, 6671991, 6671992, 6672084, 6672086, 6672109, 6672110, 6672172, 6672196, 6672197, + 6672200, 6672201, 6672252, 6672257, 6672258, 6672259, 6672260, 6672264, 6672326, 6672327, + 6672328, 6672329, 6672330, 6672331, 6672332, 6672333, 6672334, 6672335, 6672336, 6672337, + 6672344, 6672347, 6672376, 6672386, 6672391, 6672392, 6672393, 6672394, 6672395, 6672396, + 6672397, 6672398, 6672399, 6672400, 6672413, 6672431, 6672432, 6672483, 6672566, 6672567, + 6672572, 6672596, 6672606, 6672686, 6672687, 6672719, 6672735, 6672750, 6672751, 6672770, + 6672825, 6672857, 6672934, 6672946, 6672950, 6673007, 6673020, 6673047, 6673061, 6673064, + 6673143, 6673172, 6673173, 6673174, 6673175, 6673176, 6673177, 6673178, 6673179, 6673192, + 6673219, 6673220, 6673225, 6673280, 6673281, 6673284, 6673285, 6673301, 6673302, 6673402, + 6673404, 6673424, 6673468, 6673514, 6673522, 6673525, 6673526, 6673551, 6673662, 6673681, + 6673760, 6673863, 6673871, 6673872, 6673873, 6673874, 6673875, 6673876, 6673877, 6673878, + 6673879, 6673880, 6673892, 6673893, 6673894, 6673895, 6673908, 6673909, 6673910, 6673911, + 6673912, 6673913, 6673914, 6673915, 6673916, 6673917, 6673918, 6673919, 6673920, 6673921, + 6673922, 6673923, 6673924, 6673929, 6673988, 6674035, 6674053, 6674054, 6674093, 6674103, + 6674107, 6674111, 6674147, 6674240, 6674254, 6674255, 6674256, 6674257, 6674258, 6674259, + 6674260, 6674261, 6674262, 6674263, 6674264, 6674280, 6674283, 6674302, 6674328, 6674333, + 6674342, 6674346, 6674350, 6674385, 6674386, 6674387, 6674388, 6674389, 6674390, 6674391, + 6674392, 6674393, 6674394, 6674395, 6674396, 6674397, 6674398, 6674399, 6674418, 6674453, + 6674454, 6674594, 6674607, 6674739, 6674745, 6674756, 6674761, 6674763, 6674836, 6674848, + 6674854, 6674863, 6674904, 6674906, 6674913, 6674914, 6674923, 6674924, 6674925, 6674926, + 6674927, 6674928, 6674929, 6674930, 6674939, 6675054, 6675067, 6675069, 6675090, 6675093, + 6675102, 6675114, 6675121, 6675123, 6675154, 6675170, 6675171, 6675238, 6675256, 6675290, + 6675324, 6675371, 6675372, 6675373, 6675374, 6675375, 6675376, 6675377, 6675378, 6675379, + 6675380, 6675383, 6675386, 6675410, 6675411, 6675423, 6675434, 6675484, 6675485, 6675507, + 6675511, 6675530, 6675540, 6675547, 6675553, 6675554, 6675642, 6675643, 6675644, 6675645, + 6675646, 6675647, 6675648, 6675649, 6675650, 6675651, 6675652, 6675653, 6675654, 6675664, + 6675713, 6675725, 6675733, 6675744, 6675775, 6675824, 6675879, 6675900, 6675902, 6675945, + 6675949, 6676070, 6676099, 6676108, 6676121, 6676129, 6676130, 6676131, 6676132, 6676133, + 6676134, 6676135, 6676136, 6676137, 6676138, 6676139, 6676140, 6676181, 6676183, 6676215, + 6676346, 6676367, 6676395, 6676412, 6676440, 6676468, 6676507, 6676538, 6676580, 6676631, + 6676634, 6676664, 6676675, 6676676, 6676677, 6676678, 6676679, 6676680, 6676681, 6676714, + 6676715, 6676716, 6676717, 6676718, 6676719, 6676720, 6676721, 6676722, 6676723, 6676724, + 6676725, 6676726, 6676727, 6676728, 6676729, 6676751, 6676756, 6676800, 6676853, 6676854, + 6676952, 6676953, 6676954, 6676955, 6676959, 6677111, 6677112, 6677123, 6677128, 6677152, + 6677170, 6677235, 6677238, 6677244, 6677254, 6677262, 6677281, 6677293, 6677303, 6677316, + 6677398, 6677449, 6677450, 6677451, 6677452, 6677453, 6677454, 6677455, 6677456, 6677457, + 6677458, 6677459, 6677460, 6677461, 6677462, 6677463, 6677464, 6677465, 6677466, 6677467, + 6677468, 6677469, 6677470, 6677471, 6677472, 6677473, 6677474, 6677475, 6677476, 6677477, + 6677478, 6677479, 6677480, 6677481, 6677530, 6677531, 6677532, 6677533, 6677534, 6677535, + 6677536, 6677537, 6677561, 6677570, 6677605, 6677606, 6677657, 6677660, 6677683, 6677710, + 6677772, 6677787, 6677810, 6677819, 6677821, 6677848, 6677898, 6677922, 6677931, 6677939, + 6677944, 6677945, 6677946, 6677947, 6677948, 6677949, 6677950, 6677951, 6677952, 6677953, + 6677954, 6677955, 6677956, 6677957, 6677958, 6678075, 6678089, 6678126, 6678217, 6678218, + 6678219, 6678221, 6678237, 6678331, 6678349, 6678350, 6678411, 6678412, 6678413, 6678414, + 6678415, 6678416, 6678417, 6678418, 6678419, 6678420, 6678421, 6678422, 6678423, 6678424, + 6678425, 6678426, 6678427, 6678428, 6678429, 6678430, 6678431, 6678432, 6678433, 6678434, + 6678435, 6678436, 6678437, 6678438, 6678439, 6678448, 6678454, 6678608, 6678609, 6678655, + 6678821, 6678866, 6678915, 6678917, 6678994, 6679027, 6679029, 6679036, 6679044, 6679100, + 6679101, 6679102, 6679103, 6679104, 6679105, 6679106, 6679107, 6679108, 6679109, 6679110, + 6679111, 6679112, 6679148, 6679163, 6679195, 6679196, 6679197, 6679198, 6679199, 6679200, + 6679201, 6679202, 6679203, 6679204, 6679235, 6679236, 6679237, 6679238, 6679239, 6679240, + 6679241, 6679242, 6679243, 6679244, 6679245, 6679246, 6679261, 6679264, 6679296, 6679316, + 6679342, 6679404, 6679511, 6679534, 6679548, 6679549, 6679585, 6679596, 6679598, 6679623, + 6679628, 6679641, 6679646, 6679671, 6679693, 6679701, 6679710, 6679716, 6679731, 6679735, + 6679737, 6679764, 6679812, 6679813, 6679814, 6679815, 6679816, 6679817, 6679818, 6679819, + 6679820, 6679821, 6679822, 6679823, 6679824, 6679825, 6679826, 6679827, 6679901, 6679902, + 6679903, 6679904, 6679946, 6679974, 6680017, 6680160, 6680161, 6680162, 6680163, 6680164, + 6680165, 6680167, 6680169, 6680171, 6680172, 6680173, 6680174, 6680175, 6680176, 6680178, + 6680179, 6680180, 6680182, 6680183, 6680203, 6680265, 6680304, 6680319, 6680342, 6680375, + 6680434, 6680441, 6680442, 6680448, 6680449, 6680450, 6680451, 6680452, 6680453, 6680454, + 6680455, 6680456, 6680457, 6680458, 6680459, 6680460, 6680461, 6680462, 6680508, 6680539, + 6680567, 6680594, 6680616, 6680628, 6680646, 6680676, 6680745, 6680746, 6680747, 6680748, + 6680749, 6680750, 6680751, 6680752, 6680753, 6680754, 6680755, 6680756, 6680757, 6680758, + 6680759, 6680760, 6680761, 6680762, 6680763, 6680764, 6680765, 6680766, 6680767, 6680768, + 6680769, 6680770, 6680771, 6680772, 6680773, 6680774, 6680775, 6680776, 6680777, 6680778, + 6680779, 6680780, 6680781, 6680782, 6680783, 6680784, 6680785, 6680786, 6680787, 6680788, + 6680789, 6680790, 6680791, 6680792, 6680793, 6680794, 6680795, 6680796, 6680797, 6680798, + 6680799, 6680800, 6680801, 6680802, 6680820, 6680955, 6680956, 6680957, 6680958, 6680959, + 6680960, 6680961, 6680962, 6680963, 6680964, 6680965, 6680966, 6680967, 6680968, 6680969, + 6680970, 6680971, 6680972, 6680973, 6680974, 6680975, 6680976, 6680977, 6680978, 6680979, + 6680980, 6680981, 6680982, 6680983, 6680984, 6680985, 6680986, 6680987, 6680988, 6680989, + 6680990, 6680991, 6680992, 6680993, 6680994, 6680995, 6680996, 6680997, 6680998, 6680999, + 6681060, 6681111, 6681145, 6681190, 6681201, 6681227, 6681229, 6681235, 6681237, 6681257, + 6681383, 6681436, 6681476, 6681477, 6681478, 6681479, 6681480, 6681481, 6681482, 6681483, + 6681484, 6681485, 6681550, 6681554, 6681576, 6681600, 6681614, 6681621, 6681789, 6681798, + 6681818, 6681819, 6681820, 6681821, 6681822, 6681823, 6681824, 6681825, 6681826, 6681827, + 6681828, 6681829, 6681830, 6681831, 6681832, 6681833, 6681864, 6681951, 6681952, 6681953, + 6681954, 6681955, 6681956, 6681957, 6681958, 6681959, 6681960, 6681961, 6681962, 6681966, + 6681993, 6682073, 6682074, 6682093, 6682115, 6682131, 6682176, 6682204, 6682291, 6682359, + 6682393, 6682399, 6682433, 6682445, 6682508, 6682522, 6682523, 6682524, 6682528, 6682629, + 6682697, 6682724, 6682754, 6682829, 6682830, 6682831, 6682832, 6682833, 6682834, 6682835, + 6682836, 6682837, 6682838, 6682839, 6682840, 6682841, 6682842, 6682843, 6682844, 6682845, + 6682846, 6682847, 6682880, 6682897, 6682932, 6682966, 6682969, 6682981, 6682992, 6682999, + 6683023, 6683030, 6683038, 6683042, 6683062, 6683080, 6683081, 6683082, 6683083, 6683084, + 6683085, 6683086, 6683087, 6683088, 6683089, 6683090, 6683091, 6683092, 6683093, 6683094, + 6683095, 6683096, 6683097, 6683098, 6683099, 6683100, 6683101, 6683102, 6683103, 6683104, + 6683105, 6683106, 6683107, 6683108, 6683136, 6683140, 6683211, 6683212, 6683213, 6683233, + 6683248, 6683251, 6683263, 6683339, 6683363, 6683365, 6683369, 6683370, 6683371, 6683372, + 6683418, 6683431, 6683441, 6683447, 6683541, 6683604, 6683626, 6683627, 6683628, 6683629, + 6683630, 6683631, 6683632, 6683633, 6683634, 6683635, 6683636, 6683747, 6683758, 6683878, + 6683984, 6684040, 6684070, 6684115, 6684116, 6684117, 6684118, 6684119, 6684120, 6684145, + 6684154, 6684156, 6684258, 6684261, 6684262, 6684282, 6684283, 6684285, 6684314, 6684316, + 6684318, 6684320, 6684323, 6684324, 6684325, 6684326, 6684327, 6684328, 6684329, 6684330, + 6684331, 6684332, 6684333, 6684334, 6684335, 6684336, 6684337, 6684378, 6684407, 6684414, + 6684416, 6684424, 6684472, 6684563, 6684574, 6684575, 6684576, 6684577, 6684601, 6684635, + 6684636, 6684639, 6684640, 6684641, 6684642, 6684666, 108658947, + ]; + let original = ARRAY.iter().cloned().collect::(); + let new = serialize_and_deserialize(&original); + assert_eq!(original, new); +} + +#[test] +fn test_runs() { + let mut original = RoaringBitmap::from_iter((1000..3000).chain(70000..77000)); + original.optimize(); + let new = serialize_and_deserialize(&original); + assert_eq!(original.len(), new.len()); + assert_eq!(original.min(), new.min()); + assert_eq!(original.max(), new.max()); +} + +fn assert_invalid_serialization(serialized: &[u8], msg: &str) { + let result = RoaringBitmap::deserialize_from(serialized); + if let Ok(res) = result { + panic!("Expected error: {msg}. Got: {res:?}"); + } +} + +#[test] +fn deserialize_negative_container_count() { + let data = [ + 0x3A, 0x30, 0, 0, // Serial cookie, no run containers + 0x00, 0x00, 0x00, 0x80, // Container count (NEGATIVE) + ]; + assert_invalid_serialization(&data, "Negative container count"); +} + +#[test] +fn deserialize_huge_container_count() { + const MAX_CONTAINERS: usize = 0xFFFF; + let data = [ + 0x3A, 0x30, 0, 0, // Serial cookie, no run containers + 0x01, 0x00, 0x01, 0x00, // Container count (MAX_CONTAINERS + 1) + ]; + assert_invalid_serialization(&data, "Huge container count"); + + // For each container, 32 bits for container offset, 16 bits for a key, cardinality - 1, and a + // single array value + let full_size = data.len() + (MAX_CONTAINERS + 1) * (4 + 3 * 2); + let mut full_data = vec![0; full_size]; + full_data[..data.len()].copy_from_slice(&data); + assert_invalid_serialization(&full_data, "Huge container count"); +} + +#[test] +fn deserialize_empty_run_container() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0x00, 0x00, // Container count - 1 + 0x01, // Run Flag Bitset (single container is a run) + 0, 0, // Upper 16 bits of the first container + 0, 0, // Cardinality - 1 of the first container + 0, 0, // First Container - Number of runs + ]; + assert_invalid_serialization(&data, "Empty run container"); +} + +#[test] +fn deserialize_run_container_contiguous_ranges() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0x00, 0x00, // Container count - 1 + 0x01, // Run Flag Bitset (single container is a run) + 0, 0, // Upper 16 bits of the first container + 1, 0, // Cardinality - 1 of the first container + 2, 0, // First Container - Number of runs + 0, 0, // First run start + 0, 0, // First run length - 1 + 1, 0, // Second run start (STARTS AT THE END OF THE FIRST) + 0, 0, // Second run length - 1 + ]; + + assert_invalid_serialization(&data, "Contiguous ranges in run container"); +} + +#[test] +fn deserialize_run_container_overlap() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0x00, 0x00, // Container count - 1 + 0x01, // Run Flag Bitset (single container is a run) + 0, 0, // Upper 16 bits of the first container + 4, 0, // Cardinality - 1 of the first container + 2, 0, // First Container - Number of runs + 0, 0, // First run start + 4, 0, // First run length - 1 + 1, 0, // Second run start (STARTS INSIDE THE FIRST) + 0, 0, // Second run length - 1 + ]; + + assert_invalid_serialization(&data, "Overlapping ranges in run container"); +} + +#[test] +fn deserialize_run_container_overflow() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0x00, 0x00, // Container count - 1 + 0x01, // Run Flag Bitset (single container is a run) + 0, 0, // Upper 16 bits of the first container + 4, 0, // Cardinality - 1 of the first container + 1, 0, // First Container - Number of runs + 0xFE, 0xFF, // First run start + 4, 0, // First run length - 1 (OVERFLOW) + ]; + + assert_invalid_serialization(&data, "Overflow in run container"); +} + +#[test] +fn deserialize_duplicate_keys() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0x01, 0x00, // Container count - 1 + 0, // Run Flag Bitset (no runs) + 0, 0, // Upper 16 bits of the first container + 0, 0, // Cardinality - 1 of the first container + 0, 0, // Upper 16 bits of the second container - DUPLICATE + 0, 0, // Cardinality - 1 of the second container + 0, 0, // Only value of first container + 0, 0, // Only value of second container + ]; + + assert_invalid_serialization(&data, "Duplicate keys in containers"); +} + +#[test] +fn deserialize_unsorted_keys() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 1, 0, // Container count - 1 + 0, // Run Flag Bitset (no runs) + 1, 0, // Upper 16 bits of the first container + 0, 0, // Cardinality - 1 of the first container + 0, 0, // Upper 16 bits of the second container (LESS THAN FIRST) + 0, 0, // Cardinality - 1 of the second container + 0, 0, // Only value of first container + 0, 0, // Only value of second container + ]; + + assert_invalid_serialization(&data, "Unsorted keys in containers"); +} + +#[test] +fn deserialize_array_duplicate_value() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0, 0, // Container count - 1 + 0, // Run Flag Bitset (no runs) + 0, 0, // Upper 16 bits of the first container + 1, 0, // Cardinality - 1 of the first container + 0, 0, // first value of first container + 0, 0, // second value of first container (DUPLICATE) + ]; + + assert_invalid_serialization(&data, "Duplicate values in array container"); +} + +#[test] +fn deserialize_array_unsorted_values() { + let data = [ + 0x3B, 0x30, // Serial Cookie + 0, 0, // Container count - 1 + 0, // Run Flag Bitset (no runs) + 0, 0, // Upper 16 bits of the first container + 1, 0, // Cardinality - 1 of the first container + 1, 0, // first value of first container + 0, 0, // second value of first container (LESS THAN FIRST) + ]; + + assert_invalid_serialization(&data, "Unsorted values in array container"); +} + +#[test] +fn deserialize_bitset_incorrect_cardinality() { + let data_start = [ + 0x3B, 0x30, // Serial Cookie + 0, 0, // Container count - 1 + 0, // Run Flag Bitset (no runs) + 0, 0, // Upper 16 bits of the first container + 0xFF, + 0xFF, // Cardinality - 1 of the first container. + + // First container is a bitset, should be followed by 1 << 16 bits + ]; + let mut data = vec![0xFF; data_start.len() + (1 << 16) / 8]; + data[..data_start.len()].copy_from_slice(&data_start); + // Bitset filled with 0xFF will have the correct cardinality + let result = RoaringBitmap::deserialize_from(&data[..]).unwrap(); + assert_eq!(result.len(), 0x1_0000); + + // Bitset will no longer have the correct cardinality + data[data_start.len()] = 0x0; + assert_invalid_serialization(&data, "Bitset incorrect cardinality"); +} diff --git a/vendor/roaring/tests/size_hint.rs b/vendor/roaring/tests/size_hint.rs new file mode 100644 index 0000000..14dc5d1 --- /dev/null +++ b/vendor/roaring/tests/size_hint.rs @@ -0,0 +1,81 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array() { + let bitmap = (0..2000).collect::(); + let mut iter = bitmap.iter(); + assert_eq!((2000, Some(2000)), iter.size_hint()); + iter.by_ref().take(1000).for_each(drop); + assert_eq!((1000, Some(1000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn bitmap() { + let bitmap = (0..6000).collect::(); + let mut iter = bitmap.iter(); + assert_eq!((6000, Some(6000)), iter.size_hint()); + iter.by_ref().take(3000).for_each(drop); + assert_eq!((3000, Some(3000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn run() { + let mut bitmap = RoaringBitmap::from_iter(0..6000); + bitmap.optimize(); + let mut iter = bitmap.iter(); + assert_eq!((6000, Some(6000)), iter.size_hint()); + iter.by_ref().take(3000).for_each(drop); + assert_eq!((3000, Some(3000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn arrays() { + let bitmap = (0..2000) + .chain(1_000_000..1_002_000) + .chain(2_000_000..2_001_000) + .collect::(); + let mut iter = bitmap.iter(); + assert_eq!((5000, Some(5000)), iter.size_hint()); + iter.by_ref().take(3000).for_each(drop); + assert_eq!((2000, Some(2000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn bitmaps() { + let bitmap = (0..6000) + .chain(1_000_000..1_012_000) + .chain(2_000_000..2_010_000) + .collect::(); + let mut iter = bitmap.iter(); + assert_eq!((28000, Some(28000)), iter.size_hint()); + iter.by_ref().take(2000).for_each(drop); + assert_eq!((26000, Some(26000)), iter.size_hint()); + iter.by_ref().take(5000).for_each(drop); + assert_eq!((21000, Some(21000)), iter.size_hint()); + iter.by_ref().take(20000).for_each(drop); + assert_eq!((1000, Some(1000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn runs() { + let mut bitmap = + RoaringBitmap::from_iter((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_001_000)); + bitmap.optimize(); + let mut iter = bitmap.iter(); + assert_eq!((5000, Some(5000)), iter.size_hint()); + iter.by_ref().take(3000).for_each(drop); + assert_eq!((2000, Some(2000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} diff --git a/vendor/roaring/tests/symmetric_difference_with.rs b/vendor/roaring/tests/symmetric_difference_with.rs new file mode 100644 index 0000000..d9c2bf5 --- /dev/null +++ b/vendor/roaring/tests/symmetric_difference_with.rs @@ -0,0 +1,124 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (0..1000).chain(2000..3000).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn no_symmetric_difference() { + let mut bitmap1 = (0..2).collect::(); + let bitmap2 = (0..2).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, RoaringBitmap::new()); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (0..1000).chain(2000..8000).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (0..6000).chain(12000..18000).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (2000..7000).collect::(); + let bitmap3 = (0..2000).chain(6000..7000).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (11000..14000).collect::(); + let bitmap3 = (0..11000).chain(12000..14000).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..7000).collect::(); + let bitmap3 = (0..3000).chain(6000..7000).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = (0..2000) + .chain(1_000_000..1_002_000) + .chain(3_000_000..3_001_000) + .collect::(); + let bitmap2 = (1000..3000) + .chain(1_001_000..1_003_000) + .chain(2_000_000..2_000_001) + .collect::(); + let bitmap3 = (0..1000) + .chain(1_000_000..1_001_000) + .chain(2000..3000) + .chain(1_002_000..1_003_000) + .chain(2_000_000..2_000_001) + .chain(3_000_000..3_001_000) + .collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = (0..6000) + .chain(1_000_000..1_012_000) + .chain(3_000_000..3_010_000) + .collect::(); + let bitmap2 = (3000..7000) + .chain(1_006_000..1_018_000) + .chain(2_000_000..2_010_000) + .collect::(); + let bitmap3 = (0..3000) + .chain(1_000_000..1_006_000) + .chain(6000..7000) + .chain(1_012_000..1_018_000) + .chain(2_000_000..2_010_000) + .chain(3_000_000..3_010_000) + .collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/treemap_clone.rs b/vendor/roaring/tests/treemap_clone.rs new file mode 100644 index 0000000..ddeb849 --- /dev/null +++ b/vendor/roaring/tests/treemap_clone.rs @@ -0,0 +1,40 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +#[allow(clippy::redundant_clone)] +fn array() { + let original = (0..2000).collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn bitmap() { + let original = (0..6000).collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn arrays() { + let original = ((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_001_000)) + .collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} + +#[test] +#[allow(clippy::redundant_clone)] +fn bitmaps() { + let original = ((0..6000).chain(1_000_000..1_012_000).chain(2_000_000..2_010_000)) + .collect::(); + let clone = original.clone(); + + assert_eq!(clone, original); +} diff --git a/vendor/roaring/tests/treemap_difference_with.rs b/vendor/roaring/tests/treemap_difference_with.rs new file mode 100644 index 0000000..91d4cd3 --- /dev/null +++ b/vendor/roaring/tests/treemap_difference_with.rs @@ -0,0 +1,117 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (0..1000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn no_difference() { + let mut bitmap1 = (1..3).collect::(); + let bitmap2 = (1..3).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, RoaringTreemap::new()); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (0..1000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (0..6000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..9000).collect::(); + let bitmap3 = (0..3000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (9000..12000).collect::(); + let bitmap3 = (0..9000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..6000).collect::(); + let bitmap3 = (0..3000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = ((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_001_000)) + .collect::(); + let bitmap2 = ((1000..3000).chain(1_001_000..1_003_000).chain(2_000_000..2_001_000)) + .collect::(); + let bitmap3 = ((0..1000).chain(1_000_000..1_001_000)).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays_removing_one_whole_container() { + let mut bitmap1 = ((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_001_000)) + .collect::(); + let bitmap2 = ((0..3000).chain(1_001_000..1_003_000).chain(2_000_000..2_001_000)) + .collect::(); + let bitmap3 = (1_000_000..1_001_000).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = ((0..6000).chain(1_000_000..1_012_000).chain(2_000_000..2_010_000)) + .collect::(); + let bitmap2 = ((3000..9000).chain(1_006_000..1_018_000).chain(2_000_000..2_010_000)) + .collect::(); + let bitmap3 = ((0..3000).chain(1_000_000..1_006_000)).collect::(); + + bitmap1 -= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/treemap_intersect_with.rs b/vendor/roaring/tests/treemap_intersect_with.rs new file mode 100644 index 0000000..a794a6c --- /dev/null +++ b/vendor/roaring/tests/treemap_intersect_with.rs @@ -0,0 +1,93 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (1000..2000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn no_intersection() { + let mut bitmap1 = (0..2).collect::(); + let bitmap2 = (3..4).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, RoaringTreemap::new()); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (1000..2000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (6000..12000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..9000).collect::(); + let bitmap3 = (3000..6000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (7000..9000).collect::(); + let bitmap3 = (7000..9000).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = ((0..2000).chain(1_000_000..1_002_000).chain(3_000_000..3_001_000)) + .collect::(); + let bitmap2 = ((1000..3000).chain(1_001_000..1_003_000).chain(2_000_000..2_001_000)) + .collect::(); + let bitmap3 = ((1000..2000).chain(1_001_000..1_002_000)).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = ((0..6000).chain(1_000_000..1_012_000).chain(3_000_000..3_010_000)) + .collect::(); + let bitmap2 = ((3000..9000).chain(1_006_000..1_018_000).chain(2_000_000..2_010_000)) + .collect::(); + let bitmap3 = ((3000..6000).chain(1_006_000..1_012_000)).collect::(); + + bitmap1 &= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/treemap_is_disjoint.rs b/vendor/roaring/tests/treemap_is_disjoint.rs new file mode 100644 index 0000000..0680bf2 --- /dev/null +++ b/vendor/roaring/tests/treemap_is_disjoint.rs @@ -0,0 +1,62 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array() { + let bitmap1 = (0..2000).collect::(); + let bitmap2 = (4000..6000).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn array_not() { + let bitmap1 = (0..4000).collect::(); + let bitmap2 = (2000..6000).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmap() { + let bitmap1 = (0..6000).collect::(); + let bitmap2 = (10000..16000).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmap_not() { + let bitmap1 = (0..10000).collect::(); + let bitmap2 = (5000..15000).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn arrays() { + let bitmap1 = ((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_002_000)) + .collect::(); + let bitmap2 = ((100_000..102_000).chain(1_100_000..1_102_000)).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn arrays_not() { + let bitmap1 = ((0..2_000).chain(1_000_000..1_002_000).chain(2_000_000..2_002_000)) + .collect::(); + let bitmap2 = ((100_000..102_000).chain(1_001_000..1_003_000)).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmaps() { + let bitmap1 = ((0..6000).chain(1_000_000..1_006_000).chain(2_000_000..2_006_000)) + .collect::(); + let bitmap2 = ((100_000..106_000).chain(1_100_000..1_106_000)).collect::(); + assert!(bitmap1.is_disjoint(&bitmap2)); +} + +#[test] +fn bitmaps_not() { + let bitmap1 = ((0..6000).chain(1_000_000..1_006_000).chain(2_000_000..2_006_000)) + .collect::(); + let bitmap2 = ((100_000..106_000).chain(1_004_000..1_008_000)).collect::(); + assert!(!bitmap1.is_disjoint(&bitmap2)); +} diff --git a/vendor/roaring/tests/treemap_is_subset.rs b/vendor/roaring/tests/treemap_is_subset.rs new file mode 100644 index 0000000..5abb784 --- /dev/null +++ b/vendor/roaring/tests/treemap_is_subset.rs @@ -0,0 +1,80 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array_not() { + let sup = (0..2000).collect::(); + let sub = (1000..3000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn array() { + let sup = (0..4000).collect::(); + let sub = (2000..3000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn array_bitmap_not() { + let sup = (0..2000).collect::(); + let sub = (1000..15000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmap_not() { + let sup = (0..6000).collect::(); + let sub = (4000..10000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmap() { + let sup = (0..20000).collect::(); + let sub = (5000..15000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn bitmap_array_not() { + let sup = (0..20000).collect::(); + let sub = (19000..21000).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmap_array() { + let sup = (0..20000).collect::(); + let sub = (18000..20000).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn arrays_not() { + let sup = ((0..2000).chain(1_000_000..1_002_000)).collect::(); + let sub = ((100_000..102_000).chain(1_100_000..1_102_000)).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn arrays() { + let sup = ((0..3000).chain(100_000..103_000)).collect::(); + let sub = ((0..2000).chain(100_000..102_000)).collect::(); + assert!(sub.is_subset(&sup)); +} + +#[test] +fn bitmaps_not() { + let sup = ((0..6000).chain(1_000_000..1_006_000).chain(2_000_000..2_010_000)) + .collect::(); + let sub = ((100_000..106_000).chain(1_100_000..1_106_000)).collect::(); + assert!(!sub.is_subset(&sup)); +} + +#[test] +fn bitmaps() { + let sup = ((0..1_000_000).chain(2_000_000..2_010_000)).collect::(); + let sub = ((0..10_000).chain(500_000..510_000)).collect::(); + assert!(sub.is_subset(&sup)); +} diff --git a/vendor/roaring/tests/treemap_iter.rs b/vendor/roaring/tests/treemap_iter.rs new file mode 100644 index 0000000..be5b9a6 --- /dev/null +++ b/vendor/roaring/tests/treemap_iter.rs @@ -0,0 +1,142 @@ +extern crate roaring; +mod iter; +use roaring::RoaringTreemap; + +use iter::outside_in; +use proptest::arbitrary::any; +use proptest::collection::btree_set; +use proptest::proptest; + +#[test] +fn range() { + let original = (0..2000).collect::(); + let clone = RoaringTreemap::from_iter(&original); + let clone2 = RoaringTreemap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn array() { + let original = (0..5).collect::(); + let clone = RoaringTreemap::from([0, 1, 2, 3, 4]); + + assert_eq!(clone, original); +} + +#[test] +fn bitmap() { + let original = (0..6000).collect::(); + let clone = RoaringTreemap::from_iter(&original); + let clone2 = RoaringTreemap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn arrays() { + let original = ((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_001_000)) + .collect::(); + let clone = RoaringTreemap::from_iter(&original); + let clone2 = RoaringTreemap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn bitmaps() { + let original = ((0..6000).chain(1_000_000..1_012_000).chain(2_000_000..2_010_000)) + .collect::(); + let clone = RoaringTreemap::from_iter(&original); + let clone2 = RoaringTreemap::from_iter(original.clone()); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +#[test] +fn bitmaps_iterator() { + let original = ((0..6000).chain(1_000_000..1_012_000).chain(2_000_000..2_010_000)) + .collect::(); + let clone = RoaringTreemap::from_bitmaps(original.bitmaps().map(|(p, b)| (p, b.clone()))); + let clone2 = original.bitmaps().map(|(p, b)| (p, b.clone())).collect::(); + + assert_eq!(clone, original); + assert_eq!(clone2, original); +} + +proptest! { + #[test] + fn iter(values in btree_set(any::(), ..=10_000)) { + let bitmap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap(); + + assert!(values.into_iter().eq(bitmap)); + } +} + +proptest! { + #[test] + fn fold(values in btree_set(any::(), ..=10_000)) { + let bitmap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap(); + let mut val_iter = values.into_iter(); + // `Iterator::all` uses currently unimplementable `try_fold`, we test `fold` + #[allow(clippy::unnecessary_fold)] + let r = bitmap.into_iter().fold(true, |b, i| { + b && i == val_iter.next().unwrap() + }); + assert!(r) + } +} + +#[test] +fn rev() { + let values = (1..3) + .chain(1_000_000..1_012_003) + .chain(2_000_001..2_000_003) + .chain(2_000_000_000_001..2_000_000_000_003); + let bitmap = RoaringTreemap::from_iter(values.clone()); + + assert!(values.into_iter().rev().eq(bitmap.iter().rev())); +} + +proptest! { + #[test] + fn rev_iter(values in btree_set(any::(), ..=10_000)) { + let bitmap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap(); + + assert!(values.into_iter().rev().eq(bitmap.iter().rev())); + } +} + +#[test] +fn from_iter() { + // This test verifies that the public API allows conversion from iterators + // with u64 as well as &u64 elements. + let vals = vec![1, 5, 1_000_000_000_000_000]; + let a = RoaringTreemap::from_iter(vals.iter()); + let b = RoaringTreemap::from_iter(vals); + assert_eq!(a, b); +} + +#[test] +fn interleaved() { + let values = (1..3) + .chain(1_000_000..1_012_003) + .chain(2_000_001..2_000_003) + .chain(2_000_000_000_001..2_000_000_000_003); + let bitmap = RoaringTreemap::from_iter(values.clone()); + + assert!(outside_in(values).eq(outside_in(bitmap))); +} + +proptest! { + #[test] + fn interleaved_iter(values in btree_set(any::(), 50_000..=100_000)) { + let bitmap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap(); + + assert!(outside_in(values).eq(outside_in(bitmap))); + } +} diff --git a/vendor/roaring/tests/treemap_iter_advance_to.rs b/vendor/roaring/tests/treemap_iter_advance_to.rs new file mode 100644 index 0000000..bead176 --- /dev/null +++ b/vendor/roaring/tests/treemap_iter_advance_to.rs @@ -0,0 +1,257 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn iter_basic() { + let bm = RoaringTreemap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.iter(); + i.advance_to(10); + for n in 11..=14 { + assert_eq!(i.next(), Some(n)) + } + assert_eq!(i.next(), None); +} + +#[test] +fn to_missing_container() { + let bm = RoaringTreemap::from([1, 0x2_0001, 0x2_0002]); + let mut i = bm.iter(); + i.advance_to(0x1_0000); + assert_eq!(i.next(), Some(0x2_0001)); + assert_eq!(i.next(), Some(0x2_0002)); + assert_eq!(i.next(), None); +} + +#[test] +fn to_next_bitmap() { + let bm = + RoaringTreemap::from([1u64, 0x2_0001u64 + u32::MAX as u64, 0x2_0002u64 + u32::MAX as u64]); + let mut i = bm.iter(); + i.advance_to(0x1_0000); + assert_eq!(i.next(), Some(0x2_0001u64 + u32::MAX as u64)); + assert_eq!(i.next(), Some(0x2_0002u64 + u32::MAX as u64)); + assert_eq!(i.next(), None); +} + +#[test] +fn iter_back_basic() { + let bm = RoaringTreemap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.iter(); + i.advance_back_to(10); + assert_eq!(i.next(), Some(1)); + assert_eq!(i.next(), Some(2)); + assert_eq!(i.next_back(), Some(4)); + assert_eq!(i.next_back(), Some(3)); + + assert_eq!(i.next(), None); + assert_eq!(i.next_back(), None); +} + +#[test] +fn iter_advance_past_end() { + let bm = RoaringTreemap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.iter(); + i.advance_to(15); + assert_eq!(i.next(), None); + assert_eq!(i.size_hint(), (0, Some(0))); +} + +#[test] +fn iter_multi_container() { + let bm = RoaringTreemap::from([1, 2, 3, 100000, 100001]); + let mut i = bm.iter(); + i.advance_to(3); + assert_eq!(i.size_hint(), (3, Some(3))); + assert_eq!(i.next(), Some(3)); + assert_eq!(i.size_hint(), (2, Some(2))); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.size_hint(), (1, Some(1))); + assert_eq!(i.next(), Some(100001)); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None); + assert_eq!(i.size_hint(), (0, Some(0))); +} + +#[test] +fn iter_multi_container_multi_bitmap() { + let bm = RoaringTreemap::from([ + 1, + 2, + 3, + 100000, + 100001, + 1u64 + u32::MAX as u64, + 2u64 + u32::MAX as u64, + 3u64 + u32::MAX as u64, + 100000u64 + u32::MAX as u64, + 100001u64 + u32::MAX as u64, + ]); + let mut i = bm.iter(); + i.advance_to(3); + assert_eq!(i.size_hint(), (8, Some(8))); + assert_eq!(i.next(), Some(3)); + assert_eq!(i.size_hint(), (7, Some(7))); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.size_hint(), (6, Some(6))); + assert_eq!(i.next(), Some(100001)); + assert_eq!(i.size_hint(), (5, Some(5))); + assert_eq!(i.next(), Some(1u64 + u32::MAX as u64)); + assert_eq!(i.size_hint(), (4, Some(4))); + assert_eq!(i.next(), Some(2u64 + u32::MAX as u64)); + assert_eq!(i.size_hint(), (3, Some(3))); + assert_eq!(i.next(), Some(3u64 + u32::MAX as u64)); + assert_eq!(i.size_hint(), (2, Some(2))); + assert_eq!(i.next(), Some(100000u64 + u32::MAX as u64)); + assert_eq!(i.size_hint(), (1, Some(1))); + assert_eq!(i.next(), Some(100001u64 + u32::MAX as u64)); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None); + assert_eq!(i.size_hint(), (0, Some(0))); +} + +#[test] +fn iter_empty() { + let bm = RoaringTreemap::new(); + let mut i = bm.iter(); + i.advance_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +} + +#[test] +fn iter_back_empty() { + let bm = RoaringTreemap::new(); + let mut i = bm.iter(); + i.advance_back_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +} + +/*#[test] +fn into_iter_basic() { + let bm = RoaringTreemap::from([1, 2, 3, 4, 11, 12, 13, 14]); + let mut i = bm.into_iter(); + i.advance_to(10); + let mut expected_size_hint = 4; + assert_eq!(i.size_hint(), (expected_size_hint, Some(expected_size_hint))); + for n in 11..=14 { + assert_eq!(i.next(), Some(n)); + expected_size_hint -= 1; + assert_eq!(i.size_hint(), (expected_size_hint, Some(expected_size_hint))); + } + assert_eq!(i.next(), None); +}*/ + +/*#[test] +fn into_iter_multi_container() { + let bm = RoaringTreemap::from([1, 2, 3, 100000, 100001]); + let mut i = bm.into_iter(); + i.advance_to(3); + assert_eq!(i.size_hint(), (3, Some(3))); + assert_eq!(i.next(), Some(3)); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.next(), Some(100001)); + assert_eq!(i.next(), None); +}*/ + +/*#[test] +fn into_iter_empty() { + let bm = RoaringTreemap::new(); + let mut i = bm.into_iter(); + i.advance_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +}*/ + +/*#[test] +fn into_iter_back_empty() { + let bm = RoaringTreemap::new(); + let mut i = bm.into_iter(); + i.advance_back_to(31337); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None) +}*/ + +#[test] +fn advance_to_with_tail_iter() { + let bm = RoaringTreemap::from([1, 2, 3, 100000, 100001]); + let mut i = bm.iter(); + i.next_back(); + i.advance_to(100000); + assert_eq!(i.size_hint(), (1, Some(1))); + assert_eq!(i.next(), Some(100000)); + assert_eq!(i.size_hint(), (0, Some(0))); + assert_eq!(i.next(), None); +} + +#[test] +fn advance_to_end() { + let bitmap = RoaringTreemap::from([u64::MAX]); + let mut iter = bitmap.iter(); + iter.advance_to(u64::MAX); + assert_eq!(Some(u64::MAX), iter.next()); + assert_eq!(None, iter.next()); +} + +#[test] +fn advance_bitset() { + let mut bitmap = RoaringTreemap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_to(0x1_0000 - 4); + // 0x1_0000 + 5 is not in the bitmap, so the next value will be the first value less than that + iter.advance_back_to(0x1_0000 + 5); + assert_eq!(iter.next(), Some(0x1_0000 - 4)); + assert_eq!(iter.next_back(), Some(0x1_0000 + 4)); + + assert_eq!(iter.next(), Some(0x1_0000 - 2)); + assert_eq!(iter.next(), Some(0x1_0000)); + assert_eq!(iter.next(), Some(0x1_0000 + 2)); + assert_eq!(iter.next(), None); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn advance_bitset_current_word() { + let mut bitmap = RoaringTreemap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_to(4); + iter.advance_back_to(0x2_0000 - 4); + for i in (4..=(0x2_0000 - 4)).step_by(2) { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_bitset_to_end_word() { + let mut bitmap = RoaringTreemap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_to(0x1_0000 - 4); + for i in ((0x1_0000 - 4)..=0x2_0000).step_by(2) { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); +} + +#[test] +fn advance_bitset_back_to_start_word() { + let mut bitmap = RoaringTreemap::new(); + for i in (0..=0x2_0000).step_by(2) { + bitmap.insert(i); + } + let mut iter = bitmap.iter(); + iter.advance_back_to(0x1_0000 - 4); + for i in (0..=(0x1_0000 - 4)).step_by(2) { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); +} diff --git a/vendor/roaring/tests/treemap_lib.rs b/vendor/roaring/tests/treemap_lib.rs new file mode 100644 index 0000000..0c302af --- /dev/null +++ b/vendor/roaring/tests/treemap_lib.rs @@ -0,0 +1,119 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn smoke() { + let mut bitmap = RoaringTreemap::new(); + assert_eq!(bitmap.len(), 0); + assert!(bitmap.is_empty()); + bitmap.remove(0); + assert_eq!(bitmap.len(), 0); + assert!(bitmap.is_empty()); + bitmap.insert(1); + assert!(bitmap.contains(1)); + assert_eq!(bitmap.len(), 1); + assert!(!bitmap.is_empty()); + bitmap.insert(u64::MAX - 2); + assert!(bitmap.contains(u64::MAX - 2)); + assert_eq!(bitmap.len(), 2); + bitmap.insert(u64::MAX); + assert!(bitmap.contains(u64::MAX)); + assert_eq!(bitmap.len(), 3); + bitmap.insert(2); + assert!(bitmap.contains(2)); + assert_eq!(bitmap.len(), 4); + bitmap.remove(2); + assert!(!bitmap.contains(2)); + assert_eq!(bitmap.len(), 3); + assert!(!bitmap.contains(0)); + assert!(bitmap.contains(1)); + assert!(!bitmap.contains(100)); + assert!(bitmap.contains(u64::MAX - 2)); + assert!(!bitmap.contains(u64::MAX - 1)); + assert!(bitmap.contains(u64::MAX)); +} + +#[test] +fn insert_range() { + let ranges = 0..0x1000; + const SIGMA: u64 = u32::MAX as u64; + + let mut bitmap = RoaringTreemap::new(); + assert_eq!(bitmap.insert_range(ranges), 0x1000); + assert_eq!(bitmap.len(), 0x1000); + assert_eq!(bitmap.max(), Some(0xFFF)); + + assert_eq!(bitmap.insert_range(u32::MAX as u64 - 1..u32::MAX as u64 + 1), 2); + assert!(bitmap.contains(2)); + assert!(bitmap.contains(0xFFF)); + assert!(!bitmap.contains(0x1000)); + + bitmap.clear(); + bitmap.insert_range(2 * SIGMA..=4 * SIGMA); + + assert_eq!(bitmap.min(), Some(2 * SIGMA)); + assert_eq!(bitmap.max(), Some(4 * SIGMA)); + + assert!(bitmap.contains(3 * SIGMA)); +} + +#[test] +fn remove_range() { + let ranges = [0u64, 1, 63, 64, 65, 100, 4096 - 1, 4096, 4096 + 1, 65536 - 1]; + for (i, &a) in ranges.iter().enumerate() { + for &b in &ranges[i..] { + let mut bitmap = (0..=65536).collect::(); + assert_eq!(bitmap.remove_range(a..b), (b - a)); + assert_eq!(bitmap, ((0..a).chain(b..=65536)).collect::()); + } + } +} + +#[test] +fn test_max() { + let mut bitmap = RoaringTreemap::new(); + assert_eq!(bitmap.max(), None); + bitmap.insert(0); + assert_eq!(bitmap.max(), Some(0)); + bitmap.insert(1); + assert_eq!(bitmap.max(), Some(1)); + bitmap.insert(u64::MAX); + assert_eq!(bitmap.max(), Some(u64::MAX)); +} + +#[test] +fn test_min() { + let mut bitmap = RoaringTreemap::new(); + assert_eq!(bitmap.min(), None); + bitmap.insert(u64::MAX); + assert_eq!(bitmap.min(), Some(u64::MAX)); + bitmap.insert(1); + assert_eq!(bitmap.min(), Some(1)); + bitmap.insert(0); + assert_eq!(bitmap.min(), Some(0)); +} + +#[test] +fn to_bitmap() { + let bitmap = (0..5000).collect::(); + assert_eq!(bitmap.len(), 5000); + for i in 1..5000 { + assert!(bitmap.contains(i)); + } + assert!(!bitmap.contains(5001)); +} + +#[test] +fn to_array() { + let mut bitmap = (0..5000).collect::(); + for i in 3000..5000 { + bitmap.remove(i); + } + assert_eq!(bitmap.len(), 3000); + for i in 0..3000 { + assert!(bitmap.contains(i)); + } + for i in 3000..5000 { + assert!(!bitmap.contains(i)); + } +} diff --git a/vendor/roaring/tests/treemap_ops.rs b/vendor/roaring/tests/treemap_ops.rs new file mode 100644 index 0000000..39375ee --- /dev/null +++ b/vendor/roaring/tests/treemap_ops.rs @@ -0,0 +1,78 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn or() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = (1..6).collect::(); + + assert_eq!(rb3, &rb1 | &rb2); + assert_eq!(rb3, &rb1 | rb2.clone()); + assert_eq!(rb3, rb1.clone() | &rb2); + assert_eq!(rb3, rb1.clone() | rb2.clone()); + assert_eq!(rb3.len(), rb1.union_len(&rb2)); + + rb1 |= &rb2; + rb1 |= rb2; + + assert_eq!(rb3, rb1); +} + +#[test] +fn and() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = (3..4).collect::(); + + assert_eq!(rb3, &rb1 & &rb2); + assert_eq!(rb3, &rb1 & rb2.clone()); + assert_eq!(rb3, rb1.clone() & &rb2); + assert_eq!(rb3, rb1.clone() & rb2.clone()); + assert_eq!(rb3.len(), rb1.intersection_len(&rb2)); + + rb1 &= &rb2; + rb1 &= rb2; + + assert_eq!(rb3, rb1); +} + +#[test] +fn sub() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = (1..3).collect::(); + + assert_eq!(rb3, &rb1 - &rb2); + assert_eq!(rb3, &rb1 - rb2.clone()); + assert_eq!(rb3, rb1.clone() - &rb2); + assert_eq!(rb3, rb1.clone() - rb2.clone()); + assert_eq!(rb3.len(), rb1.difference_len(&rb2)); + + rb1 -= &rb2; + rb1 -= rb2; + + assert_eq!(rb3, rb1); +} + +#[test] +fn xor() { + let mut rb1 = (1..4).collect::(); + let rb2 = (3..6).collect::(); + let rb3 = ((1..3).chain(4..6)).collect::(); + let rb4 = (0..0).collect::(); + + assert_eq!(rb3, &rb1 ^ &rb2); + assert_eq!(rb3, &rb1 ^ rb2.clone()); + assert_eq!(rb3, rb1.clone() ^ &rb2); + assert_eq!(rb3, rb1.clone() ^ rb2.clone()); + assert_eq!(rb3.len(), rb1.symmetric_difference_len(&rb2)); + + rb1 ^= &rb2; + + assert_eq!(rb3, rb1); + + rb1 ^= rb3; + + assert_eq!(rb4, rb1); +} diff --git a/vendor/roaring/tests/treemap_rank.rs b/vendor/roaring/tests/treemap_rank.rs new file mode 100644 index 0000000..e9c7421 --- /dev/null +++ b/vendor/roaring/tests/treemap_rank.rs @@ -0,0 +1,54 @@ +extern crate roaring; + +use core::ops::RangeInclusive; +use proptest::collection::{btree_set, vec}; +use proptest::prelude::*; +use roaring::RoaringTreemap; + +const BITMAP_MAX: u64 = u32::MAX as u64; + +#[test] +fn rank_roaring_bitmaps() { + // A treemap with two roaring bitmaps. + // The lower one contains one array container with the highest 1000 values + // The higher one contains one bitmap at with the lowest 5000 values + let treemap = RoaringTreemap::from_sorted_iter(BITMAP_MAX - 1000..BITMAP_MAX + 5000).unwrap(); + + // start of treemap + assert_eq!(treemap.rank(0), 0); + + // low boundary + assert_eq!(treemap.rank(BITMAP_MAX - 1002), 0); + assert_eq!(treemap.rank(BITMAP_MAX - 1001), 0); + assert_eq!(treemap.rank(BITMAP_MAX - 1000), 1); + + // middle range (spans two roaring bitmaps) + assert_eq!(treemap.rank(BITMAP_MAX - 1), 1000); + assert_eq!(treemap.rank(BITMAP_MAX), 1001); + assert_eq!(treemap.rank(BITMAP_MAX + 1), 1002); + + // high boundary + assert_eq!(treemap.rank(BITMAP_MAX + 4998), 5999); + assert_eq!(treemap.rank(BITMAP_MAX + 4999), 6000); + assert_eq!(treemap.rank(BITMAP_MAX + 5000), 6000); + + // end of treemap + assert_eq!(treemap.rank(u64::MAX), 6000); +} + +// A range that spans 2 roaring bitmaps with 2 containers each +const PROP_RANGE: RangeInclusive = BITMAP_MAX - (1 << 17)..=BITMAP_MAX + (1 << 17); + +proptest! { + #[test] + fn proptest_rank( + values in btree_set(PROP_RANGE, ..=1000), + checks in vec(PROP_RANGE, ..=100) + ){ + let treemap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap(); + for i in checks { + let expected = values.iter().take_while(|&&x| x <= i).count() as u64; + assert_eq!(treemap.rank(i), expected); + } + } +} diff --git a/vendor/roaring/tests/treemap_select.rs b/vendor/roaring/tests/treemap_select.rs new file mode 100644 index 0000000..a568cef --- /dev/null +++ b/vendor/roaring/tests/treemap_select.rs @@ -0,0 +1,44 @@ +extern crate roaring; + +use proptest::collection::btree_set; +use proptest::prelude::*; +use roaring::RoaringTreemap; + +#[test] +fn select() { + let bitmap = (0..2000).collect::(); + + assert_eq!(bitmap.select(0), Some(0)); +} + +#[test] +fn select_multiple_bitmap() { + let mut bitmap = (0..100_000).collect::(); + bitmap.append(u32::MAX as u64..u32::MAX as u64 + 100_000).expect("sorted integers"); + + assert_eq!(bitmap.select(0), Some(0)); + assert_eq!(bitmap.select(99_999), Some(99_999)); + assert_eq!(bitmap.select(100_000), Some(u32::MAX as u64)); + assert_eq!(bitmap.select(199_999), Some(u32::MAX as u64 + 99_999)); + assert_eq!(bitmap.select(200_000), None); + assert_eq!(bitmap.select(u64::MAX), None); +} + +#[test] +fn select_empty() { + let bitmap = RoaringTreemap::new(); + + assert_eq!(bitmap.select(0), None); + assert_eq!(bitmap.select(1024), None); + assert_eq!(bitmap.select(u64::MAX), None); +} + +proptest! { + #[test] + fn proptest_select(values in btree_set(any::(), 1000)) { + let bitmap = RoaringTreemap::from_sorted_iter(values.iter().cloned()).unwrap(); + for (i, value) in values.iter().cloned().enumerate() { + prop_assert_eq!(bitmap.select(i as u64), Some(value)); + } + } +} diff --git a/vendor/roaring/tests/treemap_serialization.rs b/vendor/roaring/tests/treemap_serialization.rs new file mode 100644 index 0000000..2a15ed6 --- /dev/null +++ b/vendor/roaring/tests/treemap_serialization.rs @@ -0,0 +1,45 @@ +#![cfg(feature = "std")] + +use roaring::RoaringTreemap; + +fn serialize_deserialize(dataset: Dataset) +where + Dataset: IntoIterator, + I: Iterator, +{ + let rb = RoaringTreemap::from_iter(dataset); + + let mut buffer = vec![]; + rb.serialize_into(&mut buffer).unwrap(); + + assert_eq!(buffer.len(), rb.serialized_size()); + + let new_rb = RoaringTreemap::deserialize_from(&buffer[..]).unwrap(); + + assert_eq!(rb, new_rb); +} + +#[test] +fn empty() { + serialize_deserialize(vec![]) +} + +#[test] +fn basic() { + serialize_deserialize(vec![1, 2, 3, 4, 5, 100, 1000]) +} + +#[test] +fn basic_2() { + serialize_deserialize(vec![1, 2, 3, 4, 5, 100, 1000, 10000, 100000, 1000000]) +} + +#[test] +fn basic_3() { + let u32max = u32::MAX as u64; + serialize_deserialize( + vec![1, 2, 3, 4, 5, 100, 1000, 10000, 100000, 1000000, u32max + 10, u32max << 10] + .into_iter() + .chain(u32max..(u32max + 2 * (1 << 16))), + ) +} diff --git a/vendor/roaring/tests/treemap_size_hint.rs b/vendor/roaring/tests/treemap_size_hint.rs new file mode 100644 index 0000000..186464d --- /dev/null +++ b/vendor/roaring/tests/treemap_size_hint.rs @@ -0,0 +1,52 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array() { + let bitmap = (0..2000).collect::(); + let mut iter = bitmap.iter(); + assert_eq!((2000, Some(2000)), iter.size_hint()); + iter.by_ref().take(1000).for_each(drop); + assert_eq!((1000, Some(1000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn bitmap() { + let bitmap = (0..6000).collect::(); + let mut iter = bitmap.iter(); + assert_eq!((6000, Some(6000)), iter.size_hint()); + iter.by_ref().take(3000).for_each(drop); + assert_eq!((3000, Some(3000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn arrays() { + let bitmap = ((0..2000).chain(1_000_000..1_002_000).chain(2_000_000..2_001_000)) + .collect::(); + let mut iter = bitmap.iter(); + assert_eq!((5000, Some(5000)), iter.size_hint()); + iter.by_ref().take(3000).for_each(drop); + assert_eq!((2000, Some(2000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} + +#[test] +fn bitmaps() { + let bitmap = ((0..6000).chain(1_000_000..1_012_000).chain(2_000_000..2_010_000)) + .collect::(); + let mut iter = bitmap.iter(); + assert_eq!((28000, Some(28000)), iter.size_hint()); + iter.by_ref().take(2000).for_each(drop); + assert_eq!((26000, Some(26000)), iter.size_hint()); + iter.by_ref().take(5000).for_each(drop); + assert_eq!((21000, Some(21000)), iter.size_hint()); + iter.by_ref().take(20000).for_each(drop); + assert_eq!((1000, Some(1000)), iter.size_hint()); + iter.by_ref().for_each(drop); + assert_eq!((0, Some(0)), iter.size_hint()); +} diff --git a/vendor/roaring/tests/treemap_symmetric_difference_with.rs b/vendor/roaring/tests/treemap_symmetric_difference_with.rs new file mode 100644 index 0000000..2dba2bf --- /dev/null +++ b/vendor/roaring/tests/treemap_symmetric_difference_with.rs @@ -0,0 +1,116 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = ((0..1000).chain(2000..3000)).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn no_symmetric_difference() { + let mut bitmap1 = (0..2).collect::(); + let bitmap2 = (0..2).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, RoaringTreemap::new()); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = ((0..1000).chain(2000..8000)).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = ((0..6000).chain(12000..18000)).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (2000..7000).collect::(); + let bitmap3 = ((0..2000).chain(6000..7000)).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (11000..14000).collect::(); + let bitmap3 = ((0..11000).chain(12000..14000)).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array_to_array() { + let mut bitmap1 = (0..6000).collect::(); + let bitmap2 = (3000..7000).collect::(); + let bitmap3 = ((0..3000).chain(6000..7000)).collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = ((0..2000).chain(1_000_000..1_002_000).chain(3_000_000..3_001_000)) + .collect::(); + let bitmap2 = ((1000..3000).chain(1_001_000..1_003_000).chain(2_000_000..2_000_001)) + .collect::(); + let bitmap3 = ((0..1000) + .chain(1_000_000..1_001_000) + .chain(2000..3000) + .chain(1_002_000..1_003_000) + .chain(2_000_000..2_000_001) + .chain(3_000_000..3_001_000)) + .collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = ((0..6000).chain(1_000_000..1_012_000).chain(3_000_000..3_010_000)) + .collect::(); + let bitmap2 = ((3000..7000).chain(1_006_000..1_018_000).chain(2_000_000..2_010_000)) + .collect::(); + let bitmap3 = ((0..3000) + .chain(1_000_000..1_006_000) + .chain(6000..7000) + .chain(1_012_000..1_018_000) + .chain(2_000_000..2_010_000) + .chain(3_000_000..3_010_000)) + .collect::(); + + bitmap1 ^= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/treemap_union_with.rs b/vendor/roaring/tests/treemap_union_with.rs new file mode 100644 index 0000000..e370b6a --- /dev/null +++ b/vendor/roaring/tests/treemap_union_with.rs @@ -0,0 +1,91 @@ +extern crate roaring; +use roaring::RoaringTreemap; + +#[test] +fn array_to_array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (0..3000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn array_to_bitmap() { + let mut bitmap1 = (0..4000).collect::(); + let bitmap2 = (4000..8000).collect::(); + let bitmap3 = (0..8000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (0..8000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (0..18000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (10000..13000).collect::(); + let bitmap3 = (0..13000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = ((0..2000).chain(1_000_000..1_002_000).chain(3_000_000..3_001_000)) + .collect::(); + let bitmap2 = ((1000..3000).chain(1_001_000..1_003_000).chain(2_000_000..2_001_000)) + .collect::(); + let bitmap3 = ((0..3000) + .chain(1_000_000..1_003_000) + .chain(2_000_000..2_001_000) + .chain(3_000_000..3_001_000)) + .collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = ((0..6000).chain(1_000_000..1_012_000).chain(3_000_000..3_010_000)) + .collect::(); + let bitmap2 = ((3000..9000).chain(1_006_000..1_018_000).chain(2_000_000..2_010_000)) + .collect::(); + let bitmap3 = ((0..9000) + .chain(1_000_000..1_018_000) + .chain(2_000_000..2_010_000) + .chain(3_000_000..3_010_000)) + .collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} diff --git a/vendor/roaring/tests/union_with.rs b/vendor/roaring/tests/union_with.rs new file mode 100644 index 0000000..765b829 --- /dev/null +++ b/vendor/roaring/tests/union_with.rs @@ -0,0 +1,99 @@ +extern crate roaring; +use roaring::RoaringBitmap; + +#[test] +fn array_to_array() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..3000).collect::(); + let bitmap3 = (0..3000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn array_to_bitmap() { + let mut bitmap1 = (0..4000).collect::(); + let bitmap2 = (4000..8000).collect::(); + let bitmap3 = (0..8000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn array_and_bitmap() { + let mut bitmap1 = (0..2000).collect::(); + let bitmap2 = (1000..8000).collect::(); + let bitmap3 = (0..8000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (6000..18000).collect::(); + let bitmap3 = (0..18000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmap_and_array() { + let mut bitmap1 = (0..12000).collect::(); + let bitmap2 = (10000..13000).collect::(); + let bitmap3 = (0..13000).collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn arrays() { + let mut bitmap1 = (0..2000) + .chain(1_000_000..1_002_000) + .chain(3_000_000..3_001_000) + .collect::(); + let bitmap2 = (1000..3000) + .chain(1_001_000..1_003_000) + .chain(2_000_000..2_001_000) + .collect::(); + let bitmap3 = (0..3000) + .chain(1_000_000..1_003_000) + .chain(2_000_000..2_001_000) + .chain(3_000_000..3_001_000) + .collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +} + +#[test] +fn bitmaps() { + let mut bitmap1 = (0..6000) + .chain(1_000_000..1_012_000) + .chain(3_000_000..3_010_000) + .collect::(); + let bitmap2 = (3000..9000) + .chain(1_006_000..1_018_000) + .chain(2_000_000..2_010_000) + .collect::(); + let bitmap3 = (0..9000) + .chain(1_000_000..1_018_000) + .chain(2_000_000..2_010_000) + .chain(3_000_000..3_010_000) + .collect::(); + + bitmap1 |= bitmap2; + + assert_eq!(bitmap1, bitmap3); +}