diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 453e1c95..2ee0a09d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -35,6 +35,35 @@ jobs: target/i686-win7-windows-msvc/release/rust_g.dll target/i686-win7-windows-msvc/release/rust_g.pdb target/rust_g.dm + + build-windows-x64: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@nightly + with: + targets: x86_64-pc-windows-msvc + components: clippy, rustfmt, rust-src + + - uses: Swatinem/rust-cache@v2 + + - name: x64 Clippy (all features) + run: cargo clippy -Z build-std --target x86_64-pc-windows-msvc --features all,allow_non_32bit --locked -- -D warnings + + - name: Rustfmt + run: cargo fmt -- --check + + - name: x64 Build (release) (default features) + run: cargo build -Z build-std --target x86_64-pc-windows-msvc --features allow_non_32bit --locked --release + + - uses: actions/upload-artifact@v4 + with: + name: Windows Build x64 + path: | + target/x86_64-pc-windows-msvc/release/rust_g.dll + target/x86_64-pc-windows-msvc/release/rust_g.pdb + target/rust_g.dm build-linux: runs-on: ubuntu-latest @@ -54,7 +83,7 @@ jobs: - uses: dtolnay/rust-toolchain@nightly with: - targets: i686-unknown-linux-gnu + targets: i686-unknown-linux-gnu, x86_64-unknown-linux-gnu - uses: Swatinem/rust-cache@v2 @@ -78,3 +107,41 @@ jobs: path: | target/i686-unknown-linux-gnu/release/librust_g.so target/rust_g.dm + + build-linux-x64: + runs-on: ubuntu-latest + env: + BYOND_MAJOR: 515 + BYOND_MINOR: 1642 + PKG_CONFIG_ALLOW_CROSS: 1 + + steps: + - uses: actions/checkout@v4 + + - run: | + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install libgcc-s1:i386 g++-multilib zlib1g-dev:i386 + ./scripts/install_byond.sh + + - uses: dtolnay/rust-toolchain@nightly + with: + targets: x86_64-unknown-linux-gnu + + - uses: Swatinem/rust-cache@v2 + + - name: x64 Check (all features) + run: cargo check --target x86_64-unknown-linux-gnu --locked --features all,allow_non_32bit + + - name: x64 Build (Debug) (all features) + run: cargo build --target x86_64-unknown-linux-gnu --locked --features all,allow_non_32bit + + - name: x64 Build (release) (default features) + run: cargo build --target x86_64-unknown-linux-gnu --locked --features allow_non_32bit --release + + - uses: actions/upload-artifact@v4 + with: + name: Linux Build x64 + path: | + target/x86_64-unknown-linux-gnu/release/librust_g.so + target/rust_g.dm diff --git a/Cargo.lock b/Cargo.lock index 6f51e9e5..5fc490fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,9 +60,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "ammonia" @@ -127,9 +127,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bigdecimal" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f850665a0385e070b64c38d2354e6c104c8479c59868d1e48a0c13ee2c7a1c1" +checksum = "7f31f3af01c5c65a07985c804d3366560e6fa7883d640a122819b14ec327482c" dependencies = [ "autocfg", "libm", @@ -140,20 +140,20 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.70.1" +version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "cexpr", "clang-sys", "itertools", "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash", "shlex", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -164,9 +164,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bitvec" @@ -191,9 +191,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" dependencies = [ "borsh-derive", "cfg_aliases", @@ -201,22 +201,22 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" +checksum = "f8b668d39970baad5356d7c83a86fee3a539e6f93bf6764c97368243e17a0487" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "bstr" -version = "1.11.0" +version = "1.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" dependencies = [ "memchr", "regex-automata", @@ -268,9 +268,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" [[package]] name = "byteorder" @@ -286,9 +286,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "bzip2" @@ -313,9 +313,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.1" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "jobserver", "libc", @@ -345,9 +345,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -386,9 +386,9 @@ checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" [[package]] name = "cmake" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" +checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" dependencies = [ "cc", ] @@ -493,18 +493,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -521,18 +521,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -571,7 +571,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -582,7 +582,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -638,7 +638,7 @@ dependencies = [ "proc-macro2", "quote", "semver", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -658,18 +658,18 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "derive_utils" -version = "0.14.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f152f4b8559c4da5d574bafc7af85454d706b4c5fe8b530d508cacbb6807ea" +checksum = "ccfae181bab5ab6c5478b2ccb69e4c68a02f8c3ec72f6616bfec9dbc599d2ee0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -691,7 +691,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -700,7 +700,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91bec4fbd086174ce996af5c8d10074f63c82b4a1aa517fd40e2d812cd75f734" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "deflate", "image", "inflate", @@ -736,12 +736,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -772,15 +772,15 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -828,9 +828,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" [[package]] name = "foreign-types" @@ -885,7 +885,7 @@ checksum = "e99b8b3c28ae0e84b604c75f721c21dc77afb3706076af5e8216d15fd1deaae3" dependencies = [ "frunk_proc_macro_helpers", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -897,7 +897,7 @@ dependencies = [ "frunk_core", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -909,7 +909,7 @@ dependencies = [ "frunk_core", "frunk_proc_macro_helpers", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -965,9 +965,9 @@ dependencies = [ [[package]] name = "gix" -version = "0.67.0" +version = "0.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d3e78ddac368d3e3bfbc2862bc2aafa3d89f1b15fed898d9761e1ec6f3f17f" +checksum = "736f14636705f3a56ea52b553e67282519418d9a35bb1e90b3a9637a00296b68" dependencies = [ "gix-actor", "gix-commitgraph", @@ -986,11 +986,13 @@ dependencies = [ "gix-odb", "gix-pack", "gix-path", + "gix-protocol", "gix-ref", "gix-refspec", "gix-revision", "gix-revwalk", "gix-sec", + "gix-shallow", "gix-tempfile", "gix-trace", "gix-traverse", @@ -999,60 +1001,72 @@ dependencies = [ "gix-validate", "once_cell", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-actor" -version = "0.33.0" +version = "0.33.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59226ef06661c756e664b46b1d3b2c198f6adc5407a484c086d0171108a70027" +checksum = "20018a1a6332e065f1fcc8305c1c932c6b8c9985edea2284b3c79dc6fa3ee4b2" dependencies = [ "bstr", "gix-date", "gix-utils", "itoa", - "thiserror 1.0.69", + "thiserror 2.0.11", "winnow", ] [[package]] name = "gix-bitmap" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f78312288bd02052be5dbc2ecbc342c9f4eb791986d86c0a5c06b92dc72efa" +checksum = "b1db9765c69502650da68f0804e3dc2b5f8ccc6a2d104ca6c85bc40700d37540" dependencies = [ - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-chunk" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c28b58ba04f0c004722344390af9dbc85888fbb84be1981afb934da4114d4cf" +checksum = "0b1f1d8764958699dc764e3f727cef280ff4d1bd92c107bbf8acd85b30c1bd6f" dependencies = [ - "thiserror 1.0.69", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-command" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb410b84d6575db45e62025a9118bdbf4d4b099ce7575a76161e898d9ca98df1" +dependencies = [ + "bstr", + "gix-path", + "gix-trace", + "shell-words", ] [[package]] name = "gix-commitgraph" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41db900b189e62dc61575f06fdf1a3b6901d264a99be9d32b286af6b2e3984e1" +checksum = "e23a8ec2d8a16026a10dafdb6ed51bcfd08f5d97f20fa52e200bc50cb72e4877" dependencies = [ "bstr", "gix-chunk", "gix-features", "gix-hash", "memmap2", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-config" -version = "0.41.0" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bedd1bf1c7b994be9d57207e8e0de79016c05e2e8701d3015da906e65ac445e" +checksum = "377c1efd2014d5d469e0b3cd2952c8097bce9828f634e04d5665383249f1d9e9" dependencies = [ "bstr", "gix-config-value", @@ -1064,53 +1078,53 @@ dependencies = [ "memchr", "once_cell", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", "unicode-bom", "winnow", ] [[package]] name = "gix-config-value" -version = "0.14.9" +version = "0.14.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3de3fdca9c75fa4b83a76583d265fa49b1de6b088ebcd210749c24ceeb74660" +checksum = "11365144ef93082f3403471dbaa94cfe4b5e72743bdb9560719a251d439f4cee" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "bstr", "gix-path", "libc", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-date" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d10d543ac13c97292a15e8e8b7889cd006faf739777437ed95362504b8fe81a0" +checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f" dependencies = [ "bstr", "itoa", "jiff", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-diff" -version = "0.47.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9850fd0c15af113db6f9e130d13091ba0d3754e570a2afdff9e2f3043da260e" +checksum = "62afb7f4ca0acdf4e9dad92065b2eb1bf2993bcc5014b57bc796e3a365b17c4d" dependencies = [ "bstr", "gix-hash", "gix-object", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-discover" -version = "0.36.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c522e31f458f50af09dfb014e10873c5378f702f8049c96f508989aad59671f6" +checksum = "d0c2414bdf04064e0f5a5aa029dfda1e663cf9a6c4bfc8759f2d369299bb65d8" dependencies = [ "bstr", "dunce", @@ -1119,14 +1133,14 @@ dependencies = [ "gix-path", "gix-ref", "gix-sec", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-features" -version = "0.39.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e0eb9efdf96c35c0bed7596d1bef2d4ce6360a1d09738001f9d3e402aa7ba3e" +checksum = "8bfdd4838a8d42bd482c9f0cb526411d003ee94cc7c7b08afe5007329c71d554" dependencies = [ "crc32fast", "crossbeam-channel", @@ -1139,15 +1153,15 @@ dependencies = [ "parking_lot", "prodash", "sha1_smol", - "thiserror 1.0.69", + "thiserror 2.0.11", "walkdir", ] [[package]] name = "gix-fs" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34740384d8d763975858fa2c176b68652a6fcc09f616e24e3ce967b0d370e4d8" +checksum = "182e7fa7bfdf44ffb7cfe7451b373cdf1e00870ac9a488a49587a110c562063d" dependencies = [ "fastrand", "gix-features", @@ -1156,11 +1170,11 @@ dependencies = [ [[package]] name = "gix-glob" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254b5101cf7facc00d9b5ff564cf46302ca76695cca23d33bc958a707b6fc857" +checksum = "4e9c7249fa0a78f9b363aa58323db71e0a6161fd69860ed6f48dedf0ef3a314e" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "bstr", "gix-features", "gix-path", @@ -1168,19 +1182,19 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "952c3a29f1bc1007cc901abce7479943abfa42016db089de33d0a4fa3c85bfe8" +checksum = "e81c5ec48649b1821b3ed066a44efb95f1a268b35c1d91295e61252539fbe9f8" dependencies = [ "faster-hex", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-hashtable" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef65b256631078ef733bc5530c4e6b1c2e7d5c2830b75d4e9034ab3997d18fe" +checksum = "189130bc372accd02e0520dc5ab1cef318dcc2bc829b76ab8d84bbe90ac212d1" dependencies = [ "gix-hash", "hashbrown 0.14.5", @@ -1189,11 +1203,11 @@ dependencies = [ [[package]] name = "gix-index" -version = "0.36.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27619009ca1ea33fd885041273f5fa5a09163a5c1d22a913b28d7b985e66fe29" +checksum = "acd12e3626879369310fffe2ac61acc828613ef656b50c4ea984dd59d7dc85d8" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "bstr", "filetime", "fnv", @@ -1212,25 +1226,25 @@ dependencies = [ "memmap2", "rustix", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-lock" -version = "15.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5102acdf4acae2644e38dbbd18cdfba9597a218f7d85f810fe5430207e03c2de" +checksum = "9739815270ff6940968441824d162df9433db19211ca9ba8c3fc1b50b849c642" dependencies = [ "gix-tempfile", "gix-utils", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-object" -version = "0.45.0" +version = "0.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a77b6e7753d298553d9ae8b1744924481e7a49170983938bb578dccfbc6fc1a" +checksum = "ddc4b3a0044244f0fe22347fb7a79cca165e37829d668b41b85ff46a43e5fd68" dependencies = [ "bstr", "gix-actor", @@ -1238,19 +1252,20 @@ dependencies = [ "gix-features", "gix-hash", "gix-hashtable", + "gix-path", "gix-utils", "gix-validate", "itoa", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", "winnow", ] [[package]] name = "gix-odb" -version = "0.64.0" +version = "0.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb86aadf7f1b2f980601b4fc94309706f9700f8008f935dc512d556c9e60f61" +checksum = "3e93457df69cd09573608ce9fa4f443fbd84bc8d15d8d83adecd471058459c1b" dependencies = [ "arc-swap", "gix-date", @@ -1264,14 +1279,14 @@ dependencies = [ "gix-quote", "parking_lot", "tempfile", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-pack" -version = "0.54.0" +version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "363e6e59a855ba243672408139db68e2478126cdcfeabb420777df4a1f20026b" +checksum = "fc13a475b3db735617017fb35f816079bf503765312d4b1913b18cf96f3fa515" dependencies = [ "clru", "gix-chunk", @@ -1282,39 +1297,70 @@ dependencies = [ "gix-path", "memmap2", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", "uluru", ] +[[package]] +name = "gix-packetline" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e5ae6bc3ac160a6bf44a55f5537813ca3ddb08549c0fd3e7ef699c73c439cd" +dependencies = [ + "bstr", + "faster-hex", + "gix-trace", + "thiserror 2.0.11", +] + [[package]] name = "gix-path" -version = "0.10.12" +version = "0.10.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c04e5a94fdb56b1e91eb7df2658ad16832428b8eeda24ff1a0f0288de2bce554" +checksum = "c40f12bb65a8299be0cfb90fe718e3be236b7a94b434877012980863a883a99f" dependencies = [ "bstr", "gix-trace", "home", "once_cell", - "thiserror 1.0.69", + "thiserror 2.0.11", +] + +[[package]] +name = "gix-protocol" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c61bd61afc6b67d213241e2100394c164be421e3f7228d3521b04f48ca5ba90" +dependencies = [ + "bstr", + "gix-date", + "gix-features", + "gix-hash", + "gix-ref", + "gix-shallow", + "gix-transport", + "gix-utils", + "maybe-async", + "thiserror 2.0.11", + "winnow", ] [[package]] name = "gix-quote" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89f9a1525dcfd9639e282ea939f5ab0d09d93cf2b90c1fc6104f1b9582a8e49" +checksum = "e49357fccdb0c85c0d3a3292a9f6db32d9b3535959b5471bb9624908f4a066c6" dependencies = [ "bstr", "gix-utils", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-ref" -version = "0.48.0" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47385e71fa2d9da8c35e642ef4648808ddf0a52bc93425879088c706dfeaea2" +checksum = "47adf4c5f933429f8554e95d0d92eee583cfe4b95d2bf665cd6fd4a1531ee20c" dependencies = [ "gix-actor", "gix-features", @@ -1327,31 +1373,31 @@ dependencies = [ "gix-utils", "gix-validate", "memmap2", - "thiserror 1.0.69", + "thiserror 2.0.11", "winnow", ] [[package]] name = "gix-refspec" -version = "0.26.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0022038a09d80d9abf773be8efcbb502868d97f6972b8633bfb52ab6edaac442" +checksum = "59650228d8f612f68e7f7a25f517fcf386c5d0d39826085492e94766858b0a90" dependencies = [ "bstr", "gix-hash", "gix-revision", "gix-validate", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-revision" -version = "0.30.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee8eb4088fece3562af4a5d751e069f90e93345524ad730512185234c4b55f1" +checksum = "3fe28bbccca55da6d66e6c6efc6bb4003c29d407afd8178380293729733e6b53" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "bstr", "gix-commitgraph", "gix-date", @@ -1360,14 +1406,14 @@ dependencies = [ "gix-object", "gix-revwalk", "gix-trace", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-revwalk" -version = "0.16.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c9a9496da98d36ff19063a8576bf09a87425583b709a56dc5594fffa9d39b2" +checksum = "d4ecb80c235b1e9ef2b99b23a81ea50dd569a88a9eb767179793269e0e616247" dependencies = [ "gix-commitgraph", "gix-date", @@ -1375,26 +1421,38 @@ dependencies = [ "gix-hashtable", "gix-object", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-sec" -version = "0.10.9" +version = "0.10.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2007538eda296445c07949cf04f4a767307d887184d6b3e83e2d636533ddc6e" +checksum = "d84dae13271f4313f8d60a166bf27e54c968c7c33e2ffd31c48cafe5da649875" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "gix-path", "libc", "windows-sys 0.52.0", ] +[[package]] +name = "gix-shallow" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab72543011e303e52733c85bef784603ef39632ddf47f69723def52825e35066" +dependencies = [ + "bstr", + "gix-hash", + "gix-lock", + "thiserror 2.0.11", +] + [[package]] name = "gix-tempfile" -version = "15.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2feb86ef094cc77a4a9a5afbfe5de626897351bbbd0de3cb9314baf3049adb82" +checksum = "2558f423945ef24a8328c55d1fd6db06b8376b0e7013b1bb476cc4ffdf678501" dependencies = [ "gix-fs", "libc", @@ -1405,17 +1463,33 @@ dependencies = [ [[package]] name = "gix-trace" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04bdde120c29f1fc23a24d3e115aeeea3d60d8e65bab92cc5f9d90d9302eb952" +checksum = "7c396a2036920c69695f760a65e7f2677267ccf483f25046977d87e4cb2665f7" + +[[package]] +name = "gix-transport" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11187418489477b1b5b862ae1aedbbac77e582f2c4b0ef54280f20cfe5b964d9" +dependencies = [ + "bstr", + "gix-command", + "gix-features", + "gix-packetline", + "gix-quote", + "gix-sec", + "gix-url", + "thiserror 2.0.11", +] [[package]] name = "gix-traverse" -version = "0.42.0" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f20f1b13cc4fa6ba92b24e6aa0c2fb6a34beb4458ef88c6300212db504e818df" +checksum = "2bec70e53896586ef32a3efa7e4427b67308531ed186bb6120fb3eca0f0d61b4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "gix-commitgraph", "gix-date", "gix-hash", @@ -1423,27 +1497,28 @@ dependencies = [ "gix-object", "gix-revwalk", "smallvec", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "gix-url" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e7c297c3265015c133a2c02199610b6e1373a09dc4be057d0c1b5285737f06" +checksum = "29218c768b53dd8f116045d87fec05b294c731a4b2bdd257eeca2084cc150b13" dependencies = [ "bstr", "gix-features", "gix-path", - "thiserror 1.0.69", + "percent-encoding", + "thiserror 2.0.11", "url", ] [[package]] name = "gix-utils" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba427e3e9599508ed98a6ddf8ed05493db114564e338e41f6a996d2e4790335f" +checksum = "ff08f24e03ac8916c478c8419d7d3c33393da9bb41fa4c24455d5406aeefd35f" dependencies = [ "fastrand", "unicode-normalization", @@ -1451,19 +1526,19 @@ dependencies = [ [[package]] name = "gix-validate" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e187b263461bc36cea17650141567753bc6207d036cedd1de6e81a52f277ff68" +checksum = "9eaa01c3337d885617c0a42e92823922a2aea71f4caeace6fe87002bdcadbd90" dependencies = [ "bstr", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] name = "glob" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "hashbrown" @@ -1486,9 +1561,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -1518,11 +1593,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1536,7 +1611,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -1677,7 +1752,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -1721,12 +1796,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -1758,9 +1833,9 @@ dependencies = [ [[package]] name = "io-enum" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b53d712d99a73eec59ee5e4fe6057f8052142d38eeafbbffcb06b36d738a6e" +checksum = "d197db2f7ebf90507296df3aebaf65d69f5dce8559d8dbd82776a6cadab61bbf" dependencies = [ "derive_utils", ] @@ -1776,31 +1851,35 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jiff" -version = "0.1.14" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d9d414fc817d3e3d62b2598616733f76c4cc74fbac96069674739b881295c8" +checksum = "d2bb0c2e28117985a4d90e3bc70092bc8f226f434c7ec7e23dd9ff99c5c5721a" dependencies = [ "jiff-tzdb-platform", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", "windows-sys 0.59.0", ] [[package]] name = "jiff-tzdb" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91335e575850c5c4c673b9bd467b0e025f164ca59d0564f69d0c2ee0ffad4653" +checksum = "cf2cec2f5d266af45a071ece48b1fb89f3b00b2421ac3a5fe10285a6caaa60d3" [[package]] name = "jiff-tzdb-platform" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9835f0060a626fe59f160437bc725491a6af23133ea906500027d1bd2f8f4329" +checksum = "a63c62e404e7b92979d2792352d885a7f8f83fd1d0d31eea582d77b2ceca697e" dependencies = [ "jiff-tzdb", ] @@ -1816,10 +1895,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1840,15 +1920,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.164" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets", @@ -1866,16 +1946,16 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "libc", "redox_syscall", ] [[package]] name = "libz-sys" -version = "1.1.20" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" +checksum = "df9b68e50e6e0b26f672573834882eb57759f6db9b3be2ea3c35c91188bb4eaa" dependencies = [ "cc", "pkg-config", @@ -1884,9 +1964,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -1912,9 +1992,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "lru" @@ -1922,7 +2002,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -1961,6 +2041,17 @@ dependencies = [ "tendril", ] +[[package]] +name = "maybe-async" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "md-5" version = "0.10.6" @@ -1994,9 +2085,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", "simd-adler32", @@ -2043,7 +2134,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", "termcolor", "thiserror 1.0.69", ] @@ -2057,7 +2148,7 @@ dependencies = [ "base64", "bigdecimal", "bindgen", - "bitflags 2.6.0", + "bitflags 2.8.0", "bitvec", "btoi", "byteorder", @@ -2195,7 +2286,7 @@ version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "cfg-if", "foreign-types", "libc", @@ -2212,7 +2303,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -2258,16 +2349,16 @@ dependencies = [ [[package]] name = "pathfinding" -version = "4.11.0" +version = "4.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cff69f3ba9d0346c1dbe1248fc2ed4523567b683d1b6ff4144a6b3583369082" +checksum = "aa74fe034e0996b3146ded51d52e2aa5494b604e52c2839cb9f5f501d5948f70" dependencies = [ "deprecate-until", "indexmap", "integer-sqrt", "num-traits", - "rustc-hash 2.0.0", - "thiserror 1.0.69", + "rustc-hash", + "thiserror 2.0.11", ] [[package]] @@ -2298,21 +2389,21 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "phf_shared 0.11.2", + "phf_shared 0.11.3", ] [[package]] name = "phf_codegen" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "phf_generator 0.11.2", - "phf_shared 0.11.2", + "phf_generator 0.11.3", + "phf_shared 0.11.3", ] [[package]] @@ -2327,11 +2418,11 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared 0.11.2", + "phf_shared 0.11.3", "rand", ] @@ -2341,16 +2432,16 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" dependencies = [ - "siphasher", + "siphasher 0.3.11", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] @@ -2361,9 +2452,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.14" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -2372,6 +2463,21 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -2421,14 +2527,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -2465,9 +2571,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -2576,9 +2682,9 @@ dependencies = [ [[package]] name = "redis" -version = "0.27.5" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +checksum = "9f89727cba9cec05cc579942321ff6dd09fe57a8b3217f52f952301efa010da5" dependencies = [ "ahash 0.8.11", "arc-swap", @@ -2594,11 +2700,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", ] [[package]] @@ -2685,7 +2791,7 @@ dependencies = [ [[package]] name = "rust-g" -version = "3.5.1" +version = "3.6.0" dependencies = [ "aho-corasick", "ammonia", @@ -2717,7 +2823,7 @@ dependencies = [ "sha-1", "sha2", "symphonia", - "thiserror 2.0.3", + "thiserror 2.0.11", "toml", "tracy_full", "twox-hash", @@ -2744,15 +2850,9 @@ dependencies = [ [[package]] name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" @@ -2765,22 +2865,22 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "log", "once_cell", @@ -2802,9 +2902,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" [[package]] name = "rustls-webpki" @@ -2817,6 +2917,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" version = "1.0.18" @@ -2865,7 +2971,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.8.0", "core-foundation", "core-foundation-sys", "libc", @@ -2874,9 +2980,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -2884,35 +2990,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.133" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +checksum = "336a0c23cf42a38d9eaa7cd22c7040d04e1228a19a933890805ffd00a16437d2" dependencies = [ "itoa", "memchr", @@ -2968,6 +3074,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "shlex" version = "1.3.0" @@ -2992,6 +3104,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "smallvec" version = "1.13.2" @@ -3000,9 +3118,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3253,9 +3371,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.89" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -3270,7 +3388,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -3281,12 +3399,13 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.14.0" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", "once_cell", "rustix", "windows-sys 0.59.0", @@ -3323,11 +3442,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.11", ] [[package]] @@ -3338,25 +3457,25 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "num-conv", @@ -3374,9 +3493,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -3403,9 +3522,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -3452,9 +3571,9 @@ dependencies = [ [[package]] name = "tracy-client-sys" -version = "0.24.2" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3637e734239e12ab152cd269302500bd063f37624ee210cd04b4936ed671f3b1" +checksum = "69fff37da548239c3bf9e64a12193d261e8b22b660991c6fd2df057c168f435f" dependencies = [ "cc", "windows-targets", @@ -3473,9 +3592,9 @@ dependencies = [ [[package]] name = "twox-hash" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6db6856664807f43c17fbaf2718e2381ac1476a449aa104f5f64622defa1245" +checksum = "e7b17f197b3050ba473acf9181f7b1d3b66d1cf7356c6cc57886662276e65908" dependencies = [ "rand", ] @@ -3524,9 +3643,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.1" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" dependencies = [ "base64", "flate2", @@ -3569,9 +3688,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" [[package]] name = "vcpkg" @@ -3603,35 +3722,35 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3639,22 +3758,25 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "webpki" @@ -3799,9 +3921,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] @@ -3847,7 +3969,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", "synstructure", ] @@ -3869,7 +3991,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -3889,7 +4011,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", "synstructure", ] @@ -3910,7 +4032,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] @@ -3932,14 +4054,14 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.89", + "syn 2.0.96", ] [[package]] name = "zip" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d52293fc86ea7cf13971b3bb81eb21683636e7ae24c729cdaf1b7c4157a352" +checksum = "ae9c1ea7b3a5e1f4b922ff856a129881167511563dc219869afe3787fc0c1a45" dependencies = [ "aes", "arbitrary", @@ -3957,7 +4079,7 @@ dependencies = [ "pbkdf2", "rand", "sha1", - "thiserror 2.0.3", + "thiserror 2.0.11", "time", "zeroize", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index ea2b13cd..23f98149 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rust-g" edition = "2021" -version = "3.5.1" +version = "3.6.0" authors = [ "Bjorn Neergaard ", "Tad Hardesty ", @@ -27,7 +27,7 @@ flume = { version = "0.11", optional = true } chrono = { version = "0.4", optional = true } base64 = { version = "0.22", optional = true } md-5 = { version = "0.10", optional = true } -twox-hash = { version = "2.0", optional = true } +twox-hash = { version = "2.1", optional = true } const-random = { version = "0.1.18", optional = true } sha-1 = { version = "0.10", optional = true } sha2 = { version = "0.10", optional = true } @@ -38,13 +38,13 @@ png = { version = "0.17", optional = true } image = { version = "0.25", optional = true, default-features = false, features = [ "png", ] } -gix = { version = "0.67", optional = true, default-features = false, features = [ +gix = { version = "0.70", optional = true, default-features = false, features = [ "revision", "max-performance-safe", ] } noise = { version = "0.9", optional = true } -redis = { version = "0.27", optional = true, features = ["ahash"] } -ureq = { version = "2.10", optional = true } +redis = { version = "0.28", optional = true, features = ["ahash"] } +ureq = { version = "2.12", optional = true } serde = { version = "1.0", optional = true, features = ["derive"] } serde_json = { version = "1.0", optional = true } once_cell = { version = "1.20", optional = true } @@ -56,7 +56,7 @@ toml-dep = { version = "0.8.19", package = "toml", optional = true } aho-corasick = { version = "1.1", optional = true } rayon = { version = "1.10", optional = true } dbpnoise = { version = "0.1.2", optional = true } -pathfinding = { version = "4.11", optional = true } +pathfinding = { version = "4.13", optional = true } num-integer = { version = "0.1.46", optional = true } dmi = { version = "0.3.7", optional = true } tracy_full = { version = "1.10.0", optional = true } @@ -76,7 +76,9 @@ default = [ "dmi", "file", "git", + "hash", "http", + "iconforge", "json", "log", "noise", @@ -96,7 +98,9 @@ all = [ "dmi", "file", "git", + "hash", "http", + "iconforge", "json", "log", "noise", @@ -107,8 +111,6 @@ all = [ "time", "toml", "url", - "hash", - "iconforge", "pathfinder", "poissonnoise", "redis_pubsub", @@ -124,17 +126,6 @@ cellularnoise = ["rand", "rayon"] dmi = ["png", "image", "dep:dmi"] file = [] git = ["gix", "chrono"] -http = ["ureq", "serde", "serde_json", "once_cell", "jobs"] -json = ["serde", "serde_json"] -log = ["chrono"] -sanitize = ["ammonia", "serde_json"] -sound_len = ["symphonia"] -sql = ["mysql", "serde", "serde_json", "once_cell", "dashmap", "jobs"] -time = [] -toml = ["serde", "serde_json", "toml-dep"] -url = ["url-dep", "percent-encoding"] - -# additional features hash = [ "base64", "const-random", @@ -146,6 +137,7 @@ hash = [ "serde", "serde_json", ] +http = ["ureq", "serde", "serde_json", "once_cell", "jobs"] iconforge = [ "dashmap", "dep:dmi", @@ -160,6 +152,16 @@ iconforge = [ "tracy_full", "twox-hash", ] +json = ["serde", "serde_json"] +log = ["chrono"] +sanitize = ["ammonia", "serde_json"] +sound_len = ["symphonia"] +sql = ["mysql", "serde", "serde_json", "once_cell", "dashmap", "jobs"] +time = [] +toml = ["serde", "serde_json", "toml-dep"] +url = ["url-dep", "percent-encoding"] + +# additional features pathfinder = ["num-integer", "pathfinding", "serde", "serde_json"] poissonnoise = ["fast_poisson"] redis_pubsub = ["flume", "redis", "serde", "serde_json"] diff --git a/README.md b/README.md index 4326403e..60da8369 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,9 @@ The default features are: Mostly used by the asset cache subsystem to improve load times. * file: Faster replacements for `file2text` and `text2file`, as well as reading or checking if files exist. * git: Functions for robustly checking the current git revision. +* hash: Faster replacement for `md5`, support for SHA-1, SHA-256, and SHA-512. * http: Asynchronous HTTP(s) client supporting most standard methods. +* iconforge: A much faster replacement for various bulk DM /icon operations such as [/tg/station]'s asset subsystem spritesheet generation and GAGS bundle generation. * json: Function to check JSON validity. * log: Faster log output. * noise: 2d Perlin noise. @@ -110,8 +112,6 @@ The default features are: Additional features are: * allow_non_32bit: Disables the forced compile errors on non-32bit targets. Only use this if you know exactly what you are doing. * batchnoise: Discrete Batched Perlin-like Noise, fast and multi-threaded - sent over once instead of having to query for every tile. -* hash: Faster replacement for `md5`, support for SHA-1, SHA-256, and SHA-512. Requires OpenSSL on Linux. -* iconforge: A much faster replacement for the spritesheet generation system used by [/tg/station]. * pathfinder: An a* pathfinder used for finding the shortest path in a static node map. Not to be used for a non-static map. * poissonnoise: A way to generate a 2D poisson disk distribution ('blue noise'), which is relatively uniform. * redis_pubsub: Library for sending and receiving messages through Redis. diff --git a/dmsrc/iconforge.dm b/dmsrc/iconforge.dm index 5f6d9bf0..2e97b949 100644 --- a/dmsrc/iconforge.dm +++ b/dmsrc/iconforge.dm @@ -52,6 +52,20 @@ #define rustg_iconforge_cache_valid(input_hash, dmi_hashes, sprites) RUSTG_CALL(RUST_G, "iconforge_cache_valid")(input_hash, dmi_hashes, sprites) /// Returns a job_id for use with rustg_iconforge_check() #define rustg_iconforge_cache_valid_async(input_hash, dmi_hashes, sprites) RUSTG_CALL(RUST_G, "iconforge_cache_valid_async")(input_hash, dmi_hashes, sprites) +/// Provided a /datum/greyscale_config typepath, JSON string containing the greyscale config, and path to a DMI file containing the base icons, +/// Loads that config into memory for later use by rustg_iconforge_gags(). The config_path is the unique identifier used later. +/// JSON Config schema: https://hackmd.io/@tgstation/GAGS-Layer-Types +/// Unsupported features: color_matrix layer type, 'or' blend_mode. May not have BYOND parity with animated icons or varying dirs between layers. +/// Returns "OK" if successful, otherwise, returns a string containing the error. +#define rustg_iconforge_load_gags_config(config_path, config_json, config_icon_path) RUSTG_CALL(RUST_G, "iconforge_load_gags_config")("[config_path]", config_json, config_icon_path) +/// Given a config_path (previously loaded by rustg_iconforge_load_gags_config), and a string of hex colors formatted as "#ff00ff#ffaa00" +/// Outputs a DMI containing all of the states within the config JSON to output_dmi_path, creating any directories leading up to it if necessary. +/// Returns "OK" if successful, otherwise, returns a string containing the error. +#define rustg_iconforge_gags(config_path, colors, output_dmi_path) RUSTG_CALL(RUST_G, "iconforge_gags")("[config_path]", colors, output_dmi_path) +/// Returns a job_id for use with rustg_iconforge_check() +#define rustg_iconforge_load_gags_config_async(config_path, config_json, config_icon_path) RUSTG_CALL(RUST_G, "iconforge_load_gags_config_async")("[config_path]", config_json, config_icon_path) +/// Returns a job_id for use with rustg_iconforge_check() +#define rustg_iconforge_gags_async(config_path, colors, output_dmi_path) RUSTG_CALL(RUST_G, "iconforge_gags_async")("[config_path]", colors, output_dmi_path) #define RUSTG_ICONFORGE_BLEND_COLOR "BlendColor" #define RUSTG_ICONFORGE_BLEND_ICON "BlendIcon" diff --git a/src/iconforge.rs b/src/iconforge.rs index 40145dea..e84a55a2 100644 --- a/src/iconforge.rs +++ b/src/iconforge.rs @@ -1,4 +1,4 @@ -// DMI spritesheet generator +// Multi-threaded DMI spritesheet generator and GAGS re-implementation // Developed by itsmeow use crate::{ byond::catch_panic, @@ -9,9 +9,9 @@ use crate::{ use dashmap::DashMap; use dmi::{ dirs::Dirs, - icon::{Icon, IconState}, + icon::{DmiVersion, Icon, IconState}, }; -use image::{Pixel, RgbaImage}; +use image::{DynamicImage, Pixel, RgbaImage}; use once_cell::sync::Lazy; use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; @@ -106,6 +106,58 @@ byond_fn!(fn iconforge_cache_valid_async(input_hash, dmi_hashes, sprites) { result }); +byond_fn!(fn iconforge_load_gags_config(config_path, config_json, config_icon_path) { + let config_path = config_path.to_owned(); + let config_json = config_json.to_owned(); + let config_icon_path = config_icon_path.to_owned(); + let result = Some(match catch_panic(|| load_gags_config(&config_path, &config_json, &config_icon_path)) { + Ok(o) => o.to_string(), + Err(e) => e.to_string() + }); + frame!(); + result +}); + +byond_fn!(fn iconforge_load_gags_config_async(config_path, config_json, config_icon_path) { + let config_path = config_path.to_owned(); + let config_json = config_json.to_owned(); + let config_icon_path = config_icon_path.to_owned(); + Some(jobs::start(move || { + let result = match catch_panic(|| load_gags_config(&config_path, &config_json, &config_icon_path)) { + Ok(o) => o.to_string(), + Err(e) => e.to_string() + }; + frame!(); + result + })) +}); + +byond_fn!(fn iconforge_gags(config_path, colors, output_dmi_path) { + let config_path = config_path.to_owned(); + let colors = colors.to_owned(); + let output_dmi_path = output_dmi_path.to_owned(); + let result = Some(match catch_panic(|| gags(&config_path, &colors, &output_dmi_path)) { + Ok(o) => o.to_string(), + Err(e) => e.to_string() + }); + frame!(); + result +}); + +byond_fn!(fn iconforge_gags_async(config_path, colors, output_dmi_path) { + let config_path = config_path.to_owned(); + let colors = colors.to_owned(); + let output_dmi_path = output_dmi_path.to_owned(); + Some(jobs::start(move || { + let result = match catch_panic(|| gags(&config_path, &colors, &output_dmi_path)) { + Ok(o) => o.to_string(), + Err(e) => e.to_string() + }; + frame!(); + result + })) +}); + #[derive(Serialize)] struct SpritesheetResult { sizes: Vec, @@ -357,9 +409,8 @@ fn generate_spritesheet( sprites_map.par_iter().for_each(|(sprite_name, icon)| { zone!("sprite_to_icons"); - icon_to_icons(icon) - .into_par_iter() - .for_each(|icon| match icon_to_dmi(icon) { + icon_to_icons(icon).into_par_iter().for_each(|icon| { + match filepath_to_dmi(&icon.icon_file) { Ok(_) => { if hash_icons && !dmi_hashes.contains_key(&icon.icon_file) { zone!("hash_dmi"); @@ -375,7 +426,8 @@ fn generate_spritesheet( } } Err(err) => error.lock().unwrap().push(err), - }); + } + }); { zone!("map_to_base"); @@ -709,10 +761,9 @@ fn icon_to_icons_io(icon_in: &IconObjectIO) -> Vec<&IconObjectIO> { icons } -/// Given an IconObject, returns a DMI Icon structure and caches it. -fn icon_to_dmi(icon: &IconObject) -> Result, String> { - zone!("icon_to_dmi"); - let icon_path = &icon.icon_file; +/// Given a DMI filepath, returns a DMI Icon structure and caches it. +fn filepath_to_dmi(icon_path: &str) -> Result, String> { + zone!("filepath_to_dmi"); { zone!("check_dmi_exists"); if let Some(found) = ICON_FILES.get(icon_path) { @@ -771,7 +822,7 @@ fn icon_to_image( return Err(String::from("Image not found in cache!")); } } - let dmi = icon_to_dmi(icon)?; + let dmi = filepath_to_dmi(&icon.icon_file)?; let mut matched_state: Option<&IconState> = None; { zone!("match_icon_state"); @@ -835,36 +886,66 @@ fn apply_all_transforms(image: &mut RgbaImage, transforms: &Vec) -> R Ok(()) } +fn blend_color( + image: &mut RgbaImage, + color: &String, + blend_mode: &BlendMode, +) -> Result<(), String> { + zone!("blend_color"); + let mut color2: [u8; 4] = [0, 0, 0, 255]; + { + zone!("from_hex"); + let mut hex: String = color.to_owned(); + if hex.starts_with('#') { + hex = hex[1..].to_string(); + } + if hex.len() == 6 { + hex += "ff"; + } + + if let Err(err) = hex::decode_to_slice(hex, &mut color2) { + return Err(format!("Decoding hex color {} failed: {}", color, err)); + } + } + for x in 0..image.width() { + for y in 0..image.height() { + let px = image.get_pixel_mut(x, y); + let pixel = px.channels(); + let blended = Rgba::blend_u8(pixel, &color2, blend_mode); + + *px = image::Rgba::(blended); + } + } + Ok(()) +} + +fn blend_icon( + image: &mut RgbaImage, + other_image: &RgbaImage, + blend_mode: &BlendMode, +) -> Result<(), String> { + zone!("blend_icon"); + for x in 0..std::cmp::min(image.width(), other_image.width()) { + for y in 0..std::cmp::min(image.height(), other_image.height()) { + let px1 = image.get_pixel_mut(x, y); + let px2 = other_image.get_pixel(x, y); + let pixel_1 = px1.channels(); + let pixel_2 = px2.channels(); + + let blended = Rgba::blend_u8(pixel_1, pixel_2, blend_mode); + + *px1 = image::Rgba::(blended); + } + } + Ok(()) +} + /// Applies transforms to a RgbaImage. fn transform_image(image: &mut RgbaImage, transform: &Transform) -> Result<(), String> { zone!("transform_image"); match transform { Transform::BlendColor { color, blend_mode } => { - zone!("blend_color"); - let mut color2: [u8; 4] = [0, 0, 0, 255]; - { - zone!("from_hex"); - let mut hex: String = color.to_owned(); - if hex.starts_with('#') { - hex = hex[1..].to_string(); - } - if hex.len() == 6 { - hex += "ff"; - } - - if let Err(err) = hex::decode_to_slice(hex, &mut color2) { - return Err(format!("Decoding hex color {} failed: {}", color, err)); - } - } - for x in 0..image.width() { - for y in 0..image.height() { - let px = image.get_pixel_mut(x, y); - let pixel = px.channels(); - let blended = Rgba::blend_u8(pixel, &color2, *blend_mode); - - *px = image::Rgba::(blended); - } - } + blend_color(image, color, &BlendMode::from_u8(blend_mode)?)? } Transform::BlendIcon { icon, blend_mode } => { zone!("blend_icon"); @@ -874,18 +955,7 @@ fn transform_image(image: &mut RgbaImage, transform: &Transform) -> Result<(), S if !cached { apply_all_transforms(&mut other_image, &icon.transform)?; }; - for x in 0..std::cmp::min(image.width(), other_image.width()) { - for y in 0..std::cmp::min(image.width(), other_image.width()) { - let px1 = image.get_pixel_mut(x, y); - let px2 = other_image.get_pixel(x, y); - let pixel_1 = px1.channels(); - let pixel_2 = px2.channels(); - - let blended = Rgba::blend_u8(pixel_1, pixel_2, *blend_mode); - - *px1 = image::Rgba::(blended); - } - } + blend_icon(image, &other_image, &BlendMode::from_u8(blend_mode)?)?; if let Err(err) = return_image(other_image, icon) { return Err(err.to_string()); } @@ -983,6 +1053,478 @@ fn transform_image(image: &mut RgbaImage, transform: &Transform) -> Result<(), S Ok(()) } +type GAGSConfigEntry = Vec; + +#[derive(Serialize, Deserialize, Clone)] +#[serde(untagged)] +enum GAGSLayerGroupOption { + GAGSLayer(GAGSLayer), + GAGSLayerGroup(Vec), +} + +#[derive(Serialize, Deserialize, Clone)] +#[serde(untagged)] +enum GAGSColorID { + GAGSColorStatic(String), + GAGSColorIndex(u8), +} + +#[derive(Serialize, Deserialize, Clone)] +#[serde(tag = "type", rename_all = "snake_case")] +enum GAGSLayer { + IconState { + icon_state: String, + blend_mode: String, + #[serde(default)] + color_ids: Vec, + }, + Reference { + reference_type: String, + #[serde(default)] + icon_state: String, + blend_mode: String, + #[serde(default)] + color_ids: Vec, + }, + // Unsupported, but exists nonetheless. + ColorMatrix { + blend_mode: String, + color_matrix: [[f32; 4]; 5], + }, +} + +impl GAGSLayer { + fn get_blendmode_str(&self) -> &String { + match self { + GAGSLayer::IconState { + icon_state: _, + blend_mode, + color_ids: _, + } => blend_mode, + GAGSLayer::Reference { + reference_type: _, + icon_state: _, + blend_mode, + color_ids: _, + } => blend_mode, + GAGSLayer::ColorMatrix { + blend_mode, + color_matrix: _, + } => blend_mode, + } + } + + fn get_blendmode(&self) -> Result { + BlendMode::from_str(self.get_blendmode_str().as_str()) + } +} + +type GAGSConfig = HashMap; + +struct GAGSData { + config: GAGSConfig, + config_path: String, + config_icon: Arc, +} + +static GAGS_CACHE: Lazy> = Lazy::new(DashMap::new); + +/// Loads a GAGS config and the requested DMIs into memory for use by iconforge_gags() +fn load_gags_config( + config_path: &str, + config_json: &str, + config_icon_path: &str, +) -> Result { + zone!("load_gags_config"); + let gags_config: GAGSConfig; + { + zone!("gags_from_json"); + gags_config = serde_json::from_str::(config_json)?; + } + let icon_data = match filepath_to_dmi(config_icon_path) { + Ok(data) => data, + Err(err) => { + return Err(Error::IconForge(err)); + } + }; + { + zone!("gags_insert_config"); + GAGS_CACHE.insert( + config_path.to_owned(), + GAGSData { + config: gags_config, + config_path: config_path.to_owned(), + config_icon: icon_data, + }, + ); + } + Ok(String::from("OK")) +} + +/// Given an config path and a list of color_ids, outputs a dmi at output_dmi_path with the config's states. +fn gags(config_path: &str, colors: &str, output_dmi_path: &str) -> Result { + zone!("gags"); + let gags_data = match GAGS_CACHE.get(config_path) { + Some(config) => config, + None => { + return Err(Error::IconForge(format!( + "Provided config_path {} has not been loaded by iconforge_load_gags_config!", + config_path + ))); + } + }; + + let colors_vec = colors + .split('#') + .map(|x| String::from("#") + x) + .filter(|x| x != "#") + .collect::>(); + let errors = Arc::new(Mutex::new(Vec::::new())); + + let output_states = Arc::new(Mutex::new(Vec::::new())); + gags_data.config.par_iter().for_each(|(icon_state_name, layer_groups)| { + zone!("gags_create_icon_state"); + let mut first_matched_state: Option = None; + let transformed_images = match generate_layer_groups_for_iconstate(icon_state_name, &colors_vec, layer_groups, &gags_data, None, &mut first_matched_state) { + Ok(images) => images, + Err(err) => { + errors.lock().unwrap().push(err); + return; + } + }; + let icon_state = match first_matched_state { + Some(state) => state, + None => { + errors.lock().unwrap().push(format!("GAGS state {} for GAGS config {} had no matching icon_states in any layers!", icon_state_name, config_path)); + return; + } + }; + + { + zone!("gags_insert_icon_state"); + output_states.lock().unwrap().push(IconState { + name: icon_state_name.to_owned(), + dirs: icon_state.dirs, + frames: icon_state.frames, + delay: icon_state.delay.to_owned(), + loop_flag: icon_state.loop_flag, + rewind: icon_state.rewind, + movement: icon_state.movement, + unknown_settings: icon_state.unknown_settings.to_owned(), + hotspot: icon_state.hotspot, + images: transformed_images, + }); + } + }); + + let errors_unlocked = errors.lock().unwrap(); + if !errors_unlocked.is_empty() { + return Err(Error::IconForge(errors_unlocked.join("\n"))); + } + + { + zone!("gags_write_dmi"); + let path = std::path::Path::new(output_dmi_path); + std::fs::create_dir_all(path.parent().unwrap())?; + let mut output_file = File::create(path)?; + + if let Err(err) = (Icon { + version: DmiVersion::default(), + width: gags_data.config_icon.width, + height: gags_data.config_icon.height, + states: output_states.lock().unwrap().to_owned(), + } + .save(&mut output_file)) + { + return Err(Error::IconForge(format!( + "Error during icon saving: {}", + err + ))); + } + } + + Ok(String::from("OK")) +} + +/// Version of gags() for use by the reference layer type that acts in memory +fn gags_internal( + config_path: &str, + colors_vec: &Vec, + icon_state: &String, + last_external_images: Option>, + first_matched_state: &mut Option, +) -> Result, String> { + zone!("gags_internal"); + let gags_data = match GAGS_CACHE.get(config_path) { + Some(config) => config, + None => { + return Err(format!("Provided config_path {} has not been loaded by iconforge_load_gags_config (from gags_internal)!", config_path)); + } + }; + + let layer_groups = match gags_data.config.get(icon_state) { + Some(data) => data, + None => { + return Err(format!("Provided config_path {} did not contain requested icon_state {} for reference type.", config_path, icon_state)); + } + }; + { + zone!("gags_create_icon_state"); + let mut first_matched_state_internal: Option = None; + let transformed_images = match generate_layer_groups_for_iconstate( + icon_state, + colors_vec, + layer_groups, + &gags_data, + last_external_images, + &mut first_matched_state_internal, + ) { + Ok(images) => images, + Err(err) => { + return Err(err); + } + }; + { + zone!("update_first_matched_state"); + if first_matched_state.is_none() && first_matched_state_internal.is_some() { + *first_matched_state = first_matched_state_internal; + } + } + Ok(transformed_images) + } +} + +/// Recursive function that parses out GAGS configs into layer groups. +fn generate_layer_groups_for_iconstate( + state_name: &str, + colors: &Vec, + layer_groups: &Vec, + gags_data: &GAGSData, + last_external_images: Option>, + first_matched_state: &mut Option, +) -> Result, String> { + zone!("generate_layer_groups_for_iconstate"); + let mut new_images: Option> = None; + for option in layer_groups { + zone!("process_gags_layergroup_option"); + let (layer_images, blend_mode_result) = match option { + GAGSLayerGroupOption::GAGSLayer(layer) => ( + generate_layer_for_iconstate( + state_name, + colors, + layer, + gags_data, + new_images.clone().or(last_external_images.clone()), + first_matched_state, + )?, + layer.get_blendmode(), + ), + GAGSLayerGroupOption::GAGSLayerGroup(layers) => { + if layers.is_empty() { + return Err(format!( + "Empty layer group provided to GAGS state {} for GAGS config {} !", + state_name, gags_data.config_path + )); + } + ( + generate_layer_groups_for_iconstate( + state_name, + colors, + layers, + gags_data, + new_images.clone().or(last_external_images.clone()), + first_matched_state, + )?, + match layers.first().unwrap() { + GAGSLayerGroupOption::GAGSLayer(layer) => layer.get_blendmode(), + GAGSLayerGroupOption::GAGSLayerGroup(_) => { + return Err(format!("Layer group began with another layer group in GAGS state {} for GAGS config {} !", state_name, gags_data.config_path)); + } + }, + ) + } + }; + + let blend_mode = blend_mode_result?; + new_images = match new_images { + Some(images) => Some(blend_images_other(images, layer_images, &blend_mode)?), + None => Some(layer_images), + } + } + match new_images { + Some(images) => Ok(images), + None => Err(format!("No image found for GAGS state {}", state_name)), + } +} + +/// Generates a specific layer. +fn generate_layer_for_iconstate( + state_name: &str, + colors: &[String], + layer: &GAGSLayer, + gags_data: &GAGSData, + new_images: Option>, + first_matched_state: &mut Option, +) -> Result, String> { + zone!("generate_layer_for_iconstate"); + let images_result: Option> = match layer { + GAGSLayer::IconState { + icon_state, + blend_mode: _, + color_ids, + } => { + zone!("gags_layer_type_icon_state"); + let icon_state: &IconState = match gags_data + .config_icon + .states + .iter() + .find(|state| state.name == *icon_state) + { + Some(state) => state, + None => { + return Err(format!( + "Invalid icon_state {} in layer provided for GAGS config {}", + state_name, gags_data.config_path + )); + } + }; + + if first_matched_state.is_none() { + *first_matched_state = Some(icon_state.clone()); + } + + let images = icon_state.images.clone(); + if !color_ids.is_empty() { + // silly BYOND, indexes from 1! Also, for some reason this is an array despite only ever having one value. Thanks TG :) + let actual_color = match color_ids.first().unwrap() { + GAGSColorID::GAGSColorIndex(idx) => colors.get(*idx as usize - 1).unwrap(), + GAGSColorID::GAGSColorStatic(color) => color, + }; + return Ok(blend_images_color( + images, + actual_color, + &BlendMode::Multiply, + )?); + } else { + return Ok(images); // this will get blended by the layergroup. + } + } + GAGSLayer::Reference { + reference_type, + icon_state, + blend_mode: _, + color_ids, + } => { + zone!("gags_layer_type_reference"); + let mut colors_in: Vec = colors.to_owned(); + if !color_ids.is_empty() { + colors_in = color_ids + .iter() + .map(|color| match color { + GAGSColorID::GAGSColorIndex(idx) => { + colors.get(*idx as usize - 1).unwrap().clone() + } + GAGSColorID::GAGSColorStatic(color) => color.clone(), + }) + .collect(); + } + Some(gags_internal( + reference_type, + &colors_in, + icon_state, + new_images, + first_matched_state, + )?) + } + GAGSLayer::ColorMatrix { + blend_mode: _, + color_matrix: _, + } => new_images, // unsupported! TROLLED! + }; + + match images_result { + Some(images) => Ok(images), + None => Err(format!( + "No images found for GAGS state {} for GAGS config {} !", + state_name, gags_data.config_path + )), + } +} + +/// Blends a set of images with a color. +fn blend_images_color( + images: Vec, + color: &String, + blend_mode: &BlendMode, +) -> Result, Error> { + zone!("blend_images_color"); + let errors = Arc::new(Mutex::new(Vec::::new())); + let images_out = images + .into_par_iter() + .map(|image| { + zone!("blend_image_color"); + let mut new_image = image.clone().into_rgba8(); + if let Err(err) = blend_color(&mut new_image, color, blend_mode) { + errors.lock().unwrap().push(err); + } + DynamicImage::ImageRgba8(new_image) + }) + .collect(); + let errors_unlock = errors.lock().unwrap(); + if !errors_unlock.is_empty() { + return Err(Error::IconForge(errors_unlock.join("\n"))); + } + Ok(images_out) +} + +/// Blends a set of images with another set of images. +fn blend_images_other( + images: Vec, + mut images_other: Vec, + blend_mode: &BlendMode, +) -> Result, Error> { + zone!("blend_images_other"); + let errors = Arc::new(Mutex::new(Vec::::new())); + let images_out: Vec = if images_other.len() == 1 { + // This is useful in the case where the something with 4+ dirs blends with 1dir + let first_image = images_other.remove(0).into_rgba8(); + images + .into_par_iter() + .map(|image| { + zone!("blend_image_other_simple"); + let mut new_image = image.clone().into_rgba8(); + match blend_icon(&mut new_image, &first_image, blend_mode) { + Ok(_) => (), + Err(error) => { + errors.lock().unwrap().push(error); + } + }; + DynamicImage::ImageRgba8(new_image) + }) + .collect() + } else { + (images, images_other) + .into_par_iter() + .map(|(image, image2)| { + zone!("blend_image_other"); + let mut new_image = image.clone().into_rgba8(); + match blend_icon(&mut new_image, &image2.into_rgba8(), blend_mode) { + Ok(_) => (), + Err(error) => { + errors.lock().unwrap().push(error); + } + }; + DynamicImage::ImageRgba8(new_image) + }) + .collect() + }; + let errors_unlock = errors.lock().unwrap(); + if !errors_unlock.is_empty() { + return Err(Error::IconForge(errors_unlock.join("\n"))); + } + Ok(images_out) +} + #[derive(Clone)] struct Rgba { r: f32, @@ -991,6 +1533,41 @@ struct Rgba { a: f32, } +// The numbers correspond to BYOND ICON_X blend modes. https://www.byond.com/docs/ref/#/icon/proc/Blend +#[derive(Clone, Hash, Eq, PartialEq, Serialize)] +#[repr(u8)] +pub enum BlendMode { + Add = 0, + Subtract = 1, + Multiply = 2, + Overlay = 3, + Underlay = 6, +} + +impl BlendMode { + fn from_u8(blend_mode: &u8) -> Result { + match *blend_mode { + 0 => Ok(BlendMode::Add), + 1 => Ok(BlendMode::Subtract), + 2 => Ok(BlendMode::Multiply), + 3 => Ok(BlendMode::Overlay), + 6 => Ok(BlendMode::Underlay), + _ => Err(format!("blend_mode '{}' is not supported!", blend_mode)), + } + } + + fn from_str(blend_mode: &str) -> Result { + match blend_mode { + "add" => Ok(BlendMode::Add), + "subtract" => Ok(BlendMode::Subtract), + "multiply" => Ok(BlendMode::Multiply), + "overlay" => Ok(BlendMode::Overlay), + "underlay" => Ok(BlendMode::Underlay), + _ => Err(format!("blend_mode '{}' is not supported!", blend_mode)), + } + } +} + impl Rgba { fn into_array(self) -> [u8; 4] { [ @@ -1037,24 +1614,24 @@ impl Rgba { } /// Takes two [u8; 4]s, converts them to Rgba structs, then blends them according to blend_mode by calling blend(). - fn blend_u8(color: &[u8], other_color: &[u8], blend_mode: u8) -> [u8; 4] { + fn blend_u8(color: &[u8], other_color: &[u8], blend_mode: &BlendMode) -> [u8; 4] { Rgba::from_array(color) .blend(&Rgba::from_array(other_color), blend_mode) .into_array() } - /// Blends two colors according to blend_mode. The numbers correspond to BYOND blend modes. - fn blend(&self, other_color: &Rgba, blend_mode: u8) -> Rgba { + /// Blends two colors according to blend_mode. + fn blend(&self, other_color: &Rgba, blend_mode: &BlendMode) -> Rgba { match blend_mode { - 0 => Rgba::map_each(self, other_color, |c1, c2| c1 + c2, f32::min), - 1 => Rgba::map_each(self, other_color, |c1, c2| c1 - c2, f32::min), - 2 => Rgba::map_each( + BlendMode::Add => Rgba::map_each(self, other_color, |c1, c2| c1 + c2, f32::min), + BlendMode::Subtract => Rgba::map_each(self, other_color, |c1, c2| c1 - c2, f32::min), + BlendMode::Multiply => Rgba::map_each( self, other_color, |c1, c2| c1 * c2 / 255.0, |a1: f32, a2: f32| a1 * a2 / 255.0, ), - 3 => Rgba::map_each_a( + BlendMode::Overlay => Rgba::map_each_a( self, other_color, |c1, c2, c1_a, c2_a| { @@ -1069,7 +1646,7 @@ impl Rgba { high + (high * low / 255.0) }, ), - 6 => Rgba::map_each_a( + BlendMode::Underlay => Rgba::map_each_a( other_color, self, |c1, c2, c1_a, c2_a| { @@ -1084,7 +1661,6 @@ impl Rgba { high + (high * low / 255.0) }, ), - _ => self.clone(), } } }