diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 7f8f142..f6f2bfa 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -16,14 +16,10 @@ jobs: platform: - runner: ubuntu-22.04 target: x86_64 - # - runner: ubuntu-22.04 - # target: x86 - runner: ubuntu-22.04 target: aarch64 - runner: ubuntu-22.04 target: armv7 - # - runner: ubuntu-22.04 - # target: s390x - runner: ubuntu-22.04 target: ppc64le steps: @@ -31,13 +27,25 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - name: Store RUSTFLAGS in ENV for x86_64 + if: matrix.platform.target == 'x86_64' + id: features + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x86_64 + if: matrix.platform.target == 'x86_64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --profile dist-release --out dist --find-interpreter sccache: "true" - manylinux: auto + manylinux: manylinux_2_28 - name: Upload wheels uses: actions/upload-artifact@v4 with: @@ -52,8 +60,6 @@ jobs: platform: - runner: ubuntu-22.04 target: x86_64 - # - runner: ubuntu-22.04 - # target: x86 - runner: ubuntu-22.04 target: aarch64 - runner: ubuntu-22.04 @@ -63,13 +69,25 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - name: Store RUSTFLAGS in ENV for x86_64 + if: matrix.platform.target == 'x86_64' + id: features + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x86_64 + if: matrix.platform.target == 'x86_64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --profile dist-release --out dist --find-interpreter sccache: "true" - manylinux: musllinux_1_2 + manylinux: manylinux_2_28 - name: Upload wheels uses: actions/upload-artifact@v4 with: @@ -84,14 +102,25 @@ jobs: platform: - runner: windows-latest target: x64 - # - runner: windows-latest - # target: x86 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: 3.x architecture: ${{ matrix.platform.target }} + - name: Store RUSTFLAGS in ENV for x86_64 + if: matrix.platform.target == 'x86_64' + id: features + shell: bash + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x64 + if: matrix.platform.target == 'x64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -104,6 +133,7 @@ jobs: name: wheels-windows-${{ matrix.platform.target }} path: dist + macos: runs-on: ${{ matrix.platform.runner }} strategy: @@ -119,6 +149,18 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - name: Store RUSTFLAGS in ENV for x86_64 + if: matrix.platform.target == 'x86_64' + id: features + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x86_64 + if: matrix.platform.target == 'x86_64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -146,22 +188,3 @@ jobs: name: wheels-sdist path: dist - publish-to-pypi: - name: Publish to PyPI - needs: [ linux, musllinux, windows, macos, sdist ] - runs-on: ubuntu-latest - environment: - name: pypi - url: https://pypi.org/p/rusterize - permissions: - id-token: write - steps: - - name: Download sdists and wheels - uses: actions/download-artifact@v4 - with: - path: dist - merge-multiple: true - - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - verbose: true diff --git a/.github/workflows/test-compile.yml b/.github/workflows/test-compile.yml index b88f6f8..9f48bb2 100644 --- a/.github/workflows/test-compile.yml +++ b/.github/workflows/test-compile.yml @@ -17,14 +17,10 @@ jobs: platform: - runner: ubuntu-22.04 target: x86_64 - # - runner: ubuntu-22.04 - # target: x86 - runner: ubuntu-22.04 target: aarch64 - runner: ubuntu-22.04 target: armv7 - # - runner: ubuntu-22.04 - # target: s390x - runner: ubuntu-22.04 target: ppc64le steps: @@ -32,13 +28,24 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - name: Store RUSTFLAGS in ENV + id: features + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x86_64 + if: matrix.platform.target == 'x86_64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --profile dist-release --out dist --find-interpreter sccache: "true" - manylinux: auto + manylinux: manylinux_2_28 - name: Upload wheels uses: actions/upload-artifact@v4 with: @@ -53,8 +60,6 @@ jobs: platform: - runner: ubuntu-22.04 target: x86_64 - # - runner: ubuntu-22.04 - # target: x86 - runner: ubuntu-22.04 target: aarch64 - runner: ubuntu-22.04 @@ -64,13 +69,24 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - name: Store RUSTFLAGS in ENV + id: features + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x86_64 + if: matrix.platform.target == 'x86_64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.platform.target }} args: --profile dist-release --out dist --find-interpreter sccache: "true" - manylinux: musllinux_1_2 + manylinux: manylinux_2_28 - name: Upload wheels uses: actions/upload-artifact@v4 with: @@ -85,14 +101,24 @@ jobs: platform: - runner: windows-latest target: x64 - # - runner: windows-latest - # target: x86 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: 3.x architecture: ${{ matrix.platform.target }} + - name: Store RUSTFLAGS in ENV + id: features + shell: bash + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x64 + if: matrix.platform.target == 'x64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -105,6 +131,7 @@ jobs: name: wheels-windows-${{ matrix.platform.target }} path: dist + macos: runs-on: ${{ matrix.platform.runner }} strategy: @@ -120,6 +147,17 @@ jobs: - uses: actions/setup-python@v5 with: python-version: 3.x + - name: Store RUSTFLAGS in ENV + id: features + run: | + FEATURES=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe + echo "features=$FEATURES" >> $GITHUB_OUTPUT + - name: Set RUSTFLAGS for x86_64 + if: matrix.platform.target == 'x86_64' + env: + FEATURES: ${{ steps.features.outputs.features }} + run: | + echo "RUSTFLAGS=-C target-feature=$FEATURES" >> $GITHUB_ENV - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -145,4 +183,5 @@ jobs: uses: actions/upload-artifact@v4 with: name: wheels-sdist - path: dist \ No newline at end of file + path: dist + diff --git a/.gitignore b/.gitignore index 8c542d8..71aa478 100644 --- a/.gitignore +++ b/.gitignore @@ -36,5 +36,5 @@ tests/ # README quarto stuff README_files -# Other stuff -_ROADMAP +# uv +uv.lock diff --git a/Cargo.lock b/Cargo.lock index 5954a64..b8c6ffa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,21 +13,20 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "getrandom 0.2.15", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -71,9 +70,9 @@ dependencies = [ [[package]] name = "argminmax" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52424b59d69d69d5056d508b260553afd91c57e21849579cd1f50ee8b8b88eaa" +checksum = "70f13d10a41ac8d2ec79ee34178d61e6f47a29c2edfe7ef1721c7383b0359e65" dependencies = [ "num-traits", ] @@ -84,6 +83,30 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed51fe0f224d1d4ea768be38c51f9f831dee9d05c163c11fba0b8c44387b1fc3" +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -119,9 +142,12 @@ dependencies = [ [[package]] name = "atoi_simd" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4790f9e8961209112beb783d85449b508673cf4a6a419c8449b210743ac4dbe9" +checksum = "c2a49e05797ca52e312a0c658938b7d00693ef037799ef7187678f212d7684cf" +dependencies = [ + "debug_unsafe", +] [[package]] name = "atomic-waker" @@ -131,15 +157,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -147,7 +173,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -167,33 +193,52 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" dependencies = [ "serde", ] +[[package]] +name = "blake3" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "boxcar" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26c4925bc979b677330a8c7fe7a8c94af2dbb4a2d37b4a20a80d884400f46baa" + [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytemuck" -version = "1.22.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.9.3" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1" +checksum = "441473f2b4b0459a68628c744bc61d23e730fb00128b841d30fa4bb3972257e4" dependencies = [ "proc-macro2", "quote", @@ -217,18 +262,18 @@ dependencies = [ [[package]] name = "castaway" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" dependencies = [ "rustversion", ] [[package]] name = "cc" -version = "1.2.18" +version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ "jobserver", "libc", @@ -237,15 +282,21 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -256,25 +307,14 @@ dependencies = [ [[package]] name = "chrono-tz" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3" +checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3" dependencies = [ "chrono", - "chrono-tz-build", "phf", ] -[[package]] -name = "chrono-tz-build" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402" -dependencies = [ - "parse-zoneinfo", - "phf_codegen", -] - [[package]] name = "comfy-table" version = "7.1.4" @@ -301,6 +341,31 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -309,18 +374,18 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "crc32fast" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -368,7 +433,7 @@ dependencies = [ "bitflags", "crossterm_winapi", "parking_lot", - "rustix", + "rustix 0.38.44", "winapi", ] @@ -381,11 +446,28 @@ dependencies = [ "winapi", ] +[[package]] +name = "debug_unsafe" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85d3cef41d236720ed453e102153a53e4cc3d2fde848c0078a50cf249e8e3e5b" + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dyn-clone" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "earcutr" @@ -393,7 +475,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79127ed59a85d7687c409e9978547cffb7dc79675355ed22da6b66fd5f6ead01" dependencies = [ - "itertools", + "itertools 0.11.0", "num-traits", ] @@ -402,21 +484,6 @@ name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" -dependencies = [ - "serde", -] - -[[package]] -name = "enum_dispatch" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn", -] [[package]] name = "equivalent" @@ -426,19 +493,40 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.11" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "ethnum" -version = "1.5.0" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b" + +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] [[package]] name = "fallible-streaming-iterator" @@ -454,9 +542,9 @@ checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55" [[package]] name = "flate2" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -468,12 +556,37 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs4" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8640e34b88f7652208ce9e88b1a37a2ae95227d84abec377ccd3c5cfeb141ed4" +dependencies = [ + "rustix 1.0.8", + "windows-sys 0.59.0", +] + [[package]] name = "futures" version = "0.3.31" @@ -583,18 +696,18 @@ dependencies = [ [[package]] name = "geo-traits" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b018fc19fa58202b03f1c809aebe654f7d70fd3887dace34c3d05c11aeb474b5" +checksum = "2e7c353d12a704ccfab1ba8bfb1a7fe6cb18b665bf89d37f4f7890edcd260206" dependencies = [ "geo-types", ] [[package]] name = "geo-types" -version = "0.7.16" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ddb1950450d67efee2bbc5e429c68d052a822de3aad010d28b351fbb705224" +checksum = "75a4dcd69d35b2c87a7c83bce9af69fd65c9d68d3833a0ded568983928f3fc99" dependencies = [ "approx", "num-traits", @@ -605,36 +718,38 @@ dependencies = [ [[package]] name = "geographiclib-rs" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e5ed84f8089c70234b0a8e0aedb6dc733671612ddc0d37c6066052f9781960" +checksum = "f611040a2bb37eaa29a78a128d1e92a378a03e0b6e66ae27398d42b1ba9a7841" dependencies = [ "libm", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -649,6 +764,25 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +[[package]] +name = "h2" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hash32" version = "0.3.1" @@ -672,9 +806,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" dependencies = [ "allocator-api2", "equivalent", @@ -699,12 +833,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hex" version = "0.4.3" @@ -720,6 +848,113 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "humantime" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.0", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "i_float" version = "1.7.0" @@ -776,7 +1011,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.0", + "windows-core", ] [[package]] @@ -789,90 +1024,245 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "2.9.0" +name = "icu_collections" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ - "equivalent", - "hashbrown 0.15.2", - "serde", + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", ] [[package]] -name = "indoc" -version = "2.0.6" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] [[package]] -name = "itertools" -version = "0.11.0" +name = "icu_normalizer" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ - "either", + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", ] [[package]] -name = "itoa" -version = "1.0.15" +name = "icu_normalizer_data" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] -name = "jobserver" -version = "0.1.33" +name = "icu_properties" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ - "getrandom 0.3.2", - "libc", + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", ] [[package]] -name = "js-sys" -version = "0.3.77" +name = "icu_properties_data" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] -name = "libc" -version = "0.2.171" +name = "icu_provider" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] [[package]] -name = "libm" -version = "0.2.11" +name = "idna" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] [[package]] -name = "libmimalloc-sys" -version = "0.1.42" +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec9d6fac27761dabcd4ee73571cdb06b7022dc99089acbe5435691edffaac0f4" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "cc", - "libc", + "icu_normalizer", + "icu_properties", ] [[package]] -name = "linux-raw-sys" -version = "0.4.15" +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", + "serde", +] + +[[package]] +name = "indoc" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" + +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88cd67e9de251c1781dbe2f641a1a3ad66eaae831b8a2c38fbdc5ddae16d4d" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", @@ -884,6 +1274,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4" version = "1.28.1" @@ -905,9 +1301,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" dependencies = [ "autocfg", "rawpointer", @@ -915,15 +1311,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memmap2" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28" dependencies = [ "libc", ] @@ -939,31 +1335,31 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995942f432bbb4822a7e9c3faa87a695185b0d09273ba85f097b54f4e458f2af" +checksum = "b1791cbe101e95af5764f06f20f6760521f7158f69dbf9d6baf941ee1bf6bc40" dependencies = [ "libmimalloc-sys", ] [[package]] name = "miniz_oxide" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] @@ -991,15 +1387,6 @@ dependencies = [ "chrono", ] -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - [[package]] name = "num-complex" version = "0.4.6" @@ -1028,30 +1415,21 @@ dependencies = [ "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "num_enum" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" dependencies = [ "num_enum_derive", + "rustversion", ] [[package]] name = "num_enum_derive" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1061,9 +1439,9 @@ dependencies = [ [[package]] name = "numpy" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94caae805f998a07d33af06e6a3891e38556051b8045c615470a71590e13e78" +checksum = "29f1dee9aa8d3f6f8e8b9af3803006101bb3653866ef056d530d53ae68587191" dependencies = [ "libc", "ndarray", @@ -1071,6 +1449,7 @@ dependencies = [ "num-integer", "num-traits", "pyo3", + "pyo3-build-config", "rustc-hash", ] @@ -1083,17 +1462,64 @@ dependencies = [ "memchr", ] +[[package]] +name = "object_store" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efc4f07659e11cd45a341cd24d71e683e3be65d9ff1f8150061678fe60437496" +dependencies = [ + "async-trait", + "base64", + "bytes", + "chrono", + "form_urlencoded", + "futures", + "http", + "http-body-util", + "humantime", + "hyper", + "itertools 0.14.0", + "parking_lot", + "percent-encoding", + "quick-xml", + "rand 0.9.2", + "reqwest", + "ring", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror 2.0.12", + "tokio", + "tracing", + "url", + "walkdir", + "wasm-bindgen-futures", + "web-time", +] + [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ "lock_api", "parking_lot_core", @@ -1101,25 +1527,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] -name = "parse-zoneinfo" -version = "0.3.1" +name = "paste" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" -dependencies = [ - "regex", -] +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -1129,38 +1552,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7" dependencies = [ "phf_shared", - "rand", ] [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981" dependencies = [ "siphasher", ] @@ -1185,20 +1588,21 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "planus" -version = "0.3.1" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1691dd09e82f428ce8d6310bd6d5da2557c82ff17694d2a32cad7242aea89f" +checksum = "3daf8e3d4b712abe1d690838f6e29fb76b76ea19589c4afa39ec30e12f62af71" dependencies = [ "array-init-cursor", + "hashbrown 0.15.4", ] [[package]] name = "polars" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72571dde488ecccbe799798bf99ab7308ebdb7cf5d95bcc498dbd5a132f0da4d" +checksum = "443824f43bca39b178353d6c09e4b44e115b21f107a5654d5f980d20b432a303" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "polars-arrow", "polars-core", "polars-error", @@ -1214,24 +1618,23 @@ dependencies = [ [[package]] name = "polars-arrow" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6611c758d52e799761cc25900666b71552e6c929d88052811bc9daad4b3321a8" +checksum = "809c5340e9e6c16eee5a07585161bae99f903f53af7402075efec23ee75fce5b" dependencies = [ - "ahash", "atoi_simd", + "bitflags", "bytemuck", "chrono", "chrono-tz", "dyn-clone", "either", "ethnum", - "getrandom 0.2.15", - "hashbrown 0.15.2", + "getrandom 0.2.16", + "hashbrown 0.15.4", "itoa", "lz4", "num-traits", - "parking_lot", "polars-arrow-format", "polars-error", "polars-schema", @@ -1239,7 +1642,6 @@ dependencies = [ "serde", "simdutf8", "streaming-iterator", - "strength_reduce", "strum_macros", "version_check", "zstd", @@ -1247,9 +1649,9 @@ dependencies = [ [[package]] name = "polars-arrow-format" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b0ef2474af9396b19025b189d96e992311e6a47f90c53cd998b36c4c64b84c" +checksum = "863c04c514be005eced7db7053e20d49f7e7a58048a282fa52dfea1fd5434e78" dependencies = [ "planus", "serde", @@ -1257,85 +1659,89 @@ dependencies = [ [[package]] name = "polars-compute" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332f2547dbb27599a8ffe68e56159f5996ba03d1dad0382ccb62c109ceacdeb6" +checksum = "8b8802ff2cccea01a845ea8267a7600e495747ed109035bb5020c33eb8717ff4" dependencies = [ "atoi_simd", "bytemuck", "chrono", "either", "fast-float2", + "hashbrown 0.15.4", "itoa", "num-traits", "polars-arrow", "polars-error", "polars-utils", + "rand 0.8.5", "ryu", + "serde", + "skiplist", "strength_reduce", + "strum_macros", "version_check", ] [[package]] name = "polars-core" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "796d06eae7e6e74ed28ea54a8fccc584ebac84e6cf0e1e9ba41ffc807b169a01" +checksum = "3fc3c99d7000be1be11665e1e260b93dc3b927342b9da3b53d9a1ac264e4343d" dependencies = [ - "ahash", "bitflags", + "boxcar", "bytemuck", "chrono", "chrono-tz", "comfy-table", "either", "hashbrown 0.14.5", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "indexmap", "itoa", "num-traits", - "once_cell", "polars-arrow", "polars-compute", "polars-error", "polars-row", "polars-schema", "polars-utils", - "rand", + "rand 0.8.5", "rand_distr", "rayon", "regex", "serde", "serde_json", "strum_macros", - "thiserror 2.0.12", + "uuid", "version_check", "xxhash-rust", ] [[package]] name = "polars-error" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d6529cae0d1db5ed690e47de41fac9b35ae0c26d476830c2079f130887b847" +checksum = "1397c17712e61a55fdd45c033a69f0451fde2973ff2609c22e363e21d68f11ef" dependencies = [ + "object_store", + "parking_lot", "polars-arrow-format", "regex", + "signal-hook", "simdutf8", - "thiserror 2.0.12", ] [[package]] name = "polars-expr" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e639991a8ad4fb12880ab44bcc3cf44a5703df003142334d9caf86d77d77e7" +checksum = "33d3aa6722c9a3e0b721ec2bcdc4affd9e50e4cb606cd81bb94535a9a5a6ade9" dependencies = [ - "ahash", "bitflags", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "num-traits", - "once_cell", "polars-arrow", "polars-compute", "polars-core", @@ -1345,31 +1751,33 @@ dependencies = [ "polars-row", "polars-time", "polars-utils", - "rand", + "rand 0.8.5", "rayon", + "recursive", ] [[package]] name = "polars-io" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719a77e94480f6be090512da196e378cbcbeb3584c6fe1134c600aee906e38ab" +checksum = "1a632d442a99821250a8fa66f7d488bf5ee98e5f515e65256b12956cb81fc110" dependencies = [ - "ahash", "async-trait", "atoi_simd", + "blake3", "bytes", "chrono", "fast-float2", + "fs4", "futures", "glob", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "home", "itoa", "memchr", "memmap2", "num-traits", - "once_cell", + "object_store", "percent-encoding", "polars-arrow", "polars-core", @@ -1378,48 +1786,48 @@ dependencies = [ "polars-schema", "polars-time", "polars-utils", - "pyo3", "rayon", "regex", + "reqwest", "ryu", "serde", + "serde_json", "simdutf8", "tokio", "tokio-util", + "url", ] [[package]] name = "polars-lazy" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a731a672dfc8ac38c1f73c9a4b2ae38d2fc8ac363bfb64c5f3a3e072ffc5ad" +checksum = "f4ed0c87bdc8820447a38ae8efdb5a51a5a93e8bd528cffb05d05cf1145e4161" dependencies = [ - "ahash", "bitflags", "chrono", + "either", "memchr", - "once_cell", "polars-arrow", + "polars-compute", "polars-core", "polars-expr", "polars-io", "polars-mem-engine", "polars-ops", - "polars-pipe", "polars-plan", "polars-stream", "polars-time", "polars-utils", - "pyo3", "rayon", "version_check", ] [[package]] name = "polars-mem-engine" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33442189bcbf2e2559aa7914db3835429030a13f4f18e43af5fba9d1b018cf12" +checksum = "675294ddf9174029e48caa4e59b0665ea64bfb784a366b197690895a6ed65c68" dependencies = [ "memmap2", "polars-arrow", @@ -1431,29 +1839,28 @@ dependencies = [ "polars-plan", "polars-time", "polars-utils", - "pyo3", "rayon", + "recursive", ] [[package]] name = "polars-ops" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbb83218b0c216104f0076cd1a005128be078f958125f3d59b094ee73d78c18e" +checksum = "1eb4db68956f857c52eeda072d87644a7b42eac41d55073af94dfac8441af6cf" dependencies = [ - "ahash", "argminmax", "base64", "bytemuck", "chrono", "chrono-tz", "either", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "hex", "indexmap", + "libm", "memchr", "num-traits", - "once_cell", "polars-arrow", "polars-compute", "polars-core", @@ -1463,7 +1870,6 @@ dependencies = [ "rayon", "regex", "regex-syntax", - "serde", "strum_macros", "unicode-normalization", "unicode-reverse", @@ -1472,17 +1878,16 @@ dependencies = [ [[package]] name = "polars-parquet" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c60ee85535590a38db6c703a21be4cb25342e40f573f070d1e16f9d84a53ac7" +checksum = "7c849c10edd9511ccd4ec4130e283ee3a8b3bb48a7d74ac6354c1c20add81065" dependencies = [ - "ahash", "async-stream", "base64", "bytemuck", "ethnum", "futures", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "num-traits", "polars-arrow", "polars-compute", @@ -1504,49 +1909,21 @@ dependencies = [ "futures", ] -[[package]] -name = "polars-pipe" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42d238fb76698f56e51ddfa89b135e4eda56a4767c6e8859eed0ab78386fcd52" -dependencies = [ - "crossbeam-channel", - "crossbeam-queue", - "enum_dispatch", - "hashbrown 0.15.2", - "num-traits", - "once_cell", - "polars-arrow", - "polars-compute", - "polars-core", - "polars-expr", - "polars-io", - "polars-ops", - "polars-plan", - "polars-row", - "polars-utils", - "rayon", - "uuid", - "version_check", -] - [[package]] name = "polars-plan" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f03533a93aa66127fcb909a87153a3c7cfee6f0ae59f497e73d7736208da54c" +checksum = "71fb4412c42bf637c2c02a617381c682ed425d9c8e4bd1fcb85cf352ed2a67c6" dependencies = [ - "ahash", "bitflags", "bytemuck", "bytes", "chrono", "chrono-tz", "either", - "hashbrown 0.15.2", + "hashbrown 0.15.4", "memmap2", "num-traits", - "once_cell", "percent-encoding", "polars-arrow", "polars-compute", @@ -1555,20 +1932,18 @@ dependencies = [ "polars-ops", "polars-time", "polars-utils", - "pyo3", "rayon", "recursive", "regex", - "serde", "strum_macros", "version_check", ] [[package]] name = "polars-row" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf47f7409f8e75328d7d034be390842924eb276716d0458607be0bddb8cc839" +checksum = "08fb77ac1d37340d9cfe57cf58000cf3d9cce429e10d25066952c6145c684cc0" dependencies = [ "bitflags", "bytemuck", @@ -1580,9 +1955,9 @@ dependencies = [ [[package]] name = "polars-schema" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416621ae82b84466cf4ff36838a9b0aeb4a67e76bd3065edc8c9cb7da19b1bc7" +checksum = "ada7c7e2fbbeffbdd67628cd8a89f02b0a8d21c71d34e297e2463a7c17575203" dependencies = [ "indexmap", "polars-error", @@ -1593,10 +1968,11 @@ dependencies = [ [[package]] name = "polars-sql" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edaab553b90aa4d6743bb538978e1982368acb58a94408d7dd3299cad49c7083" +checksum = "4a8e512b1f05ffda9963fe8f6a7c62dcba86be85218bc033ecdad2802cc1b1a0" dependencies = [ + "bitflags", "hex", "polars-core", "polars-error", @@ -1605,7 +1981,7 @@ dependencies = [ "polars-plan", "polars-time", "polars-utils", - "rand", + "rand 0.8.5", "regex", "serde", "sqlparser", @@ -1613,17 +1989,24 @@ dependencies = [ [[package]] name = "polars-stream" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "498997b656c779610c1496b3d96a59fe569ef22a5b81ccfe5325cb3df8dff2fd" +checksum = "5b0a02d8050acd9b64ed7e36c5bc96f6d4f46a940220f9c0e34c96b51f830f8c" dependencies = [ + "async-channel", + "async-trait", "atomic-waker", + "bitflags", + "crossbeam-channel", "crossbeam-deque", + "crossbeam-queue", "crossbeam-utils", "futures", "memmap2", "parking_lot", + "percent-encoding", "pin-project-lite", + "polars-arrow", "polars-core", "polars-error", "polars-expr", @@ -1633,7 +2016,7 @@ dependencies = [ "polars-parquet", "polars-plan", "polars-utils", - "rand", + "rand 0.8.5", "rayon", "recursive", "slotmap", @@ -1643,9 +2026,9 @@ dependencies = [ [[package]] name = "polars-time" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d192efbdab516d28b3fab1709a969e3385bd5cda050b7c9aa9e2502a01fda879" +checksum = "72e84a30110880ffede8d93c085fc429ab1b8bf1acf3d6d489143dd34be374c4" dependencies = [ "atoi_simd", "bytemuck", @@ -1653,7 +2036,6 @@ dependencies = [ "chrono-tz", "now", "num-traits", - "once_cell", "polars-arrow", "polars-compute", "polars-core", @@ -1662,45 +2044,44 @@ dependencies = [ "polars-utils", "rayon", "regex", - "serde", "strum_macros", ] [[package]] name = "polars-utils" -version = "0.46.0" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f6c8166a4a7fbc15b87c81645ed9e1f0651ff2e8c96cafc40ac5bf43441a10" +checksum = "a05e033960552c47fc35afe14d5af5b29696acc97ae5d3c585ebc33c246cc15f" dependencies = [ - "ahash", "bincode", "bytemuck", "bytes", "compact_str", "flate2", - "hashbrown 0.15.2", + "foldhash", + "hashbrown 0.15.4", "indexmap", "libc", "memmap2", "num-traits", - "once_cell", "polars-error", - "pyo3", - "rand", + "rand 0.8.5", "raw-cpuid", "rayon", + "regex", + "rmp-serde", "serde", "serde_json", + "slotmap", "stacker", - "sysinfo", "version_check", ] [[package]] name = "portable-atomic" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" [[package]] name = "portable-atomic-util" @@ -1711,13 +2092,22 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.24", + "zerocopy", ] [[package]] @@ -1731,29 +2121,28 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] [[package]] name = "psm" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" +checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" dependencies = [ "cc", ] [[package]] name = "pyo3" -version = "0.23.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872" +checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" dependencies = [ - "cfg-if", "indoc", "libc", "memoffset", @@ -1767,9 +2156,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.23.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb" +checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" dependencies = [ "once_cell", "python3-dll-a", @@ -1778,9 +2167,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.23.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d" +checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" dependencies = [ "libc", "pyo3-build-config", @@ -1788,9 +2177,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.23.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da" +checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -1800,9 +2189,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.23.5" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028" +checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" dependencies = [ "heck", "proc-macro2", @@ -1813,31 +2202,93 @@ dependencies = [ [[package]] name = "pyo3-polars" -version = "0.20.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e7db078e647fbd863d7605d13ef1553c06dd84ba9559f76512d3ca63d5fff20" +checksum = "780638e429de4b5c2b336c3f2527440a55be1b7e8627579f6e98f8e189192c7b" dependencies = [ "libc", "once_cell", "polars", "polars-arrow", "polars-core", - "polars-lazy", - "polars-plan", - "polars-utils", "pyo3", "thiserror 1.0.69", ] [[package]] name = "python3-dll-a" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fe4227a288cf9493942ad0220ea3f185f4d1f2a14f197f7344d6d02f4ed4ed" +checksum = "d381ef313ae70b4da5f95f8a4de773c6aa5cd28f73adec4b4a31df70b66780d8" dependencies = [ "cc", ] +[[package]] +name = "quick-xml" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quinn" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.5.10", + "thiserror 2.0.12", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.12", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "quote" version = "1.0.40" @@ -1849,9 +2300,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -1860,8 +2311,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", ] [[package]] @@ -1871,7 +2332,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", ] [[package]] @@ -1880,7 +2351,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", ] [[package]] @@ -1890,7 +2370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" dependencies = [ "num-traits", - "rand", + "rand 0.8.5", ] [[package]] @@ -1950,9 +2430,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ "bitflags", ] @@ -1986,11 +2466,89 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "reqwest" +version = "0.12.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "robust" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30" +checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" [[package]] name = "rstar" @@ -2005,9 +2563,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -2017,14 +2575,14 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rusterize" -version = "0.3.0" +version = "0.4.0" dependencies = [ "geo", "geo-traits", "geo-types", "mimalloc", "ndarray", - "num_cpus", + "num-traits", "numpy", "polars", "pyo3", @@ -2043,15 +2601,75 @@ dependencies = [ "bitflags", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", "windows-sys 0.59.0", ] +[[package]] +name = "rustix" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", +] + +[[package]] +name = "rustls" +version = "0.23.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -2059,12 +2677,53 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "security-framework" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.219" @@ -2087,9 +2746,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ "itoa", "memchr", @@ -2097,12 +2756,43 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + [[package]] name = "simdutf8" version = "0.1.5" @@ -2116,14 +2806,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] -name = "slab" -version = "0.4.9" +name = "skiplist" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "0eec25f46463fcdc5e02f388c2780b1b58e01be81a8378e62ec60931beccc3f6" dependencies = [ - "autocfg", + "rand 0.8.5", ] +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + [[package]] name = "slotmap" version = "1.0.7" @@ -2135,27 +2831,37 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.15.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", ] +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "spade" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ece03ff43cd2a9b57ebf776ea5e78bd30b3b4185a619f041079f4109f385034" +checksum = "a14e31a007e9f85c32784b04f89e6e194bb252a4d41b4a8ccd9e77245d901c8c" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.4", "num-traits", "robust", "smallvec", @@ -2178,9 +2884,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "stacker" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" +checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" dependencies = [ "cc", "cfg-if", @@ -2229,11 +2935,17 @@ dependencies = [ "syn", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" -version = "2.0.100" +version = "2.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" dependencies = [ "proc-macro2", "quote", @@ -2241,23 +2953,30 @@ dependencies = [ ] [[package]] -name = "sysinfo" -version = "0.33.1" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "windows", + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "thiserror" @@ -2319,6 +3038,16 @@ dependencies = [ "tikv-jemalloc-sys", ] +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.9.0" @@ -2336,24 +3065,48 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", "pin-project-lite", - "socket2", - "windows-sys 0.52.0", + "slab", + "socket2 0.6.0", + "tokio-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", ] [[package]] name = "tokio-util" -version = "0.7.14" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -2364,21 +3117,103 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ "indexmap", "toml_datetime", "winnow", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -2411,9 +3246,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" [[package]] name = "unindent" @@ -2421,13 +3256,38 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -2436,11 +3296,30 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -2477,6 +3356,19 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.100" @@ -2509,6 +3401,39 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2526,57 +3451,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.57.0" +name = "winapi-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-core 0.57.0", - "windows-targets", + "windows-sys 0.59.0", ] [[package]] -name = "windows-core" -version = "0.57.0" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets", -] +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", + "windows-implement", + "windows-interface", "windows-link", - "windows-result 0.3.2", + "windows-result", "windows-strings", ] -[[package]] -name = "windows-implement" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-implement" version = "0.60.0" @@ -2588,17 +3489,6 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "windows-interface" version = "0.59.1" @@ -2612,33 +3502,24 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - -[[package]] -name = "windows-result" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets", -] +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -2649,7 +3530,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -2658,7 +3539,16 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -2667,14 +3557,31 @@ 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", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -2683,53 +3590,101 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[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_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[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_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[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_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -2745,9 +3700,9 @@ dependencies = [ [[package]] name = "wkb" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e2c084338d6407d24c5a43208aca32128a5d62107eab5ca18314395c4aa3f0" +checksum = "ff9eff6aebac4c64f9c7c057a68f6359284e2a80acf102dffe041fe219b3a082" dependencies = [ "byteorder", "geo-traits", @@ -2755,6 +3710,12 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + [[package]] name = "xxhash-rust" version = "0.8.15" @@ -2762,28 +3723,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] -name = "zerocopy" -version = "0.7.35" +name = "yoke" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" dependencies = [ - "zerocopy-derive 0.7.35", + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "zerocopy-derive 0.8.24", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", @@ -2791,10 +3767,59 @@ dependencies = [ ] [[package]] -name = "zerocopy-derive" -version = "0.8.24" +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbb9122ea75b11bf96e7492afb723e8a7fbe12c67417aa95e7e3d18144d37cd" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index ef51f8e..872b161 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["profile-rustflags"] [package] name = "rusterize" -version = "0.3.0" +version = "0.4.0" edition = "2024" resolver = "2" @@ -12,16 +12,16 @@ crate-type = ["cdylib"] [dependencies] geo = "0.30.0" -geo-traits = "0.2.0" -geo-types = "0.7.16" +geo-traits = "0.3.0" +geo-types = "0.7.17" ndarray = { version = "0.16.1", features = ["rayon"] } -num_cpus = "1.16.0" -numpy = "0.23.0" -polars = { version = "0.46.0", features = ["lazy", "simd", "performant", "nightly"] } -pyo3 = { version = "0.23.5", features = ["extension-module", "abi3-py311", "generate-import-lib"] } -pyo3-polars = { version = "0.20.0", features = ["lazy", "dtype-struct"] } +num-traits = "0.2.19" +numpy = "0.25.0" +polars = { version = "0.49.1", features = ["lazy", "simd", "performant", "nightly"] } +pyo3 = { version = "0.25.1", features = ["extension-module", "abi3-py311", "generate-import-lib"] } +pyo3-polars = "0.22.0" rayon = "1.10.0" -wkb = "0.8.0" +wkb = "0.9.0" # OS-specific allocators [target.'cfg(not(target_family = "unix"))'.dependencies] @@ -33,14 +33,8 @@ tikv-jemallocator = { version = "*", features = ["disable_initial_exec_tls", "ba [target.'cfg(all(target_family = "unix", target_os = "macos"))'.dependencies] tikv-jemallocator = { version = "*", features = ["disable_initial_exec_tls"] } -[profile.profiler] -inherits = "dev" -debug = true -lto = true -codegen-units = 1 - [profile.dist-release] inherits = "release" -rustflags = ["-C", "target-feature=+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+cmpxchg16b,+avx,+avx2,+fma,+bmi1,+bmi2,+lzcnt,+pclmulqdq,+movbe"] codegen-units = 1 -lto = true +debug = false +lto = "fat" diff --git a/README.md b/README.md index d2e987b..97c8aaa 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ High performance rasterization tool for Python built in Rust. This repository stems from the [fasterize](https://github.com/ecohealthalliance/fasterize.git) package built in C++ -for R and ports parts of the logics into Python with a Rust backend, in addition to some useful improvements. +for R and ports parts of the logics into Python with a Rust backend, in addition to some useful improvements (see [API](#API)). -**rusterize** is designed to work on *(multi)polygons* and *(multi)linestrings*. Functionally, it takes an input [geopandas](https://geopandas.org/en/stable/) dataframe and returns a [xarray](https://docs.xarray.dev/en/stable/). +**rusterize** is designed to work on *(multi)polygons* and *(multi)linestrings*, even when they are nested inside complex geometry collections. Functionally, it takes an input [geopandas](https://geopandas.org/en/stable/) dataframe and returns a [xarray](https://docs.xarray.dev/en/stable/). # Installation @@ -28,7 +28,7 @@ git clone https://github.com//rusterize.git cd rusterize # Install the Rust nightly toolchain -rustup toolchain install nightly-2025-01-05 +rustup toolchain install nightly-2025-07-31 # Install maturin pip install maturin @@ -42,7 +42,7 @@ maturin develop --profile dist-release This package has a simple API: ``` python -from rusterize.core import rusterize +from rusterize import rusterize # gdf = @@ -50,21 +50,25 @@ from rusterize.core import rusterize rusterize(gdf, res=(30, 30), out_shape=(10, 10) - extent=(0, 300, 0, 300) + extent=(0, 10, 10, 20) field="field", by="by", + burn=None, fun="sum", - background=0) + background=0, + dtype="uint8") ``` - `gdf`: geopandas dataframe to rasterize -- `res`: tuple of (xres, yres) for desired resolution (default: `None`) -- `out_shape`: tuple of (nrows, ncols) for desired output shape (default: `None`) -- `extent`: tuple of (xmin, ymin, xmax, ymax) for desired output extent (default: `None`) -- `field`: field to rasterize. (default: `None` -> a value of `1` is rasterized). -- `by`: column to rasterize. Assigns each group to a band in the stack. Values are taken from `field`. (default: `None` -> singleband raster) +- `res`: (xres, yres) for desired resolution (default: `None`) +- `out_shape`: (nrows, ncols) for desired output shape (default: `None`) +- `extent`: (xmin, ymin, xmax, ymax) for desired output extent (default: `None`) +- `field`: column to rasterize. Mutually exclusive with `burn`. (default: `None` -> a value of `1` is rasterized) +- `by`: column for grouping. Assign each group to a band in the stack. Values are taken from `field` if specified, else `burn` is rasterized. (default: `None` -> singleband raster) +- `burn`: a single value to burn. Mutually exclusive with `field`. (default: `None`). If no field is found in `gdf` or if `field` is `None`, then `burn=1` - `fun`: pixel function to use when multiple values overlap. Available options are `sum`, `first`, `last`, `min`, `max`, `count`, or `any`. (default: `last`) -- `background`: background value in final raster. (default: `np.nan`) +- `background`: background value in final raster. (default: `np.nan`). A `None` value corresponds to the default of the specified dtype. An illegal value for a dtype will be replaced with the default of that dtype. For example, a `background=np.nan` for `dtype="uint8"` will become `background=0`, where `0` is the default for `uint8`. +- `dtype`: dtype of the final raster. Possible values are `uint8`, `uint16`, `uint32`, `uint64`, `int8`, `int16`, `int32`, `int64`, `float32`, `float64` (default: `float64`) Note that control over the desired extent is not as strict as for resolution and shape. That is, when resolution, output shape, and extent are specified, priority is given to resolution and shape. @@ -79,7 +83,7 @@ returns a dictionary that is converted to a xarray on the Python side for simpliicty. ``` python -from rusterize.core import rusterize +from rusterize import rusterize import geopandas as gpd from shapely import wkt import matplotlib.pyplot as plt @@ -89,7 +93,8 @@ geoms = [ "POLYGON ((-180 -20, -140 55, 10 0, -140 -60, -180 -20), (-150 -20, -100 -10, -110 20, -150 -20))", "POLYGON ((-10 0, 140 60, 160 0, 140 -55, -10 0))", "POLYGON ((-125 0, 0 60, 40 5, 15 -45, -125 0))", - "MULTILINESTRING ((-180 -70, -140 -50), (-140 -50, -100 -70), (-100 -70, -60 -50), (-60 -50, -20 -70), (-20 -70, 20 -50), (20 -50, 60 -70), (60 -70, 100 -50), (100 -50, 140 -70), (140 -70, 180 -50))" + "MULTILINESTRING ((-180 -70, -140 -50), (-140 -50, -100 -70), (-100 -70, -60 -50), (-60 -50, -20 -70), (-20 -70, 20 -50), (20 -50, 60 -70), (60 -70, 100 -50), (100 -50, 140 -70), (140 -70, 180 -50))", + "GEOMETRYCOLLECTION (POINT (50 -40), POLYGON ((75 -40, 75 -30, 100 -30, 100 -40, 75 -40)), LINESTRING (80 -40, 100 0), GEOMETRYCOLLECTION (POLYGON ((100 20, 100 30, 110 30, 110 20, 100 20))))" ] # Convert WKT strings to Shapely geometries @@ -103,7 +108,7 @@ output = rusterize( gdf, res=(1, 1), field="value", - fun="sum" + fun="sum", ).squeeze() # plot it @@ -119,7 +124,7 @@ plt.show() **rusterize** is fast! Let’s try it on small and large datasets. ``` python -from rusterize.core import rusterize +from rusterize import rusterize import geopandas as gpd import requests import zipfile @@ -154,11 +159,10 @@ pytest --benchmark-min-rounds=20 --benchmark-time-unit='s' --------------------------------------------- benchmark: 1 tests -------------------------------------------- Name (time in s) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ------------------------------------------------------------------------------------------------------------- -rusterize_large 1.6430 1.9249 1.7442 0.1024 1.6878 0.1974 6;0 0.5733 20 1 -rusterize_small 0.0912 0.1194 0.1014 0.0113 0.0953 0.0223 7;0 9.8633 20 1 +rusterize_small 0.0791 0.0899 0.0812 0.0027 0.0803 0.0020 2;2 12.3214 20 1 +rusterize_large 1.379545 1.4474 1.4006 0.0178 1.3966 0.0214 5;1 0.7140 20 1 ------------------------------------------------------------------------------------------------------------- ``` - And fasterize: ``` r library(sf) @@ -181,9 +185,9 @@ microbenchmark( ``` ``` Unit: seconds - expr min lq mean median uq max neval - fasterize_large 9.9450280 10.6674467 10.8632224 10.9182963 11.1943478 11.3768210 20 - fasterize_small 0.4906411 0.5140836 0.5581061 0.5320919 0.5603512 0.8750579 20 + expr min lq mean median uq max neval + fasterize_small 0.4741043 0.4926114 0.5191707 0.5193289 0.536741 0.5859029 20 + fasterize_large 9.2199426 10.3595465 10.6653139 10.5369429 11.025771 11.7944567 20 ``` And on an even larger datasets? Here we use a layer from the province of Quebec, Canada representing ~2M polygons of forest stands, rasterized at 30 meters (20 rounds) with no field value and pixel function `any`. The comparison with `gdal_rasterize` was run with `hyperfine --runs 20 "gdal_rasterize -tr 30 30 -burn 1 "`. ``` @@ -191,7 +195,7 @@ And on an even larger datasets? Here we use a layer from the province of Quebec, --------------------------------------------- benchmark: 1 tests -------------------------------------------- Name (time in s) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations ------------------------------------------------------------------------------------------------------------- -rusterize 6.7270 7.0098 6.7824 0.0646 6.7686 0.0266 2;2 0.1474 20 1 +rusterize 5.9331 7.2308 6.1302 0.3183 5.9903 0.1736 2;4 0.1631 20 1 ------------------------------------------------------------------------------------------------------------- # fasterize @@ -200,8 +204,8 @@ Unit: seconds fasterize 157.4734 177.2055 194.3222 194.6455 213.9195 230.6504 20 # gdal_rasterize (CLI) - read from fast drive, write to fast drive -Time (mean ± σ): 5.801 s ± 0.124 s [User: 4.381 s, System: 1.396 s] -Range (min … max): 5.649 s … 6.023 s 20 runs +Time (mean ± σ): 5.495 s ± 0.038 s [User: 4.268 s, System: 1.225 s] +Range (min … max): 5.452 s … 5.623 s 20 runs ``` In terms of (multi)line rasterization speed, here's a benchmark against `gdal_rasterize` using a layer from the province of Quebec, Canada, representing a subset of the road network for a total of ~535K multilinestrings. ``` @@ -218,11 +222,11 @@ Range (min … max): 8.658 s … 8.874 s 20 runs ``` # Comparison with other tools -While **rusterize** is fast, there are other fast alternatives out there, including `GDAL`, `rasterio` and `geocube`. However, **rusterize** allows for a seamless, Rust-native processing with similar or lower memory footprint that doesn't require you to leave Python, and returns the geoinformation you need for downstream processing with ample control over resolution, shape, and extent. +While **rusterize** is fast, there are other fast alternatives out there, including `GDAL`, `rasterio` and `geocube`. However, **rusterize** allows for a seamless, Rust-native processing with similar or lower memory footprint that doesn't require you to leave Python, and returns the geoinformation you need for downstream processing with ample control over resolution, shape, extent, and data type. The following is a time comparison on a single run on the same forest stands dataset used earlier. ``` -rusterize: 6.7 sec +rusterize: 5.9 sec rasterio: 68 sec (but no spatial information) fasterize: 157 sec (including raster creation) geocube: 260 sec (larger memory footprint) diff --git a/img/plot.png b/img/plot.png index f6ec876..e7017fb 100644 Binary files a/img/plot.png and b/img/plot.png differ diff --git a/pyproject.toml b/pyproject.toml index 0096260..7641904 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ description = "High performance rasterization tool for Python built in Rust" readme = "README.md" requires-python = ">=3.11" license = {file = "LICENSE"} -keywords = ["fast", "raster", "geopandas", "xarray"] +keywords = ["rust", "fast", "raster", "geometry", "geopandas", "xarray"] author = {name = "Tommaso Trotto", email = "ttrotto@mail.ubc.ca"} classifiers = [ "License :: OSI Approved :: MIT License", @@ -33,4 +33,4 @@ repository = "https://github.com/ttrotto/rusterize" [tool.maturin] python-source = "python" module-name = "rusterize" -include = [{ path = "rust-toolchain.toml", format = "sdist" }] \ No newline at end of file +include = [{ path = "rust-toolchain.toml", format = "sdist" }] diff --git a/python/rusterize/__init__.py b/python/rusterize/__init__.py index df056f1..0192e8f 100644 --- a/python/rusterize/__init__.py +++ b/python/rusterize/__init__.py @@ -1,4 +1,120 @@ +from __future__ import annotations import importlib.metadata -from .core import * + +from types import NoneType +from typing import List, Tuple + +import numpy as np +import polars as pl +from geopandas import GeoDataFrame +import rioxarray +from xarray import DataArray +from .rusterize import _rusterize __version__ = importlib.metadata.version("rusterize") + + +def rusterize( + gdf: GeoDataFrame, + res: Tuple | List | None = None, + out_shape: Tuple | List | None = None, + extent: Tuple | List | None = None, + field: str | None = None, + by: str | None = None, + burn: int | float | None = None, + fun: str = "last", + background: int | float | None = np.nan, + dtype: str = "float64", +) -> DataArray: + """ + Fast geopandas rasterization into xarray.DataArray + + Args: + :param gdf: geopandas dataframe to rasterize. + :param res: (xres, yres) for rasterized data. + :param out_shape: (nrows, ncols) for regularized output shape. + :param extent: (xmin, xmax, ymin, ymax) for regularized extent. + :param field: field to rasterize, mutually exclusive with `burn`. Default is None. + :param by: column to rasterize, assigns each unique value to a layer in the stack based on field. Default is None. + :param burn: burn a value onto the raster, mutually exclusive with `field`. Default is None. + :param fun: pixel function to use. Available options are `sum`, `first`, `last`, `min`, `max`, `count`, or `any`. Default is `last`. + :param background: background value in final raster. Default is np.nan. + :param dtype: specify the output dtype. Default is `float64`. + + Returns: + Rasterized xarray.DataArray. + + Notes: + When any of `res`, `out_shape`, or `extent` is not provided, it is inferred from the other arguments when applicable. + Unless `extent` is specified, a half-pixel buffer is applied to avoid missing points on the border. + The logics dictating the final spatial properties of the rasterized geometries follow those of GDAL. + + If `field` is not in `gdf`, then a default `burn` value of 1 is rasterized. + + A `None` value for `dtype` corresponds to the default of that dtype. An illegal value for a dtype will be replaced with the default of + that dtype. For example, a `background=np.nan` for `dtype="uint8"` will become `background=0`, where `0` is the default for `uint8`. + """ + # type checks + if not isinstance(gdf, GeoDataFrame): + raise TypeError("`gdf` must be a geopandas dataframe.") + if not isinstance(res, (tuple, list, NoneType)): + raise TypeError("`resolution` must be a tuple or list of (x, y).") + if not isinstance(out_shape, (tuple, list, NoneType)): + raise TypeError("`out_shape` must be a tuple or list of (nrows, ncols).") + if not isinstance(extent, (tuple, list, NoneType)): + raise TypeError("`extent` must be a tuple or list of (xmin, ymin, xmax, ymax).") + if not isinstance(field, (str, NoneType)): + raise TypeError("`field` must be a string column name.") + if not isinstance(by, (str, NoneType)): + raise TypeError("`by` must be a string column name.") + if not isinstance(burn, (int, float, NoneType)): + raise TypeError("`burn` must be an integer or float.") + if not isinstance(fun, str): + raise TypeError("`pixel_fn` must be one of sum, first, last, min, max, count, or any.") + if not isinstance(background, (int, float, NoneType)): + raise TypeError("`background` must be integer, float, or None.") + if not isinstance(dtype, str): + raise TypeError("`dtype` must be a one of uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64") + + # value checks + if not res and not out_shape and not extent: + raise ValueError("One of `res`, `out_shape`, or `extent` must be provided.") + if extent and not res and not out_shape: + raise ValueError("Must also specify `res` or `out_shape` with extent.") + if res and (len(res) != 2 or any(r <= 0 for r in res) or any(not isinstance(r, (int, float)) for r in res)): + raise ValueError("Resolution must be 2 positive numbers.") + if out_shape and (len(out_shape) != 2 or any(s <= 0 for s in out_shape) or any(not isinstance(s, int) for s in out_shape)): + raise ValueError("Output shape must be 2 positive integers.") + if extent and len(extent) != 4: + raise ValueError("Extent must be 4 numbers (xmin, ymin, xmax, ymax).") + if field and burn: + raise ValueError("Only one of `field` or `burn` can be specified.") + + # defaults + _res = res if res else (0, 0) + _shape = out_shape if out_shape else (0, 0) + (_bounds, _has_extent) = (extent, True) if extent else (gdf.total_bounds, False) + + # RasterInfo + raster_info = { + "nrows": _shape[0], + "ncols": _shape[1], + "xmin": _bounds[0], + "ymin": _bounds[1], + "xmax": _bounds[2], + "ymax": _bounds[3], + "xres": _res[0], + "yres": _res[1], + "has_extent": _has_extent, + } + + # extract columns of interest and convert to polars + cols = list(set([col for col in (field, by) if col])) + try: + df = pl.from_pandas(gdf[cols]) if cols else None + except KeyError as e: + raise KeyError("Column not found in GeoDataFrame") from e + + # rusterize + r = _rusterize(gdf.geometry, raster_info, fun, df, field, by, burn, background, dtype) + return DataArray.from_dict(r).rio.write_crs(gdf.crs, inplace=True) diff --git a/python/rusterize/core.py b/python/rusterize/core.py deleted file mode 100644 index a504abb..0000000 --- a/python/rusterize/core.py +++ /dev/null @@ -1,107 +0,0 @@ -from __future__ import annotations - -from types import NoneType -from typing import Any, Dict, Tuple - -import polars as pl -from geopandas import GeoDataFrame -import rioxarray -from xarray import DataArray -from .rusterize import _rusterize - - -def rusterize(gdf: GeoDataFrame, - res: Tuple[int, ...] | Tuple[float, ...] | None = None, - out_shape: Tuple[int, ...] | None = None, - extent: Tuple[int, ...] | Tuple[float, ...] | None = None, - field: str | None = None, - by: str | None = None, - fun: str = "last", - background: int | float | None = None, - ) -> Dict[str, Any]: - """ - Fast geopandas rasterization into xarray.DataArray - - Args: - :param gdf: geopandas dataframe to rasterize. - :param res: tuple of (xres, yres) for rasterized data. - :param out_shape: tuple of (nrows, ncols) for regularized output shape. - :param extent: tuple of (xmin, xmax, ymin, ymax) for regularized extent. - :param field: field to rasterize. Default is None. - :param by: column to rasterize, assigns each unique value to a layer in the stack based on field. Default is None. - :param fun: pixel function to use. Available options are `sum`, `first`, `last`, `min`, `max`, `count`, or `any`. Default is `last`. - :param background: background value in final raster. Default is None (NaN). - - Returns: - Rasterized xarray.DataArray. - - Note: - When any of `res`, `out_shape`, or `extent` is not provided, it is inferred from the other arguments when applicable. - Unless `extent` is specified, a half-pixel buffer is applied to avoid missing points on the border. - The logics dictating the final spatial properties of the rasterized geometries follow those of GDAL. - """ - # type checks - if not isinstance(gdf, GeoDataFrame): - raise TypeError("Must pass a valid geopandas dataframe.") - if not isinstance(res, (tuple, NoneType)): - raise TypeError("Must pass a valid resolution tuple (x, y).") - if not isinstance(out_shape, (tuple, NoneType)): - raise TypeError("Must pass a valid output shape tuple (nrows, ncols).") - if not isinstance(extent, (tuple, NoneType)): - raise TypeError("Must pass a valid extent tuple (xmin, ymin, xmax, ymax).") - if not isinstance(field, (str, NoneType)): - raise TypeError("Must pass a valid string to field.") - if not isinstance(by, (str, NoneType)): - raise TypeError("Must pass a valid string to by.") - if not isinstance(fun, str): - raise TypeError("Must pass a valid string to pixel_fn. Select one of sum, first, last, min, max, count, or any.") - if not isinstance(background, (int, float, NoneType)): - raise TypeError("Must pass a valid background type.") - - # value checks - if not res and not out_shape and not extent: - raise ValueError("One of `res`, `out_shape`, or `extent` must be provided.") - if extent and not res and not out_shape: - raise ValueError("Must also specify `res` or `out_shape` with extent.") - if res and (len(res) != 2 or any(r <= 0 for r in res) or any(not isinstance(r, (int, float)) for r in res)): - raise ValueError("Resolution must be 2 positive numbers.") - if out_shape and (len(out_shape) != 2 or any(s <= 0 for s in out_shape) or any(not isinstance(s, int) for s in out_shape)): - raise ValueError("Output shape must be 2 positive integers.") - if extent and len(extent) != 4: - raise ValueError("Extent must be 4 numbers (xmin, ymin, xmax, ymax).") - if by and not field: - raise ValueError("If `by` is specified, `field` must also be specified.") - - # defaults - _res = res if res else (0, 0) - _shape = out_shape if out_shape else (0, 0) - (_bounds, has_extent) = (extent, True) if extent else (gdf.total_bounds, False) - - # RasterInfo - raster_info = { - "nrows": _shape[0], - "ncols": _shape[1], - "xmin": _bounds[0], - "ymin": _bounds[1], - "xmax": _bounds[2], - "ymax": _bounds[3], - "xres": _res[0], - "yres": _res[1], - "has_extent": has_extent - } - - # extract columns of interest and convert to polars - cols = list(set([col for col in (field, by) if col])) - df = pl.from_pandas(gdf[cols]) if cols else None - - # rusterize - r = _rusterize( - gdf.geometry, - raster_info, - fun, - df, - field, - by, - background - ) - return DataArray.from_dict(r).rio.write_crs(gdf.crs, inplace=True) \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 25282ae..bcc0268 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly-2025-01-05" +channel = "nightly-2025-07-31" diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..c3c8c37 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +imports_granularity = "Crate" diff --git a/src/edge_collection.rs b/src/edge_collection.rs index 1e5a35d..885d7e4 100644 --- a/src/edge_collection.rs +++ b/src/edge_collection.rs @@ -1,60 +1,67 @@ /* Build structured edge collection from a single (multi)polygon or (multi)linestring. -If multi, then iterates over each inner geometry. +If multi or GeometryCollection, then iterates over each inner geometry. From the Geometry, the values are extracted and reconstructed as an array of nodes. */ -use crate::structs::edge::{EdgeCollection, LineEdge, PolyEdge}; -use crate::structs::raster::RasterInfo; +use crate::structs::{ + edge::{EdgeCollection, LineEdge, PolyEdge}, + raster::RasterInfo, +}; use geo::prelude::*; use geo_types::{Geometry, LineString}; use numpy::ndarray::Array2; pub fn build_edges(geom: &Geometry, raster_info: &RasterInfo) -> EdgeCollection { - match geom { - // polygon - Geometry::Polygon(polygon) => { - let mut polyedges: Vec = Vec::new(); - // handle exterior polygon - process_ring(&mut polyedges, polygon.exterior(), raster_info); - // handle interior polygons (if any) - for hole in polygon.interiors() { - process_ring(&mut polyedges, hole, raster_info); + let mut edges = EdgeCollection::Empty; + let mut stack = vec![geom]; + + while let Some(current_geom) = stack.pop() { + match current_geom { + Geometry::GeometryCollection(collection) => { + // push geometries back to stack + for inner in collection { + stack.push(inner); + } } - EdgeCollection::PolyEdges(polyedges) - } - // multipolygon - iterate over each inner polygon - Geometry::MultiPolygon(multipolygon) => { - let mut polyedges: Vec = Vec::new(); - for polygon in multipolygon { - // handle exterior polygon + Geometry::Polygon(polygon) => { + let mut polyedges: Vec = Vec::new(); process_ring(&mut polyedges, polygon.exterior(), raster_info); - // handle interior polygons (if any) + // process holes in geometry for hole in polygon.interiors() { process_ring(&mut polyedges, hole, raster_info); } + edges.add_polyedges(polyedges); } - EdgeCollection::PolyEdges(polyedges) - } - // linestring - Geometry::LineString(line) => { - let mut linedges: Vec = Vec::new(); - // handle single segment - process_line(&mut linedges, line, raster_info); - EdgeCollection::LineEdges(linedges) - } - // multilinestring - iterate over each inner linestring - Geometry::MultiLineString(multiline) => { - let mut linedges: Vec = Vec::new(); - // handle multiple segments - for line in multiline { + Geometry::MultiPolygon(multipolygon) => { + let mut polyedges: Vec = Vec::new(); + for polygon in multipolygon { + process_ring(&mut polyedges, polygon.exterior(), raster_info); + // process holes in geometry + for hole in polygon.interiors() { + process_ring(&mut polyedges, hole, raster_info); + } + } + edges.add_polyedges(polyedges); + } + Geometry::LineString(line) => { + let mut linedges: Vec = Vec::new(); process_line(&mut linedges, line, raster_info); + edges.add_linedges(linedges); } - EdgeCollection::LineEdges(linedges) + Geometry::MultiLineString(multiline) => { + let mut linedges: Vec = Vec::new(); + for line in multiline { + process_line(&mut linedges, line, raster_info); + } + edges.add_linedges(linedges); + } + _ => (), } - _ => unimplemented!("Unsupported geometry type."), } + + edges } fn build_node_array(line: &LineString) -> Array2 { diff --git a/src/geom/validate.rs b/src/geom/validate.rs index 80f78ac..68afbf6 100644 --- a/src/geom/validate.rs +++ b/src/geom/validate.rs @@ -43,7 +43,7 @@ pub fn validate_geometries( ) -> (Vec, Option) { // check if any bad geometry let mut good_geom: Vec = Vec::with_capacity(geometry.len()); - let mut has_invalid = false; + let mut has_invalid = 0u32; for geom in &geometry { let valid = matches!( geom, @@ -51,21 +51,24 @@ pub fn validate_geometries( | &Geometry::MultiPolygon(_) | &Geometry::LineString(_) | &Geometry::MultiLineString(_) + | &Geometry::GeometryCollection(_) ); if !valid { - has_invalid = true; + has_invalid += 1; } good_geom.push(valid); } - if has_invalid { + if has_invalid > 0 { // issue warning if bad geometries Python::with_gil(|py| { let warnings = Python::import(py, "warnings").unwrap(); warnings .call_method1( "warn", - ("Detected unsupported geometries, will be dropped.",), + (format!( + "Detected {has_invalid} unsupported geometries, will be dropped." + ),), ) .unwrap(); }); diff --git a/src/lib.rs b/src/lib.rs index 03ebb7f..2395be0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(extract_if)] - mod allocator; mod structs { pub mod edge; @@ -11,168 +9,70 @@ mod geom { } mod edge_collection; mod pixel_functions; -mod rasterize; +mod prelude; +mod rasterize_geometry; +mod rusterize_impl; mod to_xarray; -use crate::geom::{from_shapely::from_shapely, validate::validate_geometries}; -use crate::pixel_functions::{PixelFn, set_pixel_function}; -use crate::rasterize::rasterize; -use geo_types::Geometry; -use numpy::{ - IntoPyArray, - ndarray::{ - parallel::prelude::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}, - {Array3, Axis}, - }, +use crate::{ + geom::from_shapely::from_shapely, pixel_functions::set_pixel_function, prelude::*, + rusterize_impl::rusterize_impl, }; -use polars::prelude::*; +use geo_types::Geometry; +use num_traits::Num; +use numpy::Element; +use polars::prelude::DataFrame; use pyo3::{ prelude::*, - types::{PyAny, PyDict, PyList}, + types::{PyAny, PyDict}, }; use pyo3_polars::PyDataFrame; use structs::raster::RasterInfo; use to_xarray::build_xarray; -fn rusterize_rust( +#[allow(clippy::too_many_arguments)] +fn execute_rusterize<'py, T>( + py: Python<'py>, geometry: Vec, - raster_info: &mut RasterInfo, - pixel_fn: PixelFn, - background: f64, + mut raster_info: RasterInfo, + pypixel_fn: &str, + pybackground: Option<&Bound<'py, PyAny>>, df: Option, - field_name: Option<&str>, - by_name: Option<&str>, -) -> (Array3, Vec) { - // validate geometries - let (good_geom, df) = validate_geometries(geometry, df, raster_info); - - // extract `field` and `by` - let casted: DataFrame; - let (field, by) = match df { - None => ( - // case 1: create a dummy `field` - &Float64Chunked::from_vec(PlSmallStr::from("field_f64"), vec![1.0; good_geom.len()]), - None, - ), - Some(df) => { - let mut lf = df.lazy(); - match (field_name, by_name) { - (Some(field_name), Some(by_name)) => { - // case 2: both `field` and `by` specified - lf = lf.with_columns([ - col(field_name).cast(DataType::Float64).alias("field_f64"), - col(by_name).cast(DataType::String).alias("by_str"), - ]); - } - (Some(field_name), None) => { - // case 3: only `field` specified - lf = lf.with_column(col(field_name).cast(DataType::Float64).alias("field_f64")); - } - (None, Some(by_name)) => { - // case 4: only `by` specified - lf = lf.with_columns([ - lit(1.0).alias("field_f64"), // dummy `field` - col(by_name).cast(DataType::String).alias("by_str"), - ]); - } - (None, None) => { - // case 5: neither `field` nor `by` specified - panic!("Either `field` or `by` must be specified."); - } - } - - // collect casted dataframe - casted = lf.collect().unwrap(); - - ( - casted.column("field_f64").unwrap().f64().unwrap(), - casted.column("by_str").ok().and_then(|col| col.str().ok()), - ) - } - }; - - // main - let mut raster: Array3; - let mut band_names: Vec = vec![String::from("band1")]; - match by { - Some(by) => { - // get groups - let groups = by.group_tuples(true, false).expect("No groups found!"); - let n_groups = groups.len(); - let group_idx = groups.into_idx(); - - // multiband raster - raster = raster_info.build_raster(n_groups, background); - - // dynamically set number of threads - let cpus = num_cpus::get(); - let num_threads = n_groups.min(cpus / 2); - - // init thread pool - let pool = rayon::ThreadPoolBuilder::new() - .num_threads(num_threads) - .build() - .unwrap(); - - // parallel iterator along bands, zipped with corresponding groups - pool.install(|| { - raster - .outer_iter_mut() - .into_par_iter() - .zip(group_idx.into_par_iter()) - .map(|(mut band, (group_idx, idxs))| { - // rasterize polygons - for &i in idxs.iter() { - if let (Some(fv), Some(geom)) = - (field.get(i as usize), good_geom.get(i as usize)) - { - // process only non-empty field values - rasterize( - raster_info, - geom, - &fv, - &mut band, - &pixel_fn, - &background, - ); - } - } - // band name - by.get(group_idx as usize).unwrap().to_string() - }) - .collect_into_vec(&mut band_names) - }); - } - None => { - // singleband raster - raster = raster_info.build_raster(1, background); + pyfield: Option<&str>, + pyby: Option<&str>, + pyburn: Option<&Bound<'py, PyAny>>, +) -> PyResult> +where + T: Num + Copy + PixelOps + PolarsHandler + FromPyObject<'py> + Element + Default, +{ + let background = pybackground + .and_then(|inner| inner.extract::().ok()) + .unwrap_or_default(); + let burn = pyburn + .and_then(|inner| inner.extract::().ok()) + .unwrap_or(T::one()); + let pixel_fn = set_pixel_function::(pypixel_fn); - // rasterize polygons - field - .into_iter() - .zip(good_geom) - .for_each(|(field_value, geom)| { - if let Some(fv) = field_value { - // process only non-empty field values - rasterize( - raster_info, - &geom, - &fv, - &mut raster.index_axis_mut(Axis(0), 0), - &pixel_fn, - &background, - ) - } - }); - } - } + // rusterize + let (ret, band_names) = rusterize_impl::( + geometry, + &mut raster_info, + pixel_fn, + background, + df, + pyfield, + pyby, + burn, + ); - (raster, band_names) + // build xarray dictionary + let xarray = build_xarray(py, raster_info, ret, band_names)?; + Ok(xarray) } #[pyfunction] #[pyo3(name = "_rusterize")] -#[pyo3(signature = (pygeometry, pyinfo, pypixel_fn, pydf=None, pyfield=None, pyby=None, pybackground=None))] +#[pyo3(signature = (pygeometry, pyinfo, pypixel_fn, pydf=None, pyfield=None, pyby=None, pyburn=None, pybackground=None, pydtype="float64"))] #[allow(clippy::too_many_arguments)] fn rusterize_py<'py>( py: Python<'py>, @@ -182,45 +82,135 @@ fn rusterize_py<'py>( pydf: Option, pyfield: Option<&str>, pyby: Option<&str>, + pyburn: Option<&Bound<'py, PyAny>>, pybackground: Option<&Bound<'py, PyAny>>, + pydtype: &str, ) -> PyResult> { // extract dataframe - let df = pydf.map(|inner| inner.into()); + let df: Option = pydf.map(|inner| inner.into()); // parse geometries let geometry = from_shapely(py, pygeometry)?; // extract raster information - let mut raster_info = RasterInfo::from(pyinfo); - - // extract function arguments - let pixel_fn = set_pixel_function(pypixel_fn); - let background = pybackground - .and_then(|inner| inner.extract::().ok()) - .unwrap_or(f64::NAN); - - // rusterize - let (ret, band_names) = rusterize_rust( - geometry, - &mut raster_info, - pixel_fn, - background, - df, - pyfield, - pyby, - ); - - // construct coordinates - let (y_coords, x_coords) = raster_info.make_coordinates(py); - - // to python - let pyret = ret.into_pyarray(py); - let pybands = PyList::new(py, band_names)?; - let pydims = PyList::new(py, vec!["bands", "y", "x"])?; - - // build xarray dictionary - let xarray = build_xarray(py, pyret, pydims, x_coords, y_coords, pybands)?; - Ok(xarray) + let raster_info = RasterInfo::from(pyinfo); + + // branch + match pydtype { + "uint8" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "uint16" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "uint32" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "uint64" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "int8" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "int16" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "int32" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "int64" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "float32" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + "float64" => execute_rusterize::( + py, + geometry, + raster_info, + pypixel_fn, + pybackground, + df, + pyfield, + pyby, + pyburn, + ), + _ => unimplemented!( + "`dtype` must be a one of uint8, uint16, uint32, uint64, int8, int16, int32, int64, float32, float64" + ), + } } #[pymodule] diff --git a/src/pixel_functions.rs b/src/pixel_functions.rs index ec7ad4a..63452f6 100644 --- a/src/pixel_functions.rs +++ b/src/pixel_functions.rs @@ -1,13 +1,18 @@ /* On-demand functions for geometry rasterizetion. */ - +use crate::prelude::*; +use num_traits::Num; use numpy::ndarray::ArrayViewMut2; +use std::ops::AddAssign; -pub type PixelFn = fn(&mut ArrayViewMut2, usize, usize, &f64, &f64); +pub type PixelFn = fn(&mut ArrayViewMut2, usize, usize, &T, &T); // sum values or NaN/background -fn sum_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &f64, bg: &f64) { +fn sum_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &T, bg: &T) +where + T: Num + AddAssign + NaNAware + Copy, +{ if array[[y, x]].eq(bg) || array[[y, x]].is_nan() || value.is_nan() { array[[y, x]] = *value; } else { @@ -16,47 +21,68 @@ fn sum_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &f64, b } // set first value only if currently NaN/background -fn first_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &f64, bg: &f64) { +fn first_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &T, bg: &T) +where + T: Num + NaNAware + Copy, +{ if array[[y, x]].eq(bg) || array[[y, x]].is_nan() { array[[y, x]] = *value; } } // always set last value -fn last_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &f64, _bg: &f64) { +fn last_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &T, _bg: &T) +where + T: Num + Copy, +{ array[[y, x]] = *value; } // set value if smaller than current -fn min_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &f64, bg: &f64) { +fn min_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &T, bg: &T) +where + T: Num + NaNAware + PartialOrd + Copy, +{ if array[[y, x]].eq(bg) || array[[y, x]].is_nan() || array[[y, x]].gt(value) { array[[y, x]] = *value; } } // set value if larger than current -fn max_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &f64, bg: &f64) { +fn max_values(array: &mut ArrayViewMut2, y: usize, x: usize, value: &T, bg: &T) +where + T: Num + NaNAware + PartialOrd + Copy, +{ if array[[y, x]].eq(bg) || array[[y, x]].is_nan() || array[[y, x]].lt(value) { array[[y, x]] = *value; } } // count values at index -fn count_values(array: &mut ArrayViewMut2, y: usize, x: usize, _value: &f64, bg: &f64) { +fn count_values(array: &mut ArrayViewMut2, y: usize, x: usize, _value: &T, bg: &T) +where + T: Num + AddAssign + NaNAware + Copy, +{ if array[[y, x]].eq(bg) || array[[y, x]].is_nan() { - array[[y, x]] = 1.0; + array[[y, x]] = T::one(); } else { - array[[y, x]] += 1.0; + array[[y, x]] += T::one(); } } // mark value presence -fn any_values(array: &mut ArrayViewMut2, y: usize, x: usize, _value: &f64, _bg: &f64) { - array[[y, x]] = 1.0; +fn any_values(array: &mut ArrayViewMut2, y: usize, x: usize, _value: &T, _bg: &T) +where + T: Num, +{ + array[[y, x]] = T::one(); } // function call -pub fn set_pixel_function(fstr: &str) -> PixelFn { +pub fn set_pixel_function(fstr: &str) -> PixelFn +where + T: Num + Copy + PixelOps, +{ match fstr { "sum" => sum_values, "first" => first_values, @@ -66,8 +92,7 @@ pub fn set_pixel_function(fstr: &str) -> PixelFn { "count" => count_values, "any" => any_values, _ => panic!( - "'fun' has an invalid value: {}. Select one of sum, first, last, min, max, count, or any", - fstr + "'fun' has an invalid value: {fstr}. One of sum, first, last, min, max, count, or any", ), } } diff --git a/src/prelude.rs b/src/prelude.rs new file mode 100644 index 0000000..11139ea --- /dev/null +++ b/src/prelude.rs @@ -0,0 +1,116 @@ +/* +Traits to handle dtype runtime polymorphism + */ +use polars::prelude::*; +use std::ops::AddAssign; + +// handle polars dtypes and conversions +pub trait PolarsHandler: Literal + Send + Sync { + fn polars_dtype() -> DataType; + fn from_anyvalue(val: AnyValue) -> Option + where + Self: Sized; + fn into_column(self, len: usize) -> Column; +} + +macro_rules! impl_polars_handler { + ($($t:ty => { + dtype: $dtype:expr, + anyvalue: $anyvalue:pat => $extract:expr, + }),* $(,)?) => { + $( + impl PolarsHandler for $t { + fn polars_dtype() -> DataType { + $dtype + } + + fn from_anyvalue(val: AnyValue) -> Option { + match val { + $anyvalue => Some($extract), + _ => None, + } + } + + fn into_column(self, len: usize) -> Column { + Column::new("field_casted".into(), vec![self; len]) + } + } + )* + }; +} + +impl_polars_handler! { + f64 => { + dtype: DataType::Float64, + anyvalue: AnyValue::Float64(v) => v, + }, + f32 => { + dtype: DataType::Float32, + anyvalue: AnyValue::Float32(v) => v, + }, + u8 => { + dtype: DataType::UInt8, + anyvalue: AnyValue::UInt8(v) => v, + }, + i8 => { + dtype: DataType::Int8, + anyvalue: AnyValue::Int8(v) => v, + }, + u16 => { + dtype: DataType::UInt16, + anyvalue: AnyValue::UInt16(v) => v, + }, + i16 => { + dtype: DataType::Int16, + anyvalue: AnyValue::Int16(v) => v, + }, + u32 => { + dtype: DataType::UInt32, + anyvalue: AnyValue::UInt32(v) => v, + }, + i32 => { + dtype: DataType::Int32, + anyvalue: AnyValue::Int32(v) => v, + }, + u64 => { + dtype: DataType::UInt64, + anyvalue: AnyValue::UInt64(v) => v, + }, + i64 => { + dtype: DataType::Int64, + anyvalue: AnyValue::Int64(v) => v, + }, +} + +// handle NaN check for dtype that don't have it +pub trait NaNAware { + fn is_nan(&self) -> bool; +} + +impl NaNAware for f32 { + fn is_nan(&self) -> bool { + f32::is_nan(*self) + } +} + +impl NaNAware for f64 { + fn is_nan(&self) -> bool { + f64::is_nan(*self) + } +} + +macro_rules! impl_maybe_nan_for_int { + ($($t:ty),*) => { + $(impl NaNAware for $t { + fn is_nan(&self) -> bool { + false + } + })* + }; +} + +impl_maybe_nan_for_int!(u8, u16, u32, u64, i8, i16, i32, i64); + +// super trait to group all pixel operations +pub trait PixelOps: AddAssign + PartialOrd + NaNAware + Sized {} +impl PixelOps for T {} diff --git a/src/rasterize.rs b/src/rasterize.rs deleted file mode 100644 index 4a66f79..0000000 --- a/src/rasterize.rs +++ /dev/null @@ -1,114 +0,0 @@ -/* -Rasterize a single (multi)polygon or (multi)linestring. - */ - -use crate::edge_collection; -use crate::pixel_functions::PixelFn; -use crate::structs::{ - edge::{EdgeCollection, PolyEdge, less_by_x, less_by_ystart}, - raster::RasterInfo, -}; - -use edge_collection::build_edges; -use geo_types::Geometry; -use numpy::ndarray::ArrayViewMut2; -use rayon::prelude::*; - -pub fn rasterize( - raster_info: &RasterInfo, - geom: &Geometry, - field_value: &f64, - ndarray: &mut ArrayViewMut2, - pxfn: &PixelFn, - background: &f64, -) { - // build edge collection - let edges = build_edges(geom, raster_info); - - // early return if no edges - if edges.is_empty() { - return; - } - - // branch by geometry type - match edges { - EdgeCollection::PolyEdges(mut polyedges) => { - // sort edges - polyedges.par_sort_by(less_by_ystart); - - // start with first y line - let mut yline = polyedges.first().unwrap().ystart; - - // active edges - let mut active_edges: Vec = Vec::new(); - - // rasterize loop - let ncols = raster_info.ncols as f64; - while yline < raster_info.nrows && !(active_edges.is_empty() && polyedges.is_empty()) { - // transfer current edges to active edges - active_edges.extend( - polyedges.extract_if(.., |edge| edge.ystart <= yline), // experimental - ); - // sort active edges - active_edges.par_sort_by(less_by_x); - - // even-odd polygon fill - for (edge1, edge2) in active_edges - .iter() - .zip(active_edges.iter().skip(1)) - .step_by(2) - { - // clamp the x-coordinates of the edges - let xstart = edge1.x.clamp(0.0, ncols).ceil() as usize; - let xend = edge2.x.clamp(0.0, ncols).ceil() as usize; - - // fill the pixels between xstart and xend - for xpix in xstart..xend { - pxfn(ndarray, yline, xpix, field_value, background); - } - } - yline += 1; - - active_edges.retain_mut(|edge| { - if edge.yend <= yline { - // drop edges above horizontal line - false - } else { - // update x-position of the next intercepts of edges for the next row - edge.x += edge.dxdy; - true - } - }) - } - } - EdgeCollection::LineEdges(mut linedges) => { - let last_idx = linedges.len() - 1; - for (idx, edge) in linedges.iter_mut().enumerate() { - // rasterize all pixels except very last - while edge.ix0 != edge.ix1 || edge.iy0 != edge.iy1 { - let ix0 = edge.ix0 as usize; - let iy0 = edge.iy0 as usize; - pxfn(ndarray, iy0, ix0, field_value, background); - - // update the error term and coordinates - let e2 = 2 * edge.err; - if e2 >= edge.dy { - edge.err += edge.dy; - edge.ix0 += edge.sx; - } - if e2 <= edge.dx { - edge.err += edge.dx; - edge.iy0 += edge.sy; - } - } - - // rasterize last pixel if very last and geometry is not closed - if idx == last_idx && !edge.is_closed { - let ix0 = edge.ix0 as usize; - let iy0 = edge.iy0 as usize; - pxfn(ndarray, iy0, ix0, field_value, background); - } - } - } - } -} diff --git a/src/rasterize_geometry.rs b/src/rasterize_geometry.rs new file mode 100644 index 0000000..2ea4b0f --- /dev/null +++ b/src/rasterize_geometry.rs @@ -0,0 +1,153 @@ +/* +Rasterize a single (multi)polygon or (multi)linestring. + */ + +use crate::{ + edge_collection, + pixel_functions::PixelFn, + structs::{ + edge::{EdgeCollection, LineEdge, PolyEdge, less_by_x, less_by_ystart}, + raster::RasterInfo, + }, +}; + +use edge_collection::build_edges; +use geo_types::Geometry; +use num_traits::Num; +use numpy::ndarray::ArrayViewMut2; +use rayon::prelude::*; + +pub fn rasterize( + raster_info: &RasterInfo, + geom: &Geometry, + field_value: &T, + ndarray: &mut ArrayViewMut2, + pxfn: &PixelFn, + background: &T, +) { + // build edge collection + let edges = build_edges(geom, raster_info); + + match edges { + // early return if no edges + EdgeCollection::Empty => (), + EdgeCollection::PolyEdges(polyedges) => { + rasterize_polygon( + raster_info, + polyedges, + field_value, + ndarray, + pxfn, + background, + ); + } + EdgeCollection::LineEdges(linedges) => { + rasterize_line(linedges, field_value, ndarray, pxfn, background); + } + EdgeCollection::Mixed { + polyedges, + linedges, + } => { + rasterize_polygon( + raster_info, + polyedges, + field_value, + ndarray, + pxfn, + background, + ); + rasterize_line(linedges, field_value, ndarray, pxfn, background); + } + } +} + +fn rasterize_polygon( + raster_info: &RasterInfo, + mut polyedges: Vec, + field_value: &T, + ndarray: &mut ArrayViewMut2, + pxfn: &PixelFn, + background: &T, +) { + // sort edges + polyedges.par_sort_by(less_by_ystart); + + // start with first y line + let mut yline = polyedges.first().unwrap().ystart; + + // active edges + let mut active_edges = Vec::new(); + + // rasterize loop + let ncols = raster_info.ncols as f64; + while yline < raster_info.nrows && !(active_edges.is_empty() && polyedges.is_empty()) { + // transfer current edges to active edges + active_edges.extend(polyedges.extract_if(.., |edge| edge.ystart <= yline)); + // sort active edges + active_edges.par_sort_by(less_by_x); + + // even-odd polygon fill + for (edge1, edge2) in active_edges + .iter() + .zip(active_edges.iter().skip(1)) + .step_by(2) + { + // clamp the x-coordinates of the edges + let xstart = edge1.x.clamp(0.0, ncols).ceil() as usize; + let xend = edge2.x.clamp(0.0, ncols).ceil() as usize; + + // fill the pixels between xstart and xend + for xpix in xstart..xend { + pxfn(ndarray, yline, xpix, field_value, background); + } + } + yline += 1; + + active_edges.retain_mut(|edge| { + if edge.yend <= yline { + // drop edges above horizontal line + false + } else { + // update x-position of the next intercepts of edges for the next row + edge.x += edge.dxdy; + true + } + }) + } +} + +fn rasterize_line( + mut linedges: Vec, + field_value: &T, + ndarray: &mut ArrayViewMut2, + pxfn: &PixelFn, + background: &T, +) { + let last_idx = linedges.len() - 1; + for (idx, edge) in linedges.iter_mut().enumerate() { + // rasterize all pixels except very last + while edge.ix0 != edge.ix1 || edge.iy0 != edge.iy1 { + let ix0 = edge.ix0 as usize; + let iy0 = edge.iy0 as usize; + pxfn(ndarray, iy0, ix0, field_value, background); + + // update the error term and coordinates + let e2 = 2 * edge.err; + if e2 >= edge.dy { + edge.err += edge.dy; + edge.ix0 += edge.sx; + } + if e2 <= edge.dx { + edge.err += edge.dx; + edge.iy0 += edge.sy; + } + } + + // rasterize last pixel if very last and geometry is not closed + if idx == last_idx && !edge.is_closed { + let ix0 = edge.ix0 as usize; + let iy0 = edge.iy0 as usize; + pxfn(ndarray, iy0, ix0, field_value, background); + } + } +} diff --git a/src/rusterize_impl.rs b/src/rusterize_impl.rs new file mode 100644 index 0000000..68814da --- /dev/null +++ b/src/rusterize_impl.rs @@ -0,0 +1,139 @@ +/* +Implementation of rusterize +*/ +use crate::{ + geom::validate::validate_geometries, pixel_functions::PixelFn, prelude::PolarsHandler, + rasterize_geometry::rasterize, structs::raster::RasterInfo, +}; +use geo_types::Geometry; +use ndarray::{Array3, Axis}; +use num_traits::Num; +use polars::prelude::*; +use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; + +#[allow(clippy::too_many_arguments)] +pub fn rusterize_impl( + geometry: Vec, + raster_info: &mut RasterInfo, + pixel_fn: PixelFn, + background: T, + df: Option, + field_name: Option<&str>, + by_name: Option<&str>, + burn_value: T, +) -> (Array3, Vec) +where + T: Num + Copy + PolarsHandler + Literal + Send + Sync, +{ + // validate geometries + let (good_geom, df) = validate_geometries(geometry, df, raster_info); + + // extract `field` and `by` + let casted: DataFrame; + let (field, by) = match df { + None => ( + // case 1: create a dummy `field` + &burn_value.into_column(good_geom.len()), + None, + ), + Some(df) => { + let mut lf = df.lazy(); + match (field_name, by_name) { + (Some(field_name), Some(by_name)) => { + // case 2: both `field` and `by` specified + lf = lf.with_columns([ + col(field_name) + .cast(T::polars_dtype()) + .alias("field_casted"), + col(by_name).cast(DataType::String).alias("by_str"), + ]); + } + (Some(field_name), None) => { + // case 3: only `field` specified + lf = lf.with_column( + col(field_name) + .cast(T::polars_dtype()) + .alias("field_casted"), + ); + } + (None, Some(by_name)) => { + // case 4: only `by` specified + lf = lf.with_columns([ + lit(burn_value).alias("field_casted"), // dummy `field` + col(by_name).cast(DataType::String).alias("by_str"), + ]); + } + (None, None) => { + // case 5: neither `field` nor `by` specified + lf = lf.with_columns([lit(burn_value).alias("field_casted")]) + } + } + + // collect casted dataframe + casted = lf.collect().unwrap(); + + ( + casted.column("field_casted").unwrap(), + casted.column("by_str").ok().and_then(|col| col.str().ok()), + ) + } + }; + + // main + let mut raster: Array3; + let mut band_names: Vec = vec![String::from("band1")]; + match by { + Some(by) => { + // get groups + let groups = by.group_tuples(true, false).expect("No groups found!"); + let n_groups = groups.len(); + let group_idx = groups.into_idx(); + + // multiband raster + raster = raster_info.build_raster(n_groups, background); + raster + .outer_iter_mut() + .into_par_iter() + .zip(group_idx.into_par_iter()) + .map(|(mut band, (group_idx, idxs))| { + // rasterize polygons + for &i in idxs.iter() { + if let (Some(fv), Some(geom)) = { + let anyvalue = field.get(i as usize).unwrap(); + (T::from_anyvalue(anyvalue), good_geom.get(i as usize)) + } { + // process only non-empty field values + rasterize(raster_info, geom, &fv, &mut band, &pixel_fn, &background); + } + } + // band name + by.get(group_idx as usize).unwrap().to_string() + }) + .collect_into_vec(&mut band_names) + } + None => { + // singleband raster + raster = raster_info.build_raster(1, background); + + // rasterize polygons + field + .phys_iter() + .zip(good_geom) + .for_each(|(field_value, geom)| { + if let Some(fv) = T::from_anyvalue(field_value) { + // process only non-empty field values + rasterize( + raster_info, + &geom, + &fv, + &mut raster.index_axis_mut(Axis(0), 0), + &pixel_fn, + &background, + ) + } + }); + } + } + + (raster, band_names) +} diff --git a/src/structs/edge.rs b/src/structs/edge.rs index 5ca25c9..8e9fb72 100644 --- a/src/structs/edge.rs +++ b/src/structs/edge.rs @@ -7,15 +7,51 @@ use std::cmp::Ordering; // collection of edges pub enum EdgeCollection { + Empty, PolyEdges(Vec), LineEdges(Vec), + Mixed { + polyedges: Vec, + linedges: Vec, + }, } impl EdgeCollection { - pub fn is_empty(&self) -> bool { + pub fn add_polyedges(&mut self, new_polyedges: Vec) { + if new_polyedges.is_empty() { + return; + } + match self { + EdgeCollection::Empty => *self = EdgeCollection::PolyEdges(new_polyedges), + EdgeCollection::PolyEdges(polyedges) => polyedges.extend(new_polyedges), + EdgeCollection::LineEdges(linedges) => { + *self = { + EdgeCollection::Mixed { + polyedges: new_polyedges, + linedges: std::mem::take(linedges), + } + } + } + EdgeCollection::Mixed { polyedges, .. } => polyedges.extend(new_polyedges), + } + } + + pub fn add_linedges(&mut self, new_linedges: Vec) { + if new_linedges.is_empty() { + return; + } match self { - EdgeCollection::PolyEdges(poly_edges) => poly_edges.is_empty(), - EdgeCollection::LineEdges(line_edges) => line_edges.is_empty(), + EdgeCollection::Empty => *self = EdgeCollection::LineEdges(new_linedges), + EdgeCollection::PolyEdges(polyedges) => { + *self = { + EdgeCollection::Mixed { + polyedges: std::mem::take(polyedges), + linedges: new_linedges, + } + } + } + EdgeCollection::LineEdges(linedges) => linedges.extend(new_linedges), + EdgeCollection::Mixed { linedges, .. } => linedges.extend(new_linedges), } } } diff --git a/src/structs/raster.rs b/src/structs/raster.rs index ff9145a..6675b1d 100644 --- a/src/structs/raster.rs +++ b/src/structs/raster.rs @@ -3,6 +3,7 @@ Structure to contain information on raster data. */ use geo::Rect; +use num_traits::Num; use numpy::{ IntoPyArray, PyArray1, ndarray::{Array, Array3}, @@ -71,7 +72,10 @@ impl RasterInfo { self.ymax = rect.max().y; } - pub fn build_raster(&self, bands: usize, background: f64) -> Array3 { + pub fn build_raster(&self, bands: usize, background: T) -> Array3 + where + T: Num + Copy, + { Array3::from_elem((bands, self.nrows, self.ncols), background) } diff --git a/src/to_xarray.rs b/src/to_xarray.rs index bd32335..b5a747e 100644 --- a/src/to_xarray.rs +++ b/src/to_xarray.rs @@ -1,22 +1,29 @@ /* Build dictionary for xarray construction. -In some cases Python will build a xarray without copying the Rust array. */ - -use numpy::{PyArray1, PyArray3}; +use crate::structs::raster::RasterInfo; +use ndarray::Array3; +use num_traits::Num; +use numpy::{Element, IntoPyArray}; use pyo3::{ prelude::*, types::{PyDict, PyList}, }; -pub fn build_xarray<'py>( - py: Python<'py>, - data: Bound<'py, PyArray3>, - dims: Bound<'py, PyList>, - x: Bound<'py, PyArray1>, - y: Bound<'py, PyArray1>, - bands: Bound<'py, PyList>, -) -> PyResult> { +pub fn build_xarray( + py: Python, + raster_info: RasterInfo, + ret: Array3, + band_names: Vec, +) -> PyResult> +where + T: Num + Element, +{ + let data = ret.into_pyarray(py); + let (y, x) = raster_info.make_coordinates(py); + let bands = PyList::new(py, band_names)?; + let dims = PyList::new(py, vec!["bands", "y", "x"])?; + // dimensions let dim_x = PyDict::new(py); dim_x.set_item("dims", "x")?;