diff --git a/.claude/.gitignore b/.claude/.gitignore new file mode 100644 index 0000000..53ced0f --- /dev/null +++ b/.claude/.gitignore @@ -0,0 +1 @@ +/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.json similarity index 73% rename from .claude/settings.local.json rename to .claude/settings.json index d0a9774..142114a 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.json @@ -4,9 +4,10 @@ "Bash(cargo test)", "Bash(cargo test:*)", "Bash(cargo clippy:*)", - "Bash(cargo fix:*)" + "Bash(cargo fix:*)", + "Bash(cargo check:*)" ], "deny": [], "ask": [] } -} \ No newline at end of file +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6656eb..c728c6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: RUSTFLAGS: -D warnings steps: - uses: actions/checkout@v3 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy @@ -55,22 +57,26 @@ jobs: RUSTFLAGS: -D warnings steps: - uses: actions/checkout@v3 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust-version }} components: rustfmt, clippy - uses: taiki-e/install-action@cargo-hack + - name: Install uv + uses: astral-sh/setup-uv@v7 - uses: Swatinem/rust-cache@v2 - name: Build run: | cargo hack build --feature-powerset - name: Test # Dev dependencies have an MSRV > 1.70. - if: ${{ matrix.rust-version.version == 'stable' }} + if: ${{ matrix.rust-version == 'stable' }} run: cargo hack test --feature-powerset - name: Test with updated Cargo.lock # Dev dependencies have an MSRV > 1.70. - if: ${{ matrix.rust-version.version == 'stable' }} + if: ${{ matrix.rust-version == 'stable' }} run: | cargo update cargo hack test --feature-powerset diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 44b1ef9..7e11cb7 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -20,6 +20,8 @@ jobs: RUSTFLAGS: -D warnings steps: - uses: actions/checkout@v3 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview @@ -27,6 +29,8 @@ jobs: - name: Install latest nextest release uses: taiki-e/install-action@nextest + - name: Install uv + uses: astral-sh/setup-uv@v7 - name: Install cargo-llvm-cov uses: taiki-e/install-action@cargo-llvm-cov - name: Update Cargo.lock diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e03fcf6..6744d7c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -12,6 +12,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - name: Update Cargo.lock run: cargo update diff --git a/.gitignore b/.gitignore index b23722f..6980cf2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ /target -# Cargo.lock is checked in to support older Rust versions +/.hegel diff --git a/Cargo.lock b/Cargo.lock index 39570a7..f7916d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "anyhow" version = "1.0.70" @@ -15,25 +30,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] -name = "bit-set" -version = "0.5.3" +name = "backtrace" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ - "bit-vec", + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", ] -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" -version = "1.3.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "buf-list" @@ -44,29 +59,16 @@ dependencies = [ "dummy-waker", "futures", "futures-io", - "proptest", - "test-strategy", + "hegeltest", "tokio", ] -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "bytes" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - [[package]] name = "cfg-if" version = "1.0.0" @@ -74,46 +76,68 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "dummy-waker" -version = "1.1.0" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea6672d73216c05740850c789368d371ca226dc8104d5f2e30c74252d5d6e5e" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] [[package]] -name = "errno" -version = "0.3.1" +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", + "ciborium-io", + "half", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "cc", - "libc", + "cfg-if", ] [[package]] -name = "fastrand" -version = "1.9.0" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "dummy-waker" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea6672d73216c05740850c789368d371ca226dc8104d5f2e30c74252d5d6e5e" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ - "instant", + "libc", + "windows-sys", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "fastrand" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "futures" @@ -171,7 +195,7 @@ checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -206,64 +230,69 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "wasi", + "r-efi", + "wasip2", ] [[package]] -name = "hermit-abi" -version = "0.3.1" +name = "gimli" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] -name = "instant" -version = "0.1.12" +name = "half" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", + "crunchy", + "zerocopy", ] [[package]] -name = "io-lifetimes" -version = "1.0.10" +name = "hegeltest" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "2a4d7a62b2b6164cd6fefa807b092598539864409d0afac49ddb20a91486768c" dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", + "ciborium", + "crc32fast", + "hegeltest-macros", + "paste", + "serde", + "tempfile", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "hegeltest-macros" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "f866f70ecaffa2176bf06643c3aaaa5a5e843caa81aa13ed336d74351de91661" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "libc" -version = "0.2.141" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" - -[[package]] -name = "libm" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "linux-raw-sys" -version = "0.3.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "memchr" @@ -272,15 +301,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] -name = "num-traits" -version = "0.2.15" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "autocfg", - "libm", + "adler2", ] +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -293,12 +342,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - [[package]] name = "proc-macro2" version = "1.0.101" @@ -308,165 +351,85 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proptest" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" -dependencies = [ - "bit-set", - "bitflags", - "byteorder", - "lazy_static", - "num-traits", - "quick-error 2.0.1", - "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 = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quote" -version = "1.0.26" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" 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" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] -name = "rand_xorshift" -version = "0.3.0" +name = "rustc-demangle" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustix" -version = "0.37.11" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] -name = "rusty-fork" -version = "0.3.0" +name = "serde" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ - "fnv", - "quick-error 1.2.3", - "tempfile", - "wait-timeout", + "serde_derive", ] [[package]] -name = "slab" -version = "0.4.7" +name = "serde_derive" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ - "autocfg", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "structmeta" -version = "0.1.6" +name = "slab" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "104842d6278bf64aa9d2f182ba4bde31e8aec7a131d29b7f444bb9b344a09e2a" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "proc-macro2", - "quote", - "structmeta-derive", - "syn", + "autocfg", ] [[package]] -name = "structmeta-derive" -version = "0.1.6" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24420be405b590e2d746d83b01f09af673270cf80e9b003a5fa7b651c58c7d93" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", - "syn", + "unicode-ident", ] [[package]] name = "syn" -version = "1.0.109" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -475,59 +438,41 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ - "cfg-if", "fastrand", - "redox_syscall", + "getrandom", + "once_cell", "rustix", - "windows-sys 0.45.0", -] - -[[package]] -name = "test-strategy" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61348cf95c0dfa12f0b6155f5b564d2806f518620a28263280ae357b41c96b4a" -dependencies = [ - "proc-macro2", - "quote", - "structmeta", - "syn", + "windows-sys", ] [[package]] name = "tokio" -version = "1.6.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a38d31d7831c6ed7aad00aa4c12d9375fd225a6dd77da1d25b707346319a975" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", - "memchr", "pin-project-lite", "tokio-macros", ] [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] -[[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.5" @@ -535,148 +480,115 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] -name = "wait-timeout" -version = "0.2.0" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ - "libc", + "wit-bindgen", ] [[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "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-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] -name = "windows_i686_gnu" -version = "0.48.0" +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" +name = "windows_x86_64_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_msvc" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" +name = "wit-bindgen" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "zerocopy" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "efbb2a062be311f2ba113ce66f697a4dc589f85e78a4aea276200804cea0ed87" +dependencies = [ + "zerocopy-derive", +] [[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" +name = "zerocopy-derive" +version = "0.8.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "0e8bc7269b54418e7aeeef514aa68f8690b8c0489a06b0136e5f57c4c5ccab89" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] diff --git a/Cargo.toml b/Cargo.toml index b20c3fa..ffd4234 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,8 +26,7 @@ tokio = { version = "1.0.0", features = ["io-std"], optional = true } anyhow = "1.0.70" dummy-waker = "1.1.0" futures = "0.3.25" -proptest = "1.1.0" -test-strategy = "0.3.0" +hegeltest = "0.3.4" tokio = { version = "1.0.0", features = ["io-std", "io-util", "macros", "rt"] } [features] diff --git a/src/cursor/tests.rs b/src/cursor/tests.rs index 9df480c..d59168c 100644 --- a/src/cursor/tests.rs +++ b/src/cursor/tests.rs @@ -6,26 +6,28 @@ use crate::BufList; use anyhow::{Context, Result, bail, ensure}; use bytes::{Buf, Bytes}; -use proptest::prelude::*; +use hegel::generators; use std::{ fmt, io::{self, BufRead, IoSliceMut, Read, Seek, SeekFrom}, }; -use test_strategy::{Arbitrary, proptest}; /// Assert that buf_list's cursor behaves identically to std::io::Cursor. -#[proptest] -fn proptest_cursor_ops( - #[strategy(buf_list_strategy())] buf_list: BufList, - #[strategy(cursor_ops_strategy())] ops: Vec, -) { +#[hegel::test(test_cases = 200)] +fn hegel_cursor_ops(tc: hegel::TestCase) { + let buf_list = tc.draw(buf_lists()); + + let num_bytes = buf_list.num_bytes(); let bytes = buf_list.clone().copy_to_bytes(buf_list.remaining()); let mut buf_list_cursor = crate::Cursor::new(&buf_list); let mut oracle_cursor = io::Cursor::new(bytes.as_ref()); - eprintln!("\n**** start!"); + let num_ops = tc.draw(generators::integers::().max_value(255)); + + eprintln!("\n**** start! num_bytes={num_bytes}, num_ops={num_ops}"); - for (index, cursor_op) in ops.into_iter().enumerate() { + for index in 0..num_ops { + let cursor_op = draw_cursor_op(&tc, num_bytes); // apply_and_compare prints out the rest of the line. eprint!("** index {}, operation {:?}: ", index, cursor_op); cursor_op @@ -36,39 +38,120 @@ fn proptest_cursor_ops( eprintln!("**** success"); } -fn buf_list_strategy() -> impl Strategy { - prop::collection::vec(prop::collection::vec(any::(), 1..128), 0..32) - .prop_map(|chunks| chunks.into_iter().map(Bytes::from).collect()) +#[hegel::composite] +fn buf_lists(tc: hegel::TestCase) -> BufList { + let chunks: Vec> = tc.draw( + generators::vecs( + generators::vecs(generators::integers::()) + .min_size(1) + .max_size(127), + ) + .max_size(31), + ); + chunks.into_iter().map(Bytes::from).collect() +} + +fn draw_cursor_op(tc: &hegel::TestCase, num_bytes: usize) -> CursorOp { + #[cfg(feature = "tokio1")] + let max_op: u8 = 15; + #[cfg(not(feature = "tokio1"))] + let max_op: u8 = 14; + + let op = tc.draw(generators::integers::().max_value(max_op)); + match op { + 0 => { + // Allow going past the end of the list a bit. + let pos = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)) as u64; + CursorOp::SetPosition(pos) + } + 1 => { + // Allow going past the end of the list a bit. + let pos = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)) as u64; + CursorOp::SeekStart(pos) + } + 2 => { + // Allow going past the beginning and end of the list a bit. + let raw = tc.draw(generators::integers::().max_value(num_bytes * 3 / 2)); + let offset = raw as i64 - (1 + num_bytes * 5 / 4) as i64; + CursorOp::SeekEnd(offset) + } + 3 => { + let raw = tc.draw(generators::integers::().max_value(num_bytes * 3 / 2)); + // Center the index at roughly 0. + let offset = raw as i64 - (num_bytes * 3 / 4) as i64; + CursorOp::SeekCurrent(offset) + } + 4 => { + let buf_size = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)); + CursorOp::Read(buf_size) + } + 5 => { + let n_bufs = tc.draw(generators::integers::().max_value(7)); + let sizes = (0..n_bufs) + .map(|_| tc.draw(generators::integers::().max_value(num_bytes))) + .collect(); + CursorOp::ReadVectored(sizes) + } + 6 => { + let buf_size = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)); + CursorOp::ReadExact(buf_size) + } + 7 => { + let amt = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)); + CursorOp::Consume(amt) + } + 8 => CursorOp::BufChunk, + 9 => { + let amt = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)); + CursorOp::BufAdvance(amt) + } + 10 => { + let num_iovs = tc.draw(generators::integers::().max_value(num_bytes)); + CursorOp::BufChunksVectored(num_iovs) + } + 11 => { + let len = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)); + CursorOp::BufCopyToBytes(len) + } + 12 => CursorOp::BufGetU8, + 13 => CursorOp::BufGetU64, + 14 => CursorOp::BufGetU64Le, + #[cfg(feature = "tokio1")] + 15 => { + let capacity = tc.draw(generators::integers::().max_value(num_bytes * 5 / 4)); + // filled is in 0..=capacity, to sometimes fill the whole buffer. + let filled = tc.draw(generators::integers::().max_value(capacity)); + CursorOp::PollRead { capacity, filled } + } + _ => unreachable!(), + } } -#[derive(Arbitrary, Clone, Debug)] +#[derive(Clone, Debug)] enum CursorOp { - SetPosition(prop::sample::Index), - SeekStart(prop::sample::Index), - SeekEnd(prop::sample::Index), - SeekCurrent(prop::sample::Index), - Read(prop::sample::Index), - ReadVectored( - #[strategy(prop::collection::vec(any::(), 0..8))] - Vec, - ), - ReadExact(prop::sample::Index), + SetPosition(u64), + SeekStart(u64), + SeekEnd(i64), + SeekCurrent(i64), + Read(usize), + ReadVectored(Vec), + ReadExact(usize), // fill_buf can't be tested here because oracle is a contiguous block. Instead, we check its // return value separately. - Consume(prop::sample::Index), - // Buf trait operations + Consume(usize), + // Buf trait operations. BufChunk, - BufAdvance(prop::sample::Index), - BufChunksVectored(prop::sample::Index), - BufCopyToBytes(prop::sample::Index), + BufAdvance(usize), + BufChunksVectored(usize), + BufCopyToBytes(usize), BufGetU8, BufGetU64, BufGetU64Le, // No need to test futures03 imps since they're simple wrappers around the main imps. #[cfg(feature = "tokio1")] PollRead { - capacity: prop::sample::Index, - filled: prop::sample::Index, + capacity: usize, + filled: usize, }, } @@ -81,17 +164,14 @@ impl CursorOp { ) -> Result<()> { let num_bytes = buf_list.get_ref().num_bytes(); match self { - Self::SetPosition(index) => { - // Allow going past the end of the list a bit. - let index = index.index(1 + num_bytes * 5 / 4) as u64; - eprintln!("set position: {}", index); + Self::SetPosition(pos) => { + eprintln!("set position: {}", pos); - buf_list.set_position(index); - oracle.set_position(index); + buf_list.set_position(pos); + oracle.set_position(pos); } - Self::SeekStart(index) => { - // Allow going past the end of the list a bit. - let style = SeekFrom::Start(index.index(1 + num_bytes * 5 / 4) as u64); + Self::SeekStart(pos) => { + let style = SeekFrom::Start(pos); eprintln!("style: {:?}", style); let buf_list_res = buf_list.seek(style); @@ -99,10 +179,8 @@ impl CursorOp { Self::assert_io_result_eq(buf_list_res, oracle_res) .context("operation result didn't match")?; } - Self::SeekEnd(index) => { - // Allow going past the beginning and end of the list a bit. - let index = index.index(1 + num_bytes * 3 / 2) as i64; - let style = SeekFrom::End(index - (1 + num_bytes * 5 / 4) as i64); + Self::SeekEnd(offset) => { + let style = SeekFrom::End(offset); eprintln!("style: {:?}", style); let buf_list_res = buf_list.seek(style); @@ -110,10 +188,8 @@ impl CursorOp { Self::assert_io_result_eq(buf_list_res, oracle_res) .context("operation result didn't match")?; } - Self::SeekCurrent(index) => { - let index = index.index(1 + num_bytes * 3 / 2) as i64; - // Center the index at roughly 0. - let style = SeekFrom::Current(index - (num_bytes * 3 / 4) as i64); + Self::SeekCurrent(offset) => { + let style = SeekFrom::Current(offset); eprintln!("style: {:?}", style); let buf_list_res = buf_list.seek(style); @@ -121,8 +197,7 @@ impl CursorOp { Self::assert_io_result_eq(buf_list_res, oracle_res) .context("operation result didn't match")?; } - Self::Read(index) => { - let buf_size = index.index(1 + num_bytes * 5 / 4); + Self::Read(buf_size) => { eprintln!("buf_size: {}", buf_size); // Must initialize the whole vec here so &mut returns the whole buffer -- can't use @@ -136,15 +211,14 @@ impl CursorOp { .context("operation result didn't match")?; ensure!(buf_list_buf == oracle_buf, "read buffer matches"); } - Self::ReadVectored(indexes) => { + Self::ReadVectored(sizes) => { // Build a bunch of IoSliceMuts. - let mut buf_list_vecs: Vec<_> = indexes + let mut buf_list_vecs: Vec<_> = sizes .into_iter() - .map(|index| { - // Must initialize the whole vec here so &mut returns the whole buffer -- can't - // use with_capacity! - let buf_size = index.index(1 + num_bytes); - vec![0u8; buf_size] + .map(|size| { + // Must initialize the whole vec here so &mut returns the whole buffer -- + // can't use with_capacity! + vec![0u8; size] }) .collect(); let mut oracle_vecs = buf_list_vecs.clone(); @@ -169,8 +243,7 @@ impl CursorOp { oracle_vecs ); } - Self::ReadExact(index) => { - let buf_size = index.index(1 + num_bytes * 5 / 4); + Self::ReadExact(buf_size) => { eprintln!("buf_size: {}", buf_size); // Must initialize the whole vec here so &mut returns the whole buffer -- can't use @@ -184,8 +257,7 @@ impl CursorOp { .context("operation result didn't match")?; ensure!(buf_list_buf == oracle_buf, "read buffer matches"); } - Self::Consume(index) => { - let amt = index.index(1 + num_bytes * 5 / 4); + Self::Consume(amt) => { eprintln!("amt: {}", amt); buf_list.consume(amt); @@ -211,19 +283,18 @@ impl CursorOp { ); if !buf_list_chunk.is_empty() { - // Verify buf_list's chunk is a prefix of oracle's chunk + // Verify buf_list's chunk is a prefix of oracle's chunk. ensure!( oracle_chunk.starts_with(buf_list_chunk), "buf_list chunk is not a prefix of oracle chunk" ); } } - Self::BufAdvance(index) => { - let amt = index.index(1 + num_bytes * 5 / 4); + Self::BufAdvance(amt) => { eprintln!("buf_advance: {}", amt); // Skip if already past the end, as the oracle's Buf impl has a debug assertion - // that checks position even when advancing by 0 + // that checks position even when advancing by 0. if buf_list.remaining() > 0 || amt == 0 && oracle.remaining() > 0 { // Cap the advance amount to the remaining bytes to avoid // hitting the debug assertion in std::io::Cursor's Buf @@ -237,11 +308,10 @@ impl CursorOp { eprintln!(" skipping: cursor past end"); } } - Self::BufChunksVectored(index) => { - let num_iovs = index.index(1 + num_bytes); + Self::BufChunksVectored(num_iovs) => { eprintln!("buf_chunks_vectored: {} iovs", num_iovs); - // First verify remaining() matches + // First verify remaining() matches. let buf_list_remaining = buf_list.remaining(); let oracle_remaining = oracle.remaining(); ensure!( @@ -266,9 +336,9 @@ impl CursorOp { // // Instead, we verify that: // 1. Both returned at least some data if there are bytes - // remaining + // remaining. // 2. The data that was returned matches (buf_list's data is a - // prefix of oracle's data) + // prefix of oracle's data). let buf_list_bytes: Vec = buf_list_iovs[..buf_list_filled] .iter() .flat_map(|iov| iov.as_ref().iter().copied()) @@ -309,7 +379,7 @@ impl CursorOp { ); } } else if buf_list_remaining == 0 { - // If no bytes remaining, should return no data + // If no bytes remaining, should return no data. ensure!( buf_list_bytes.is_empty() && oracle_bytes.is_empty(), "chunks_vectored should return no data when \ @@ -320,11 +390,10 @@ impl CursorOp { // provided. All we're doing is ensuring that buf_list doesn't // panic. } - Self::BufCopyToBytes(index) => { - let len = index.index(1 + num_bytes * 5 / 4); + Self::BufCopyToBytes(len) => { eprintln!("buf_copy_to_bytes: {}", len); - // copy_to_bytes can panic if len > remaining, so check first + // copy_to_bytes can panic if len > remaining, so check first. let buf_list_remaining = buf_list.remaining(); let oracle_remaining = oracle.remaining(); @@ -334,7 +403,7 @@ impl CursorOp { ensure!(buf_list_bytes == oracle_bytes, "copy_to_bytes didn't match"); } else { - // Both should panic, so just skip this operation + // Both should panic, so skip this operation. eprintln!(" skipping: len {} > remaining {}", len, buf_list_remaining); } } @@ -391,22 +460,18 @@ impl CursorOp { use std::{mem::MaybeUninit, pin::Pin, task::Poll}; use tokio::io::{AsyncRead, ReadBuf}; - let capacity = capacity.index(1 + num_bytes * 5 / 4); let mut buf_list_vec = vec![MaybeUninit::uninit(); capacity]; let mut oracle_vec = buf_list_vec.clone(); let mut buf_list_buf = ReadBuf::uninit(&mut buf_list_vec); - // Fill up the first bytes of the vector. This uses capacity + 1 so that we can - // sometimes fill up the whole buffer. - let filled_index = filled.index(capacity + 1); - let fill_vec = vec![0u8; filled_index]; + let fill_vec = vec![0u8; filled]; buf_list_buf.put_slice(&fill_vec); let mut oracle_buf = ReadBuf::uninit(&mut oracle_vec); oracle_buf.put_slice(&fill_vec); - eprintln!("capacity: {}, filled_index: {}", capacity, filled_index); + eprintln!("capacity: {}, filled: {}", capacity, filled); let waker = dummy_waker::dummy_waker(); let mut context = std::task::Context::from_waker(&waker); @@ -541,10 +606,6 @@ impl CursorOp { } } -fn cursor_ops_strategy() -> impl Strategy> { - prop::collection::vec(any::(), 0..256) -} - #[test] fn test_cursor_buf_trait() { // Create a BufList with multiple chunks