diff --git a/Cargo.lock b/Cargo.lock index 4aae673311..a4b84ad21d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "ab_glyph" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d" +checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2" dependencies = [ "ab_glyph_rasterizer", "owned_ttf_parser", @@ -18,39 +18,17 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.3", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -88,12 +66,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -111,12 +83,27 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse 0.2.7", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstream" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", - "anstyle-parse", + "anstyle-parse 1.0.0", "anstyle-query", "anstyle-wincon", "colorchoice", @@ -126,9 +113,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -139,31 +126,40 @@ dependencies = [ "utf8parse", ] +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arrayref" @@ -192,14 +188,14 @@ version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading 0.8.8", + "libloading 0.8.9", ] [[package]] name = "ashpd" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df" +checksum = "d2f3f79755c74fd155000314eb349864caa787c6592eace6c6882dad873d9c39" dependencies = [ "async-fs", "async-net", @@ -243,9 +239,9 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", @@ -257,9 +253,9 @@ dependencies = [ [[package]] name = "async-fs" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f7e37c0ed80b2a977691c47dae8625cfb21e205827106c64f7c588766b2e50" +checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" dependencies = [ "async-lock", "blocking", @@ -268,11 +264,11 @@ dependencies = [ [[package]] name = "async-io" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", @@ -281,14 +277,14 @@ dependencies = [ "polling", "rustix", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "async-lock" -version = "3.4.1" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc" +checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ "event-listener", "event-listener-strategy", @@ -308,9 +304,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", "async-io", @@ -332,14 +328,14 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "async-signal" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ "async-io", "async-lock", @@ -350,7 +346,7 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -367,7 +363,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -404,21 +400,6 @@ dependencies = [ "fs_extra", ] -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base64" version = "0.22.1" @@ -502,11 +483,11 @@ dependencies = [ [[package]] name = "block2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -524,9 +505,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" dependencies = [ "cfg_aliases", ] @@ -547,9 +528,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "bytemuck" @@ -568,7 +549,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -591,18 +572,18 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bzip2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea8dcd42434048e4f7a304411d9273a411f647446c1234a65ce0554923f4cff" +checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" dependencies = [ "libbz2-rs-sys", ] [[package]] name = "calloop" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ "bitflags 2.11.0", "polling", @@ -625,11 +606,11 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.12" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0b03af37dad7a14518b7691d81acb0f8222604ad3d1b02f6b4bed5188c0cd5" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -707,10 +688,11 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.34" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ + "find-msvc-tools", "jobserver", "libc", "shlex", @@ -718,9 +700,9 @@ dependencies = [ [[package]] name = "cef" -version = "142.5.0+142.0.17" +version = "142.5.1+142.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32eab60854609591d365051497b1fb78b77b129d9e39ba69b1f71ee3f4ae9345" +checksum = "13a04d2b0d1210f347f79e80de04f0a30b3a5111aec74559072809ed86511c4a" dependencies = [ "ash", "cef-dll-sys", @@ -728,7 +710,7 @@ dependencies = [ "libloading 0.9.0", "metal", "objc", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-io-surface", "thiserror 2.0.18", "tracing", @@ -739,9 +721,9 @@ dependencies = [ [[package]] name = "cef-dll-sys" -version = "142.5.0+142.0.17" +version = "142.5.1+142.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a8c418c8eb6abff55f52668dbb8cba3cd5fcf057cf3eed46c04013a08ad9004" +checksum = "526beacb4bdf73c252544ef5442b62f2858454fe5f0aa146734b773e2ad37551" dependencies = [ "anyhow", "cmake", @@ -757,9 +739,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -769,16 +751,28 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-link 0.1.3", + "windows-link", +] + +[[package]] +name = "chumsky" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14377e276b2c8300513dff55ba4cc4142b44e5d6de6d00eb5b2307d650bb4ec1" +dependencies = [ + "hashbrown 0.15.5", + "regex-automata 0.3.9", + "serde", + "unicode-ident", + "unicode-segmentation", ] [[package]] @@ -810,9 +804,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.46" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" +checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351" dependencies = [ "clap_builder", "clap_derive", @@ -820,11 +814,11 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.46" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ - "anstream", + "anstream 1.0.0", "anstyle", "clap_lex", "strsim", @@ -832,21 +826,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clipboard-win" @@ -879,19 +873,19 @@ dependencies = [ [[package]] name = "clipboard_x11" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4274ea815e013e0f9f04a2633423e14194e408a0576c943ce3d14ca56c50031c" +checksum = "bd63e33452ffdafd39924c4f05a5dd1e94db646c779c6bd59148a3d95fff5ad4" dependencies = [ - "thiserror 1.0.69", + "thiserror 2.0.18", "x11rb", ] [[package]] name = "cmake" -version = "0.1.54" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" dependencies = [ "cc", ] @@ -907,6 +901,16 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "codespan-reporting" +version = "0.12.0" +source = "git+https://github.com/urisinger/codespan-style-writer.git#7ff3cb9013bf8320c151388cd76dfe254b325f0c" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + [[package]] name = "color" version = "0.3.2" @@ -956,31 +960,31 @@ dependencies = [ [[package]] name = "console" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d" +checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" dependencies = [ "encode_unicode", "libc", "once_cell", "unicode-width", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "convert_case" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" dependencies = [ "unicode-segmentation", ] [[package]] name = "convert_case" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] @@ -998,9 +1002,9 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc4bff745c9b4c7fb1e97b25d13153da2bc7796260141df62378998d070207f" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" dependencies = [ "cookie", "document-features", @@ -1222,9 +1226,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-common" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", @@ -1250,7 +1254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1260,14 +1264,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "ctrlc" -version = "3.5.1" +version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73736a89c4aff73035ba2ed2e565061954da00d4970fc9ac25dcc85a2a20d790" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", "nix", @@ -1311,23 +1315,24 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case 0.7.1", + "convert_case 0.10.0", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version", + "syn 2.0.117", ] [[package]] @@ -1378,14 +1383,14 @@ dependencies = [ [[package]] name = "dispatch2" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags 2.11.0", - "block2 0.6.1", + "block2 0.6.2", "libc", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -1396,23 +1401,23 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "dlib" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ - "libloading 0.8.8", + "libloading 0.8.9", ] [[package]] name = "document-features" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" dependencies = [ "litrs", ] @@ -1444,7 +1449,7 @@ dependencies = [ [[package]] name = "dpi" version = "0.1.2" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "serde", ] @@ -1486,7 +1491,7 @@ dependencies = [ "dyn-any", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1525,9 +1530,9 @@ dependencies = [ [[package]] name = "endi" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" +checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" [[package]] name = "enumflags2" @@ -1547,14 +1552,14 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "env_filter" -version = "0.1.3" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log", "regex", @@ -1562,11 +1567,11 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ - "anstream", + "anstream 0.6.21", "anstyle", "env_filter", "jiff", @@ -1581,22 +1586,23 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", + "serde_core", "typeid", ] [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1607,9 +1613,9 @@ checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59" [[package]] name = "euclid" -version = "0.22.11" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" +checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" dependencies = [ "num-traits", ] @@ -1682,16 +1688,21 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.60.2", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + [[package]] name = "fixedbitset" version = "0.5.7" @@ -1700,9 +1711,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.2" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1734,9 +1745,9 @@ checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "font-types" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "511e2c18a516c666d27867d2f9821f76e7d591f762e9fc41dd6cc5c90fe54b0b" +checksum = "39a654f404bbcbd48ea58c617c2993ee91d1cb63727a37bf2323a4edeed1b8c5" dependencies = [ "bytemuck", ] @@ -1784,7 +1795,7 @@ dependencies = [ "icu_locale_core", "linebender_resource_handle", "memmap2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-core-text", "objc2-foundation 0.3.2", @@ -1814,7 +1825,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1859,9 +1870,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1874,9 +1885,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1884,15 +1895,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1912,9 +1923,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -1931,32 +1942,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1966,7 +1977,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1982,12 +1992,12 @@ dependencies = [ [[package]] name = "gethostname" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -2001,46 +2011,53 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", - "wasi 0.14.3+wasi-0.2.4", + "r-efi 5.3.0", + "wasip2", "wasm-bindgen", ] [[package]] -name = "gif" -version = "0.13.3" +name = "getrandom" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ - "color_quant", - "weezl", + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", ] [[package]] -name = "gimli" -version = "0.31.1" +name = "gif" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e" +dependencies = [ + "color_quant", + "weezl", +] [[package]] name = "gl_generator" @@ -2312,7 +2329,7 @@ dependencies = [ "graphite-desktop-wrapper", "lzma-rust2", "muda", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-foundation 0.3.2", "open", @@ -2435,7 +2452,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -2471,9 +2488,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -2490,15 +2507,16 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "bytemuck", "cfg-if", "crunchy", "num-traits", "serde", + "zerocopy", ] [[package]] @@ -2527,9 +2545,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "foldhash 0.2.0", ] @@ -2570,12 +2588,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -2610,9 +2627,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", @@ -2648,14 +2665,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -2696,7 +2712,7 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -2710,9 +2726,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2720,7 +2736,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -2734,9 +2750,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -2747,12 +2763,13 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", + "serde", "tinystr", "writeable", "zerovec", @@ -2760,11 +2777,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -2775,42 +2791,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2818,6 +2830,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "idna" version = "1.1.0" @@ -2841,16 +2859,17 @@ dependencies = [ [[package]] name = "image" -version = "0.25.6" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", "color_quant", "gif", + "moxcms", "num-traits", - "png", + "png 0.18.1", "zune-core", "zune-jpeg", ] @@ -2882,19 +2901,21 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", + "serde", + "serde_core", ] [[package]] name = "indicatif" -version = "0.18.0" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" +checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ "console", "portable-atomic", @@ -2914,9 +2935,9 @@ dependencies = [ [[package]] name = "inotify" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" +checksum = "bd5b3eaf1a28b758ac0faa5a4254e8ab2705605496f1b1f3fbbc3988ad73d199" dependencies = [ "bitflags 2.11.0", "inotify-sys", @@ -2952,28 +2973,17 @@ dependencies = [ "wgpu-executor", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags 2.11.0", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -3000,9 +3010,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -3015,32 +3025,32 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.15" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be1f93b8b1eb69c77f24bbb0afdf66f54b632ee39af40ca21c4365a1d7347e49" +checksum = "1a3546dc96b6d42c5f24902af9e2538e82e39ad350b0c766eb3fbf2d8f3d8359" dependencies = [ "jiff-static", "log", "portable-atomic", "portable-atomic-util", - "serde", + "serde_core", ] [[package]] name = "jiff-static" -version = "0.2.15" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" +checksum = "2a8c8b344124222efd714b73bb41f8b5120b27a7cc1c75593a6ff768d9d05aa4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3071,7 +3081,7 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] @@ -3087,9 +3097,9 @@ dependencies = [ [[package]] name = "keyboard-types" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cea01d04c8251f945a9f16c5364da6cdb8bce69a61382663302c62f4186d13" +checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" dependencies = [ "bitflags 2.11.0", "serde", @@ -3102,7 +3112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.8.8", + "libloading 0.8.9", "pkg-config", ] @@ -3150,6 +3160,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + [[package]] name = "libbz2-rs-sys" version = "0.2.2" @@ -3158,18 +3174,18 @@ checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" [[package]] name = "libc" -version = "0.2.175" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link", ] [[package]] @@ -3179,24 +3195,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" dependencies = [ "cfg-if", - "windows-link 0.2.1", + "windows-link", ] [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ "bitflags 2.11.0", "libc", - "redox_syscall", + "plain", + "redox_syscall 0.7.3", ] [[package]] @@ -3220,29 +3237,28 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "litrs" -version = "0.4.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] @@ -3260,9 +3276,9 @@ checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" [[package]] name = "lyon_geom" -version = "1.0.6" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570" +checksum = "4336502e29e32af93cf2dad2214ed6003c17ceb5bd499df77b1de663b9042b92" dependencies = [ "arrayvec", "euclid", @@ -3310,7 +3326,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata", + "regex-automata 0.4.14", ] [[package]] @@ -3330,11 +3346,11 @@ dependencies = [ name = "math-parser" version = "0.0.0" dependencies = [ + "chumsky", + "codespan-reporting 0.12.0 (git+https://github.com/urisinger/codespan-style-writer.git)", "criterion", "lazy_static", "num-complex", - "pest", - "pest_derive", "thiserror 2.0.18", ] @@ -3350,15 +3366,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843a98750cd611cc2965a8213b53b43e715f13c37a9e096c6408e69990961db7" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] @@ -3405,30 +3421,40 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] -name = "muda" -version = "0.17.1" -source = "git+https://github.com/timon-schelling/muda.git?rev=e5bc28bbd6781b18afbfc237981f9ef47eddf863#e5bc28bbd6781b18afbfc237981f9ef47eddf863" -dependencies = [ +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "muda" +version = "0.17.1" +source = "git+https://github.com/timon-schelling/muda.git?rev=e5bc28bbd6781b18afbfc237981f9ef47eddf863#e5bc28bbd6781b18afbfc237981f9ef47eddf863" +dependencies = [ "crossbeam-channel", "dpi", "keyboard-types", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-foundation 0.3.2", "once_cell", - "png", + "png 0.17.16", "thiserror 2.0.18", "windows-sys 0.60.2", ] @@ -3444,16 +3470,16 @@ dependencies = [ "bitflags 2.11.0", "cfg-if", "cfg_aliases", - "codespan-reporting", + "codespan-reporting 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "half", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "hexf-parse", "indexmap", "libm", "log", "num-traits", "once_cell", - "petgraph 0.8.2", + "petgraph 0.8.3", "rustc-hash 1.1.0", "spirv", "thiserror 2.0.18", @@ -3513,15 +3539,14 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.30.1" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" dependencies = [ "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", - "memoffset", ] [[package]] @@ -3569,7 +3594,7 @@ dependencies = [ "proc-macro2", "quote", "strum", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3592,17 +3617,20 @@ dependencies = [ [[package]] name = "notify-types" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" +dependencies = [ + "bitflags 2.11.0", +] [[package]] name = "nu-ansi-term" -version = "0.50.1" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -3628,7 +3656,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3652,9 +3680,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", "rustversion", @@ -3662,14 +3690,14 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -3699,9 +3727,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] @@ -3729,8 +3757,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.11.0", - "block2 0.6.1", - "objc2 0.6.3", + "block2 0.6.2", + "objc2 0.6.4", "objc2-core-foundation", "objc2-foundation 0.3.2", ] @@ -3754,9 +3782,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.11.0", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", - "objc2 0.6.3", + "objc2 0.6.4", ] [[package]] @@ -3828,8 +3856,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.11.0", - "block2 0.6.1", - "objc2 0.6.3", + "block2 0.6.2", + "objc2 0.6.4", "objc2-core-foundation", ] @@ -3841,7 +3869,7 @@ checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.11.0", "libc", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-foundation 0.3.2", ] @@ -3878,31 +3906,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.11.0", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-foundation 0.3.2", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -3912,9 +3931,9 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "open" -version = "5.3.2" +version = "5.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95" +checksum = "43bb73a7fa3799b198970490a51174027ba0d4ec504b03cd08caf513d40024bc" dependencies = [ "is-wsl", "libc", @@ -3935,10 +3954,11 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orbclient" -version = "0.3.48" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" +checksum = "59aed3b33578edcfa1bc96a321d590d31832b6ad55a26f0313362ce687e9abd6" dependencies = [ + "libc", "libredox", ] @@ -3953,9 +3973,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.6.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +checksum = "7f4779c6901a562440c3786d08192c6fbda7c1c2060edd10006b05ee35d10f2d" dependencies = [ "num-traits", ] @@ -3987,9 +4007,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -3997,15 +4017,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -4066,50 +4086,6 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" -[[package]] -name = "pest" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" -dependencies = [ - "memchr", - "thiserror 2.0.18", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.106", -] - -[[package]] -name = "pest_meta" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" -dependencies = [ - "pest", - "sha2", -] - [[package]] name = "petgraph" version = "0.7.1" @@ -4122,9 +4098,9 @@ dependencies = [ [[package]] name = "petgraph" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54acf3a685220b533e437e264e4d932cfbdc4cc7ec0cd232ed73c08d03b8a7ca" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ "fixedbitset", "hashbrown 0.15.5", @@ -4172,7 +4148,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4192,29 +4168,29 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -4224,9 +4200,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" dependencies = [ "atomic-waker", "fastrand", @@ -4239,6 +4215,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "plist" version = "1.8.0" @@ -4247,7 +4229,7 @@ checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64", "indexmap", - "quick-xml 0.38.3", + "quick-xml 0.38.4", "serde", "time", ] @@ -4293,18 +4275,31 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.11.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "polling" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi", "pin-project-lite", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4324,24 +4319,24 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" dependencies = [ "portable-atomic", ] [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -4393,13 +4388,23 @@ dependencies = [ "yansi", ] +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit", + "toml_edit 0.25.4+spec-1.1.0", ] [[package]] @@ -4421,14 +4426,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -4439,6 +4444,12 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +[[package]] +name = "pxfm" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5a041e753da8b807c9255f28de81879c78c876392ff2469cde94799b2896b9d" + [[package]] name = "qrcodegen" version = "1.8.0" @@ -4447,18 +4458,18 @@ checksum = "4339fc7a1021c9c1621d87f5e3505f2805c8c105420ba2f2a4df86814590c142" [[package]] name = "quick-xml" -version = "0.37.5" +version = "0.38.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" +checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" dependencies = [ "memchr", ] [[package]] name = "quick-xml" -version = "0.38.3" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" dependencies = [ "memchr", ] @@ -4485,13 +4496,13 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "aws-lc-rs", "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", "rand", "ring", @@ -4521,9 +4532,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -4534,6 +4545,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.9.2" @@ -4556,18 +4573,18 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] [[package]] name = "range-alloc" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d6831663a5098ea164f89cff59c6284e95f4e3c76ce9848d4529f5ccca9bde" +checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" [[package]] name = "raster-nodes" @@ -4679,7 +4696,7 @@ checksum = "6717cf23b488adf64b9d711329542ba34de147df262370221940dfabc2c91358" dependencies = [ "bytemuck", "core_maths", - "font-types 0.10.0", + "font-types 0.10.1", ] [[package]] @@ -4692,11 +4709,30 @@ dependencies = [ "font-types 0.11.0", ] +[[package]] +name = "redox_event" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea3e412d205440c7b0218af26247226f979ed1201674cda7a33cc70609084b5" +dependencies = [ + "bitflags 2.11.0", + "libredox", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ "bitflags 2.11.0", ] @@ -4707,39 +4743,56 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 2.0.18", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.14", + "regex-syntax 0.8.10", ] [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.7.5", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.10", ] [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "regex-syntax" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "relative-path" @@ -4842,11 +4895,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" dependencies = [ "ashpd", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "js-sys", "log", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-foundation 0.3.2", @@ -4867,7 +4920,7 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -4912,12 +4965,6 @@ dependencies = [ "spirv", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "1.1.0" @@ -4933,7 +4980,7 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustc_codegen_spirv-target-specs" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=c12f216121820580731440ee79ebc7403d6ea04f#3f05f5482824e3b1fbb44c9ef90a8795a0204c7c" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=c12f216121820580731440ee79ebc7403d6ea04f#c12f216121820580731440ee79ebc7403d6ea04f" dependencies = [ "serde", "strum", @@ -4943,7 +4990,7 @@ dependencies = [ [[package]] name = "rustc_codegen_spirv-types" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=c12f216121820580731440ee79ebc7403d6ea04f#3f05f5482824e3b1fbb44c9ef90a8795a0204c7c" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=c12f216121820580731440ee79ebc7403d6ea04f#c12f216121820580731440ee79ebc7403d6ea04f" dependencies = [ "rspirv", "serde", @@ -4951,17 +4998,26 @@ dependencies = [ "spirv", ] +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4992,20 +5048,11 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -5074,12 +5121,6 @@ dependencies = [ "unicode-script", ] -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - [[package]] name = "same-file" version = "1.0.6" @@ -5091,11 +5132,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5182,11 +5223,12 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" dependencies = [ "serde", + "serde_core", ] [[package]] @@ -5201,12 +5243,13 @@ dependencies = [ [[package]] name = "serde-untagged" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34836a629bcbc6f1afdf0907a744870039b1e14c0561cb26094fa683b158eff3" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" dependencies = [ "erased-serde", "serde", + "serde_core", "typeid", ] @@ -5258,7 +5301,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5269,19 +5312,20 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -5292,7 +5336,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5357,9 +5401,9 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", "mio", @@ -5368,18 +5412,19 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" [[package]] name = "simplecss" @@ -5392,9 +5437,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "skrifa" @@ -5418,15 +5463,15 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "slotmap" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" dependencies = [ "version_check", ] @@ -5480,22 +5525,22 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.3.2" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d" +checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" dependencies = [ "borsh", - "serde", + "serde_core", ] [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5531,7 +5576,7 @@ dependencies = [ [[package]] name = "spirv-builder" version = "0.9.0" -source = "git+https://github.com/Rust-GPU/rust-gpu?rev=c12f216121820580731440ee79ebc7403d6ea04f#3f05f5482824e3b1fbb44c9ef90a8795a0204c7c" +source = "git+https://github.com/Rust-GPU/rust-gpu?rev=c12f216121820580731440ee79ebc7403d6ea04f#c12f216121820580731440ee79ebc7403d6ea04f" dependencies = [ "cargo_metadata", "clap", @@ -5569,7 +5614,7 @@ dependencies = [ "proc-macro2", "quote", "spirv-std-types", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5579,9 +5624,9 @@ source = "git+https://github.com/Firestar99/rust-gpu-new?rev=c12f216121820580731 [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -5646,7 +5691,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5695,9 +5740,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -5721,14 +5766,14 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ "bitflags 2.11.0", "core-foundation 0.9.4", @@ -5758,15 +5803,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.21.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -5844,7 +5889,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5855,7 +5900,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -5936,11 +5981,12 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", + "serde_core", "zerovec", ] @@ -5971,38 +6017,35 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.47.1" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "pin-project-lite", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", @@ -6010,9 +6053,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -6038,8 +6081,8 @@ checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.11", + "toml_edit 0.22.27", ] [[package]] @@ -6051,6 +6094,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.27" @@ -6060,11 +6112,32 @@ dependencies = [ "indexmap", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.11", "toml_write", "winnow", ] +[[package]] +name = "toml_edit" +version = "0.25.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" +dependencies = [ + "indexmap", + "toml_datetime 1.0.0+spec-1.1.0", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.9+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +dependencies = [ + "winnow", +] + [[package]] name = "toml_write" version = "0.1.2" @@ -6073,9 +6146,9 @@ checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -6118,9 +6191,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -6130,20 +6203,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -6162,14 +6235,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex-automata", + "regex-automata 0.4.14", "sharded-slab", "smallvec", "thread_local", @@ -6218,7 +6291,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6238,25 +6311,19 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "uds_windows" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +checksum = "51b70b87d15e91f553711b40df3048faf27a7a04e01e0ddc0cf9309f0af7c2ca" dependencies = [ "memoffset", "tempfile", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -6279,21 +6346,21 @@ checksum = "ce61d488bcdc9bc8b5d1772c404828b17fc481c0a582b5581e95fb233aef503e" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-properties" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" [[package]] name = "unicode-script" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" +checksum = "383ad40bb927465ec0ce7720e033cb4ca06912855fc35db31b5755d0de75b1ee" [[package]] name = "unicode-segmentation" @@ -6309,9 +6376,9 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -6321,9 +6388,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unit-prefix" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "untrusted" @@ -6333,9 +6400,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00432f493971db5d8e47a65aeb3b02f8226b9b11f1450ff86bb772776ebadd70" +checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" dependencies = [ "base64", "cookie_store", @@ -6343,7 +6410,6 @@ dependencies = [ "log", "percent-encoding", "rustls", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", @@ -6355,9 +6421,9 @@ dependencies = [ [[package]] name = "ureq-proto" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe120bb823a0061680e66e9075942fcdba06d46551548c2c259766b9558bc9a" +checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f" dependencies = [ "base64", "http", @@ -6367,14 +6433,15 @@ dependencies = [ [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", "percent-encoding", "serde", + "serde_derive", ] [[package]] @@ -6429,6 +6496,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "js-sys", + "serde_core", + "wasm-bindgen", +] + [[package]] name = "valuable" version = "0.1.1" @@ -6492,7 +6570,7 @@ dependencies = [ "futures-intrusive", "log", "peniko", - "png", + "png 0.17.16", "skrifa 0.40.0", "static_assertions", "thiserror 2.0.18", @@ -6557,10 +6635,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.3+wasi-0.2.4" +name = "wasip2" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51ae83037bdd272a9e28ce236db8c07016dd0d50c27038b3f407533c030c95" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen", ] @@ -6587,7 +6674,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -6622,7 +6709,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6636,11 +6723,45 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "wayland-backend" -version = "0.3.11" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" +checksum = "aa75f400b7f719bcd68b3f47cd939ba654cedeef690f486db71331eec4c6a406" dependencies = [ "cc", "downcast-rs", @@ -6652,9 +6773,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.11" +version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" +checksum = "ab51d9f7c071abeee76007e2b742499e535148035bb835f97aaed1338cf516c3" dependencies = [ "bitflags 2.11.0", "rustix", @@ -6675,9 +6796,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.11" +version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" +checksum = "4b3298683470fbdc6ca40151dfc48c8f2fd4c41a26e13042f801f85002384091" dependencies = [ "rustix", "wayland-client", @@ -6686,9 +6807,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.9" +version = "0.32.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901" +checksum = "b23b5df31ceff1328f06ac607591d5ba360cf58f90c8fad4ac8d3a55a3c4aec7" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6711,9 +6832,9 @@ dependencies = [ [[package]] name = "wayland-protocols-misc" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +checksum = "429b99200febaf95d4f4e46deff6fe4382bcff3280ee16a41cf887b3c3364984" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6724,9 +6845,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032" +checksum = "d392fc283a87774afc9beefcd6f931582bb97fe0e6ced0b306a62cb1d026527c" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6737,9 +6858,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec" +checksum = "78248e4cc0eff8163370ba5c158630dcae1f3497a586b826eca2ef5f348d6235" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -6750,20 +6871,20 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.7" +version = "0.31.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3" +checksum = "c86287151a309799b821ca709b7345a048a2956af05957c89cb824ab919fa4e3" dependencies = [ "proc-macro2", - "quick-xml 0.37.5", + "quick-xml 0.39.2", "quote", ] [[package]] name = "wayland-sys" -version = "0.31.7" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142" +checksum = "374f6b70e8e0d6bf9461a32988fd553b59ff630964924dad6e4a4eb6bd538d17" dependencies = [ "dlib", "log", @@ -6814,18 +6935,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] [[package]] name = "weezl" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "wgpu" @@ -6838,7 +6959,7 @@ dependencies = [ "cfg-if", "cfg_aliases", "document-features", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "js-sys", "log", "naga", @@ -6869,7 +6990,7 @@ dependencies = [ "bytemuck", "cfg_aliases", "document-features", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "indexmap", "log", "naga", @@ -6956,18 +7077,18 @@ dependencies = [ "gpu-alloc", "gpu-allocator", "gpu-descriptor", - "hashbrown 0.16.0", + "hashbrown 0.16.1", "js-sys", "khronos-egl", "libc", - "libloading 0.8.8", + "libloading 0.8.9", "log", "metal", "naga", "ndk-sys", "objc", "once_cell", - "ordered-float 4.6.0", + "ordered-float 5.1.0", "parking_lot", "portable-atomic", "portable-atomic-util", @@ -7016,11 +7137,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7031,16 +7152,16 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "window_clipboard" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5793d0b08c9e6a1240fe9ab2bd8db277487bf92436fd1a6321861a90a1b0cb7e" +checksum = "d5654226305eaf2dde8853fb482861d28e5dcecbbd40cb88e8393d94bb80d733" dependencies = [ "clipboard-win", "clipboard_macos", "clipboard_wayland", "clipboard_x11", "raw-window-handle", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -7068,15 +7189,15 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement 0.60.2", "windows-interface 0.59.3", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-link", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -7087,7 +7208,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7098,7 +7219,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7109,7 +7230,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7120,15 +7241,9 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" @@ -7137,13 +7252,13 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-registry" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", + "windows-link", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -7157,11 +7272,11 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -7176,11 +7291,11 @@ dependencies = [ [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -7216,7 +7331,7 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] @@ -7225,7 +7340,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -7261,19 +7376,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.1.3", - "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", + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -7290,9 +7405,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -7308,9 +7423,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -7326,9 +7441,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -7338,9 +7453,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -7356,9 +7471,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -7374,9 +7489,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -7392,9 +7507,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -7410,14 +7525,14 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", "cfg_aliases", @@ -7443,8 +7558,8 @@ dependencies = [ [[package]] name = "winit-android" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "android-activity", "bitflags 2.11.0", @@ -7458,14 +7573,14 @@ dependencies = [ [[package]] name = "winit-appkit" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "dpi", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-app-kit 0.3.2", "objc2-core-foundation", "objc2-core-graphics", @@ -7480,11 +7595,12 @@ dependencies = [ [[package]] name = "winit-common" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ + "block2 0.6.2", "memmap2", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "smol_str", "tracing", @@ -7495,8 +7611,8 @@ dependencies = [ [[package]] name = "winit-core" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", "cursor-icon", @@ -7510,14 +7626,15 @@ dependencies = [ [[package]] name = "winit-orbital" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", "dpi", + "libredox", "orbclient", "raw-window-handle", - "redox_syscall", + "redox_event", "smol_str", "tracing", "winit-core", @@ -7525,14 +7642,14 @@ dependencies = [ [[package]] name = "winit-uikit" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", - "block2 0.6.1", + "block2 0.6.2", "dispatch2", "dpi", - "objc2 0.6.3", + "objc2 0.6.4", "objc2-core-foundation", "objc2-foundation 0.3.2", "objc2-ui-kit", @@ -7546,14 +7663,14 @@ dependencies = [ [[package]] name = "winit-wayland" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ - "ahash", "bitflags 2.11.0", "calloop", "cursor-icon", "dpi", + "foldhash 0.2.0", "libc", "memmap2", "raw-window-handle", @@ -7572,8 +7689,8 @@ dependencies = [ [[package]] name = "winit-web" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "atomic-waker", "bitflags 2.11.0", @@ -7594,8 +7711,8 @@ dependencies = [ [[package]] name = "winit-win32" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", "cursor-icon", @@ -7604,14 +7721,14 @@ dependencies = [ "smol_str", "tracing", "unicode-segmentation", - "windows-sys 0.59.0", + "windows-sys 0.61.2", "winit-core", ] [[package]] name = "winit-x11" -version = "0.30.12" -source = "git+https://github.com/rust-windowing/winit.git#bd6fef1d80ba063cbe91e150b3fb343927cdc72b" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git#5e2f421e346cae601a6211b43ff7a2f7c8e61a46" dependencies = [ "bitflags 2.11.0", "bytemuck", @@ -7633,9 +7750,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] @@ -7651,15 +7768,97 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.45.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052283831dbae3d879dc7f51f3d92703a316ca49f91540417d38591826127814" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "x11-dl" @@ -7681,7 +7880,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading 0.8.8", + "libloading 0.8.9", "once_cell", "rustix", "x11rb-protocol", @@ -7696,9 +7895,9 @@ checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] name = "xattr" -version = "1.5.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", "rustix", @@ -7731,9 +7930,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.27" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" [[package]] name = "xmlwriter" @@ -7766,11 +7965,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -7778,21 +7976,21 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "synstructure", ] [[package]] name = "zbus" -version = "5.10.0" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a073be99ace1adc48af593701c8015cd9817df372e14a1a6b0ee8f8bf043be" +checksum = "ca82f95dbd3943a40a53cfded6c2d0a2ca26192011846a1810c4256ef92c60bc" dependencies = [ "async-broadcast", "async-executor", @@ -7808,13 +8006,15 @@ dependencies = [ "futures-core", "futures-lite", "hex", - "nix", + "libc", "ordered-stream", + "rustix", "serde", "serde_repr", "tracing", "uds_windows", - "windows-sys 0.60.2", + "uuid", + "windows-sys 0.61.2", "winnow", "zbus_macros", "zbus_names", @@ -7823,14 +8023,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "5.10.0" +version = "5.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e80cd713a45a49859dcb648053f63265f4f2851b6420d47a958e5697c68b131" +checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "zbus_names", "zvariant", "zvariant_utils", @@ -7838,12 +8038,11 @@ dependencies = [ [[package]] name = "zbus_names" -version = "4.2.0" +version = "4.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" +checksum = "ffd8af6d5b78619bab301ff3c560a5bd22426150253db278f164d6cf3b72c50f" dependencies = [ "serde", - "static_assertions", "winnow", "zvariant", ] @@ -7856,22 +8055,22 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7891,21 +8090,21 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -7914,10 +8113,11 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ + "serde", "yoke", "zerofrom", "zerovec-derive", @@ -7925,35 +8125,41 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zune-core" -version = "0.4.12" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-jpeg" -version = "0.4.20" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089" +checksum = "ec5f41c76397b7da451efd19915684f727d7e1d516384ca6bd0ec43ec94de23c" dependencies = [ "zune-core", ] [[package]] name = "zvariant" -version = "5.7.0" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999dd3be73c52b1fccd109a4a81e4fcd20fab1d3599c8121b38d04e1419498db" +checksum = "5708299b21903bbe348e94729f22c49c55d04720a004aa350f1f9c122fd2540b" dependencies = [ "endi", "enumflags2", @@ -7966,26 +8172,26 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "5.7.0" +version = "5.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6643fd0b26a46d226bd90d3f07c1b5321fe9bb7f04673cb37ac6d6883885b68e" +checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "zvariant_utils", ] [[package]] name = "zvariant_utils" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599" +checksum = "f75c23a64ef8f40f13a6989991e643554d9bef1d682a281160cf0c1bc389c5e9" dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.106", + "syn 2.0.117", "winnow", ] diff --git a/frontend/wrapper/src/editor_wrapper.rs b/frontend/wrapper/src/editor_wrapper.rs index 13fdca90de..a971f0ffb2 100644 --- a/frontend/wrapper/src/editor_wrapper.rs +++ b/frontend/wrapper/src/editor_wrapper.rs @@ -917,9 +917,9 @@ pub fn is_platform_native() -> bool { #[wasm_bindgen(js_name = evaluateMathExpression)] pub fn evaluate_math_expression(expression: &str) -> Option { let value = math_parser::evaluate(expression) - .inspect_err(|err| error!("Math parser error on \"{expression}\": {err}")) + // TODO: Render to html here + .inspect_err(|err| error!("Math parser error on \"{expression}\"")) .ok()? - .0 .inspect_err(|err| error!("Math evaluate error on \"{expression}\": {err} ")) .ok()?; let Some(real) = value.as_real() else { diff --git a/libraries/math-parser/Cargo.toml b/libraries/math-parser/Cargo.toml index 3a0424b9ac..200c89e8da 100644 --- a/libraries/math-parser/Cargo.toml +++ b/libraries/math-parser/Cargo.toml @@ -8,11 +8,11 @@ description = "Parser for Graphite style mathematics expressions" license = "MIT OR Apache-2.0" [dependencies] -pest = "2.7" -pest_derive = "2.7" thiserror = "2.0" lazy_static = "1.5" num-complex = "0.4" +chumsky = { version = "0.10", default-features = false, features = ["std"] } +codespan-reporting = { git = "https://github.com/urisinger/codespan-style-writer.git"} [dev-dependencies] criterion = { workspace = true } diff --git a/libraries/math-parser/benches/bench.rs b/libraries/math-parser/benches/bench.rs index 68c158b13f..668cf3ce4e 100644 --- a/libraries/math-parser/benches/bench.rs +++ b/libraries/math-parser/benches/bench.rs @@ -9,7 +9,7 @@ macro_rules! generate_benchmarks { $( c.bench_function(concat!("parse ", $input), |b| { b.iter(|| { - let _ = black_box(ast::Node::try_parse_from_str($input)).unwrap(); + let _ = black_box(ast::Node::try_parse_from_str($input)); }); }); )* @@ -17,7 +17,13 @@ macro_rules! generate_benchmarks { fn evaluation_bench(c: &mut Criterion) { $( - let expr = ast::Node::try_parse_from_str($input).unwrap().0; + let expr = match ast::Node::try_parse_from_str($input) { + Ok(expr) => expr, + Err(err) => { + err.print(); + panic!(concat!("failed to parse `", $input, "`")); + } + }; let context = EvalContext::default(); c.bench_function(concat!("eval ", $input), |b| { diff --git a/libraries/math-parser/src/ast.rs b/libraries/math-parser/src/ast.rs index 4c42fc4b1d..4b4c0be625 100644 --- a/libraries/math-parser/src/ast.rs +++ b/libraries/math-parser/src/ast.rs @@ -37,7 +37,7 @@ impl Unit { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub enum Literal { Float(f64), Complex(Complex), @@ -54,8 +54,19 @@ pub enum BinaryOp { Add, Sub, Mul, + /// Logical AND (nonzero treated as true, returns 1.0 or 0.0) + And, Div, + /// Logical OR (nonzero treated as true, returns 1.0 or 0.0) + Or, + Modulo, Pow, + Leq, + Lt, + Geq, + Gt, + Neq, + Eq, } #[derive(Debug, PartialEq, Clone, Copy)] @@ -63,6 +74,7 @@ pub enum UnaryOp { Neg, Sqrt, Fac, + Not, } #[derive(Debug, PartialEq)] @@ -72,4 +84,5 @@ pub enum Node { FnCall { name: String, expr: Vec }, BinOp { lhs: Box, op: BinaryOp, rhs: Box }, UnaryOp { expr: Box, op: UnaryOp }, + Conditional { condition: Box, if_block: Box, else_block: Box }, } diff --git a/libraries/math-parser/src/constants.rs b/libraries/math-parser/src/constants.rs index c010d13253..d2ea380f3f 100644 --- a/libraries/math-parser/src/constants.rs +++ b/libraries/math-parser/src/constants.rs @@ -2,13 +2,21 @@ use crate::value::{Number, Value}; use lazy_static::lazy_static; use num_complex::{Complex, ComplexFloat}; use std::collections::HashMap; -use std::f64::consts::PI; +use std::f64::consts::{LN_2, PI}; type FunctionImplementation = Box Option + Send + Sync>; lazy_static! { pub static ref DEFAULT_FUNCTIONS: HashMap<&'static str, FunctionImplementation> = { let mut map: HashMap<&'static str, FunctionImplementation> = HashMap::new(); + map.insert( + "sqrt", + Box::new(|values| match values{ + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.sqrt()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.sqrt()))), + _ => None, + }) + ); map.insert( "sin", Box::new(|values| match values { @@ -63,6 +71,7 @@ lazy_static! { }), ); + // Inverse trig with legacy names and standard aliases map.insert( "invsin", Box::new(|values| match values { @@ -71,6 +80,14 @@ lazy_static! { _ => None, }), ); + map.insert( + "asin", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.asin()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.asin()))), + _ => None, + }), + ); map.insert( "invcos", @@ -80,6 +97,14 @@ lazy_static! { _ => None, }), ); + map.insert( + "acos", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.acos()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.acos()))), + _ => None, + }), + ); map.insert( "invtan", @@ -89,6 +114,14 @@ lazy_static! { _ => None, }), ); + map.insert( + "atan", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.atan()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.atan()))), + _ => None, + }), + ); map.insert( "invcsc", @@ -98,6 +131,14 @@ lazy_static! { _ => None, }), ); + map.insert( + "acsc", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().asin()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().asin()))), + _ => None, + }), + ); map.insert( "invsec", @@ -107,12 +148,486 @@ lazy_static! { _ => None, }), ); + map.insert( + "asec", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().acos()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().acos()))), + _ => None, + }), + ); map.insert( "invcot", Box::new(|values| match values { - [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real((PI / 2.0 - real).atan()))), - [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex((Complex::new(PI / 2.0, 0.0) - complex).atan()))), + [Value::Number(Number::Real(real))] => { + Some(Value::Number(Number::Real(real.recip().atan()))) + } + [Value::Number(Number::Complex(complex))] => { + Some(Value::Number(Number::Complex(complex.recip().atan()))) + } + _ => None, + }), + ); + map.insert( + "acot", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => { + Some(Value::Number(Number::Real(real.recip().atan()))) + } + [Value::Number(Number::Complex(complex))] => { + Some(Value::Number(Number::Complex(complex.recip().atan()))) + } + _ => None, + }), + ); + // Hyperbolic Functions + map.insert( + "sinh", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.sinh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.sinh()))), + _ => None, + }), + ); + + map.insert( + "cosh", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.cosh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.cosh()))), + _ => None, + }), + ); + + map.insert( + "tanh", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.tanh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.tanh()))), + _ => None, + }), + ); + + // Reciprocal hyperbolic functions + map.insert( + "csch", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.sinh().recip()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.sinh().recip()))), + _ => None, + }), + ); + + map.insert( + "sech", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.cosh().recip()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.cosh().recip()))), + _ => None, + }), + ); + + map.insert( + "coth", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.tanh().recip()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.tanh().recip()))), + _ => None, + }), + ); + + // Inverse Hyperbolic Functions + map.insert( + "asinh", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.asinh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.asinh()))), + _ => None, + }), + ); + + map.insert( + "acosh", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.acosh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.acosh()))), + _ => None, + }), + ); + + map.insert( + "atanh", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.atanh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.atanh()))), + _ => None, + }), + ); + + // Inverse reciprocal hyperbolic functions + map.insert( + "acsch", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().asinh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().asinh()))), + _ => None, + }), + ); + + map.insert( + "asech", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().acosh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().acosh()))), + _ => None, + }), + ); + + map.insert( + "acoth", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().atanh()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().atanh()))), + _ => None, + }), + ); + + // Logarithm Functions + map.insert( + "ln", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.ln()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.ln()))), + _ => None, + }), + ); + + // Exponential / power helpers + map.insert( + "exp", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.exp()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.exp()))), + _ => None, + }), + ); + + map.insert( + "pow", + Box::new(|values| match values { + [Value::Number(Number::Real(x)), Value::Number(Number::Real(n))] => { + Some(Value::Number(Number::Real(x.powf(*n)))) + } + [Value::Number(Number::Complex(x)), Value::Number(Number::Real(n))] => { + Some(Value::Number(Number::Complex(x.powf(*n)))) + } + [Value::Number(Number::Complex(x)), Value::Number(Number::Complex(n))] => { + Some(Value::Number(Number::Complex(x.powc(*n)))) + } + _ => None, + }), + ); + + map.insert( + "root", + Box::new(|values| match values { + [Value::Number(Number::Real(x)), Value::Number(Number::Real(n))] => { + Some(Value::Number(Number::Real(x.powf(1.0 / *n)))) + } + [Value::Number(Number::Complex(x)), Value::Number(Number::Real(n))] => { + Some(Value::Number(Number::Complex(x.powf(1.0 / *n)))) + } + _ => None, + }), + ); + + map.insert( + "log", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.log10()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.log10()))), + [Value::Number(n), Value::Number(base)] => { + // Custom base logarithm using change of base formula + let compute_log = |x: f64, b: f64| -> f64 { x.ln() / b.ln() }; + match (n, base) { + (Number::Real(x), Number::Real(b)) => Some(Value::Number(Number::Real(compute_log(*x, *b)))), + _ => None, + } + } + _ => None, + }), + ); + + map.insert( + "log2", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.log2()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex / LN_2))), + _ => None, + }), + ); + + // Root Functions + map.insert( + "sqrt", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.sqrt()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.sqrt()))), + _ => None, + }), + ); + + map.insert( + "cbrt", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.cbrt()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.powf(1.0/3.0)))), + _ => None, + }), + ); + + // Geometry Functions + map.insert( + "hypot", + Box::new(|values| match values { + [Value::Number(Number::Real(a)), Value::Number(Number::Real(b))] => { + Some(Value::Number(Number::Real(a.hypot(*b)))) + }, + _ => None, + }), + ); + + map.insert( + "atan2", + Box::new(|values| match values { + [Value::Number(Number::Real(y)), Value::Number(Number::Real(x))] => { + Some(Value::Number(Number::Real(y.atan2(*x)))) + } + _ => None, + }), + ); + + // Mapping Functions + map.insert( + "abs", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.abs()))), + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Real(complex.abs()))), + _ => None, + }), + ); + + map.insert( + "floor", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.floor()))), + _ => None, + }), + ); + + map.insert( + "ceil", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.ceil()))), + _ => None, + }), + ); + + map.insert( + "round", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.round()))), + _ => None, + }), + ); + + map.insert( + "clamp", + Box::new(|values| match values { + [Value::Number(Number::Real(x)), Value::Number(Number::Real(min)), Value::Number(Number::Real(max))] => { + Some(Value::Number(Number::Real(x.clamp(*min, *max)))) + }, + _ => None, + }), + ); + + map.insert( + "lerp", + Box::new(|values| match values { + [Value::Number(Number::Real(a)), Value::Number(Number::Real(b)), Value::Number(Number::Real(t))] => { + Some(Value::Number(Number::Real(a + (b - a) * t))) + }, + _ => None, + }), + ); + + map.insert( + "remap", + Box::new(|values| match values { + [ + Value::Number(Number::Real(value)), + Value::Number(Number::Real(in_a)), + Value::Number(Number::Real(in_b)), + Value::Number(Number::Real(out_a)), + Value::Number(Number::Real(out_b)), + ] => { + let t = (*value - *in_a) / (*in_b - *in_a); + Some(Value::Number(Number::Real(out_a + t * (out_b - out_a)))) + } + _ => None, + }), + ); + + map.insert( + "trunc", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.trunc()))), + _ => None, + }), + ); + + map.insert( + "fract", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.fract()))), + _ => None, + }), + ); + + map.insert( + "sign", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => { + let s = if *real > 0.0 { + 1.0 + } else if *real < 0.0 { + -1.0 + } else { + 0.0 + }; + Some(Value::Number(Number::Real(s))) + } + _ => None, + }), + ); + + map.insert( + "gcd", + Box::new(|values| match values { + [Value::Number(Number::Real(a)), Value::Number(Number::Real(b))] => { + let mut x = a.trunc() as i64; + let mut y = b.trunc() as i64; + if x == 0 && y == 0 { + return Some(Value::Number(Number::Real(0.0))); + } + x = x.abs(); + y = y.abs(); + while y != 0 { + let r = x % y; + x = y; + y = r; + } + Some(Value::Number(Number::Real(x as f64))) + } + _ => None, + }), + ); + + map.insert( + "lcm", + Box::new(|values| match values { + [Value::Number(Number::Real(a)), Value::Number(Number::Real(b))] => { + let mut x = a.trunc() as i64; + let mut y = b.trunc() as i64; + x = x.abs(); + y = y.abs(); + if x == 0 || y == 0 { + return Some(Value::Number(Number::Real(0.0))); + } + + // gcd + let mut gx = x; + let mut gy = y; + while gy != 0 { + let r = gx % gy; + gx = gy; + gy = r; + } + let lcm = (x / gx) * y; + Some(Value::Number(Number::Real(lcm as f64))) + } + _ => None, + }), + ); + + // Complex Number Functions + map.insert( + "real", + Box::new(|values| match values { + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Real(complex.re))), + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(*real))), + _ => None, + }), + ); + + map.insert( + "imag", + Box::new(|values| match values { + [Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Real(complex.im))), + [Value::Number(Number::Real(_))] => Some(Value::Number(Number::Real(0.0))), + _ => None, + }), + ); + + map.insert( + "conj", + Box::new(|values| match values { + [Value::Number(Number::Complex(complex))] => { + Some(Value::Number(Number::Complex(complex.conj()))) + } + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(*real))), + _ => None, + }), + ); + + map.insert( + "arg", + Box::new(|values| match values { + [Value::Number(Number::Complex(complex))] => { + Some(Value::Number(Number::Real(complex.arg()))) + } + [Value::Number(Number::Real(real))] => { + let angle = if *real >= 0.0 { 0.0 } else { PI }; + Some(Value::Number(Number::Real(angle))) + } + _ => None, + }), + ); + + // Logical Functions + map.insert( + "isnan", + Box::new(|values| match values { + [Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(if real.is_nan() { 1.0 } else { 0.0 }))), + _ => None, + }), + ); + + map.insert( + "eq", + Box::new(|values| match values { + [Value::Number(a), Value::Number(b)] => Some(Value::Number(Number::Real(if a == b { 1.0 } else { 0.0 }))), + _ => None, + }), + ); + + map.insert( + "greater", + Box::new(|values| match values { + [Value::Number(Number::Real(a)), Value::Number(Number::Real(b))] => { + Some(Value::Number(Number::Real(if a > b { 1.0 } else { 0.0 }))) + }, _ => None, }), ); diff --git a/libraries/math-parser/src/diagnostic.rs b/libraries/math-parser/src/diagnostic.rs new file mode 100644 index 0000000000..2d7d4874d6 --- /dev/null +++ b/libraries/math-parser/src/diagnostic.rs @@ -0,0 +1,159 @@ +use std::io::{self, Write}; + +use codespan_reporting::{ + diagnostic::{Diagnostic, Label, LabelStyle, Severity}, + files::{self, Files, SimpleFile, SimpleFiles}, + term::{ + self, Config, Renderer, RichDiagnostic, emit, + termcolor::{ColorChoice, StandardStream}, + }, +}; + +use crate::lexer::Span; + +pub struct CompileError { + pub file: SimpleFile, + pub diagnostics: Vec>, +} + +impl CompileError { + pub fn print(&self) { + let mut writer = StandardStream::stderr(ColorChoice::Auto); + let config = term::Config::default(); + for diag in &self.diagnostics { + term::emit(&mut writer.lock(), &config, &self.file, diag).unwrap(); + } + writer.flush(); + } + + pub fn render_html(&self, config: &Config) -> Result, files::Error> { + let mut buf = Vec::new(); + { + let mut html_writer = HtmlWriter::new(&mut buf); + + let mut renderer = Renderer::new(&mut html_writer, config); + for diag in &self.diagnostics { + RichDiagnostic::new(diag, config).render(&self.file, &mut renderer)?; + } + html_writer.close_span().expect("buffer writer cant fail"); + } + + Ok(buf) + } +} + +pub(crate) fn make_compile_error(filename: impl Into, src: &str, errs: impl IntoIterator)>) -> CompileError { + let file = SimpleFile::new(filename.into(), src.to_string()); + + let diagnostics = errs.into_iter().map(|(msg, primary, secondaries)| make_diagnostic(msg, primary, &secondaries)).collect(); + + CompileError { file, diagnostics } +} + +fn make_diagnostic(msg: impl Into, primary: Span, secondaries: &[(String, Span)]) -> Diagnostic<()> { + let msg_str = msg.into(); + let mut labels = vec![Label::primary((), primary).with_message(msg_str.clone())]; + for (smsg, span) in secondaries { + labels.push(Label::secondary((), *span).with_message(smsg.clone())); + } + Diagnostic::error().with_message(msg_str).with_labels(labels) +} + +struct HtmlWriter { + upstream: W, + span_open: bool, +} + +impl HtmlWriter { + pub fn new(upstream: W) -> Self { + HtmlWriter { upstream, span_open: false } + } + + /// Close any open span + fn close_span(&mut self) -> io::Result<()> { + if self.span_open { + write!(self.upstream, "")?; + self.span_open = false; + } + Ok(()) + } + + /// Open a new span with the given CSS class + fn open_span(&mut self, class: &str) -> io::Result<()> { + // close existing first + self.close_span()?; + write!(self.upstream, "", class)?; + self.span_open = true; + Ok(()) + } +} + +impl Write for HtmlWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + let mut last = 0; + for (i, &b) in buf.iter().enumerate() { + let escape = match b { + b'<' => b"<"[..].as_ref(), + b'>' => b">"[..].as_ref(), + b'&' => b"&"[..].as_ref(), + _ => continue, + }; + self.upstream.write_all(&buf[last..i])?; + self.upstream.write_all(escape)?; + last = i + 1; + } + self.upstream.write_all(&buf[last..])?; + Ok(buf.len()) + } + fn flush(&mut self) -> io::Result<()> { + self.upstream.flush() + } +} + +impl codespan_reporting::term::WriteStyle for HtmlWriter { + fn set_header(&mut self, severity: Severity) -> io::Result<()> { + let class = match severity { + Severity::Bug => "header-bug", + Severity::Error => "header-error", + Severity::Warning => "header-warning", + Severity::Note => "header-note", + Severity::Help => "header-help", + }; + self.open_span(class) + } + + fn set_header_message(&mut self) -> io::Result<()> { + self.open_span("header-message") + } + + fn set_line_number(&mut self) -> io::Result<()> { + self.open_span("line-number") + } + + fn set_note_bullet(&mut self) -> io::Result<()> { + self.open_span("note-bullet") + } + + fn set_source_border(&mut self) -> io::Result<()> { + self.open_span("source-border") + } + + fn set_label(&mut self, severity: Severity, label_style: LabelStyle) -> io::Result<()> { + let sev = match severity { + Severity::Bug => "bug", + Severity::Error => "error", + Severity::Warning => "warning", + Severity::Note => "note", + Severity::Help => "help", + }; + let typ = match label_style { + LabelStyle::Primary => "primary", + LabelStyle::Secondary => "secondary", + }; + self.open_span(&format!("label-{}-{}", typ, sev)) + } + + fn reset(&mut self) -> io::Result<()> { + self.close_span() + } +} diff --git a/libraries/math-parser/src/executer.rs b/libraries/math-parser/src/executer.rs index 9d6180f1ab..f795735093 100644 --- a/libraries/math-parser/src/executer.rs +++ b/libraries/math-parser/src/executer.rs @@ -2,6 +2,7 @@ use crate::ast::{Literal, Node}; use crate::constants::DEFAULT_FUNCTIONS; use crate::context::{EvalContext, FunctionProvider, ValueProvider}; use crate::value::{Number, Value}; +use num_complex::Complex; use thiserror::Error; #[derive(Debug, Error)] @@ -24,7 +25,7 @@ impl Node { }, Node::BinOp { lhs, op, rhs } => match (lhs.eval(context)?, rhs.eval(context)?) { - (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs.binary_op(*op, rhs))), + (Value::Number(lhs), Value::Number(rhs)) => Ok(Value::Number(lhs.binary_op(*op, rhs).ok_or(EvalError::TypeError)?)), }, Node::UnaryOp { expr, op } => match expr.eval(context)? { Value::Number(num) => Ok(Value::Number(num.unary_op(*op))), @@ -32,6 +33,7 @@ impl Node { Node::Var(name) => context.get_value(name).ok_or_else(|| EvalError::MissingValue(name.clone())), Node::FnCall { name, expr } => { let values = expr.iter().map(|expr| expr.eval(context)).collect::, EvalError>>()?; + if let Some(function) = DEFAULT_FUNCTIONS.get(&name.as_str()) { function(&values).ok_or(EvalError::TypeError) } else if let Some(val) = context.run_function(name, &values) { @@ -40,6 +42,14 @@ impl Node { context.get_value(name).ok_or_else(|| EvalError::MissingFunction(name.to_string())) } } + Node::Conditional { condition, if_block, else_block } => { + let condition = match condition.eval(context)? { + Value::Number(Number::Real(number)) => number != 0.0, + Value::Number(Number::Complex(number)) => number != Complex::ZERO, + }; + + if condition { if_block.eval(context) } else { else_block.eval(context) } + } } } } diff --git a/libraries/math-parser/src/grammer.pest b/libraries/math-parser/src/grammer.pest deleted file mode 100644 index d7a61939df..0000000000 --- a/libraries/math-parser/src/grammer.pest +++ /dev/null @@ -1,60 +0,0 @@ -WHITESPACE = _{ " " | "\t" } - -// TODO: Proper indentation and formatting -program = _{ SOI ~ expr ~ EOI } - -expr = { atom ~ (infix ~ atom)* } -atom = _{ prefix? ~ primary ~ postfix? } -infix = _{ add | sub | mul | div | pow | paren } -add = { "+" } // Addition -sub = { "-" } // Subtraction -mul = { "*" } // Multiplication -div = { "/" } // Division -mod = { "%" } // Modulo -pow = { "^" } // Exponentiation -paren = { "" } // Implicit multiplication operator - -prefix = _{ neg | sqrt } -neg = { "-" } // Negation -sqrt = { "sqrt" } - -postfix = _{ fac } -fac = { "!" } // Factorial - -primary = _{ ("(" ~ expr ~ ")") | lit | constant | fn_call | ident } -fn_call = { ident ~ "(" ~ expr ~ ("," ~ expr)* ~ ")" } -ident = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } -lit = { unit | ((float | int) ~ unit?) } - -float = @{ int ~ "." ~ int? ~ exp? | int ~ exp } -exp = _{ ^"e" ~ ("+" | "-")? ~ int } -int = @{ ASCII_DIGIT+ } - -unit = ${ (scale ~ base_unit) | base_unit ~ !ident} -base_unit = _{ meter | second | gram } -meter = { "m" } -second = { "s" } -gram = { "g" } - -scale = _{ nano | micro | milli | centi | deci | deca | hecto | kilo | mega | giga | tera } -nano = { "n" } -micro = { "µ" | "u" } -milli = { "m" } -centi = { "c" } -deci = { "d" } -deca = { "da" } -hecto = { "h" } -kilo = { "k" } -mega = { "M" } -giga = { "G" } -tera = { "T" } - -// Constants -constant = { infinity | imaginary_unit | pi | tau | euler_number | golden_ratio | gravity_acceleration } -infinity = { "inf" | "INF" | "infinity" | "INFINITY" | "∞" } -imaginary_unit = { "i" | "I" } -pi = { "pi" | "PI" | "π" } -tau = { "tau" | "TAU" | "τ" } -euler_number = { "e" } -golden_ratio = { "phi" | "PHI" | "φ" } -gravity_acceleration = { "G" } diff --git a/libraries/math-parser/src/lexer.rs b/libraries/math-parser/src/lexer.rs new file mode 100644 index 0000000000..4b1e4c7a1b --- /dev/null +++ b/libraries/math-parser/src/lexer.rs @@ -0,0 +1,372 @@ +use crate::ast::Literal; +use chumsky::input::{Input, ValueInput}; +use chumsky::prelude::*; +use chumsky::span::SimpleSpan; +use chumsky::text::{ident, int}; +use core::f64; +use num_complex::Complex64; +use std::fmt; +use std::iter::Peekable; +use std::ops::Range; +use std::str::Chars; + +pub type Span = SimpleSpan; + +#[derive(Clone, Debug, PartialEq)] +pub enum Token<'src> { + Float(f64), + Const(Constant), + Ident(&'src str), + + AndAnd, + OrOr, + Bang, + + LParen, + RParen, + Comma, + Plus, + Minus, + Modulo, + Star, + Slash, + Caret, + + Lt, + Le, + Gt, + Ge, + Neq, + EqEq, + + If, +} + +impl<'src> fmt::Display for Token<'src> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Token::Float(x) => write!(f, "{x}"), + Token::Const(c) => write!(f, "{c}"), + Token::Ident(name) => write!(f, "{name}"), + + Token::AndAnd => f.write_str("&&"), + Token::OrOr => f.write_str("||"), + Token::Bang => f.write_str("!"), + + Token::LParen => f.write_str("("), + Token::RParen => f.write_str(")"), + Token::Comma => f.write_str(","), + Token::Plus => f.write_str("+"), + Token::Minus => f.write_str("-"), + Token::Modulo => f.write_str("%"), + Token::Star => f.write_str("*"), + Token::Slash => f.write_str("/"), + Token::Caret => f.write_str("^"), + + Token::Lt => f.write_str("<"), + Token::Le => f.write_str("<="), + Token::Gt => f.write_str(">"), + Token::Ge => f.write_str(">="), + Token::Neq => f.write_str("!="), + Token::EqEq => f.write_str("=="), + + Token::If => f.write_str("if"), + } + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Constant { + Pi, + Tau, + E, + Phi, + Inf, + I, + G, +} + +impl Constant { + pub fn value(self) -> Literal { + use Constant::*; + use std::f64::consts; + match self { + Pi => Literal::Float(consts::PI), + Tau => Literal::Float(consts::TAU), + E => Literal::Float(consts::E), + Phi => Literal::Float(1.618_033_988_75), + Inf => Literal::Float(f64::INFINITY), + I => Literal::Complex(Complex64::new(0.0, 1.0)), + G => Literal::Float(9.80665), + } + } + + pub fn from_str(name: &str) -> Option { + use Constant::*; + Some(match name { + "pi" | "π" => Pi, + "tau" | "τ" => Tau, + "e" => E, + "phi" | "φ" => Phi, + "inf" | "∞" => Inf, + "i" => I, + "G" => G, + _ => return None, + }) + } +} + +impl fmt::Display for Constant { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use Constant::*; + f.write_str(match self { + Pi => "pi", + Tau => "tau", + E => "e", + Phi => "phi", + Inf => "inf", + I => "i", + G => "G", + }) + } +} + +pub struct Lexer<'a> { + input: &'a str, + pos: usize, +} + +impl<'a> Lexer<'a> { + pub fn new(input: &'a str) -> Self { + Self { input, pos: 0 } + } + + fn peek(&self) -> Option { + self.input[self.pos..].chars().next() + } + + fn bump(&mut self) -> Option { + let c = self.peek()?; + self.pos += c.len_utf8(); + Some(c) + } + + fn consume_while(&mut self, cond: F) -> &'a str + where + F: Fn(char) -> bool, + { + let start = self.pos; + while self.peek().is_some_and(&cond) { + self.bump(); + } + &self.input[start..self.pos] + } + + fn lex_ident(&mut self) -> &'a str { + self.consume_while(|c| c.is_alphanumeric() || c == '_') + } + + fn lex_uint(&mut self) -> Option<(u64, usize)> { + let mut v = 0u64; + let mut digits = 0; + while let Some(d) = self.peek().and_then(|c| c.to_digit(10)) { + v = v * 10 + d as u64; + digits += 1; + self.bump(); + } + (digits > 0).then_some((v, digits)) + } + + fn lex_number(&mut self) -> Option { + let start_pos = self.pos; + let (int_val, int_digits) = self.lex_uint().unwrap_or((0, 0)); + let mut got_digit = int_digits > 0; + let mut num = int_val as f64; + + if self.peek() == Some('.') { + self.bump(); + if let Some((frac_val, frac_digits)) = self.lex_uint() { + num += (frac_val as f64) / 10f64.powi(frac_digits as i32); + got_digit = true; + } + } + + if matches!(self.peek(), Some('e' | 'E')) { + self.bump(); + let sign = match self.peek() { + Some('+') => { + self.bump(); + 1 + } + Some('-') => { + self.bump(); + -1 + } + _ => 1, + }; + if let Some((exp_val, _)) = self.lex_uint() { + num *= 10f64.powi(sign * exp_val as i32); + } else { + self.pos = start_pos; + return None; + } + } + + got_digit.then_some(num) + } + + fn skip_ws(&mut self) { + self.consume_while(char::is_whitespace); + } + + pub fn next_token(&mut self) -> Option> { + self.skip_ws(); + let start = self.pos; + let ch = self.bump()?; + + use Token::*; + let tok = match ch { + '&' => { + if self.peek() == Some('&') { + self.bump(); + AndAnd + } else { + return None; + } + } + '|' => { + if self.peek() == Some('|') { + self.bump(); + OrOr + } else { + return None; + } + } + + '(' => LParen, + ')' => RParen, + ',' => Comma, + '+' => Plus, + '-' => Minus, + '*' => Star, + '%' => Modulo, + '/' => Slash, + '^' => Caret, + '≠' => Neq, + + '!' => { + if self.peek() == Some('=') { + self.bump(); + Neq + } else { + Bang + } + } + + '≤' => Le, + '<' => { + if self.peek() == Some('=') { + self.bump(); + Le + } else { + Lt + } + } + + '≥' => Ge, + '>' => { + if self.peek() == Some('=') { + self.bump(); + Ge + } else { + Gt + } + } + '=' => { + if self.peek() == Some('=') { + self.bump(); + EqEq + } else { + return None; + } + } + + c if c.is_ascii_digit() || (c == '.' && self.peek().is_some_and(|c| c.is_ascii_digit())) => { + self.pos = start; + Float(self.lex_number()?) + } + + _ => { + self.consume_while(|c| c.is_alphanumeric() || c == '_'); + let ident = &self.input[start..self.pos]; + + if ident == "if" { + If + } else if let Some(lit) = Constant::from_str(ident) { + Const(lit) + } else if ch.is_alphanumeric() { + Ident(ident) + } else { + return None; + } + } + }; + + Some(tok) + } +} + +impl<'a> Iterator for Lexer<'a> { + type Item = Token<'a>; + + fn next(&mut self) -> Option { + self.next_token() + } +} + +impl<'src> Input<'src> for Lexer<'src> { + type Token = Token<'src>; + type Span = Span; + type Cursor = usize; // byte offset inside `input` + type MaybeToken = Token<'src>; + type Cache = Self; + + #[inline] + fn begin(self) -> (Self::Cursor, Self::Cache) { + (0, self) + } + + #[inline] + fn cursor_location(cursor: &Self::Cursor) -> usize { + *cursor + } + + #[inline] + unsafe fn next_maybe(this: &mut Self::Cache, cursor: &mut Self::Cursor) -> Option { + this.pos = *cursor; + if let Some(tok) = this.next_token() { + *cursor = this.pos; + Some(tok) + } else { + None + } + } + + #[inline] + unsafe fn span(_this: &mut Self::Cache, range: Range<&Self::Cursor>) -> Self::Span { + (*range.start..*range.end).into() + } +} + +impl<'src> ValueInput<'src> for Lexer<'src> { + #[inline] + unsafe fn next(this: &mut Self::Cache, cursor: &mut Self::Cursor) -> Option { + this.pos = *cursor; + if let Some(tok) = this.next_token() { + *cursor = this.pos; + Some(tok) + } else { + None + } + } +} diff --git a/libraries/math-parser/src/lib.rs b/libraries/math-parser/src/lib.rs index e596d78dff..6889e5b27d 100644 --- a/libraries/math-parser/src/lib.rs +++ b/libraries/math-parser/src/lib.rs @@ -3,147 +3,280 @@ pub mod ast; mod constants; pub mod context; +pub mod diagnostic; pub mod executer; +pub mod lexer; pub mod parser; pub mod value; use ast::Unit; use context::{EvalContext, ValueMap}; +use diagnostic::CompileError; use executer::EvalError; -use parser::ParseError; use value::Value; -pub fn evaluate(expression: &str) -> Result<(Result, Unit), ParseError> { +pub fn evaluate(expression: &str) -> Result, CompileError> { let expr = ast::Node::try_parse_from_str(expression); let context = EvalContext::default(); - expr.map(|(node, unit)| (node.eval(&context), unit)) + expr.map(|node| node.eval(&context)) } #[cfg(test)] mod tests { use super::*; use ast::Unit; + use codespan_reporting::term::{ + self, + termcolor::{ColorChoice, StandardStream}, + }; use value::Number; const EPSILON: f64 = 1e-10_f64; - macro_rules! test_end_to_end{ - ($($name:ident: $input:expr_2021 => ($expected_value:expr_2021, $expected_unit:expr_2021)),* $(,)?) => { - $( - #[test] - fn $name() { - let expected_value = $expected_value; - let expected_unit = $expected_unit; - - let expr = ast::Node::try_parse_from_str($input); - let context = EvalContext::default(); - - let (actual_value, actual_unit) = expr.map(|(node, unit)| (node.eval(&context), unit)).unwrap(); - let actual_value = actual_value.unwrap(); - - - assert!(actual_unit == expected_unit, "Expected unit {:?} but found unit {:?}", expected_unit, actual_unit); - - let expected_value = expected_value.into(); - - match (actual_value, expected_value) { - (Value::Number(Number::Complex(actual_c)), Value::Number(Number::Complex(expected_c))) => { - assert!( - (actual_c.re.is_infinite() && expected_c.re.is_infinite()) || (actual_c.re - expected_c.re).abs() < EPSILON, - "Expected real part {}, but got {}", - expected_c.re, - actual_c.re - ); - assert!( - (actual_c.im.is_infinite() && expected_c.im.is_infinite()) || (actual_c.im - expected_c.im).abs() < EPSILON, - "Expected imaginary part {}, but got {}", - expected_c.im, - actual_c.im - ); - } - (Value::Number(Number::Real(actual_f)), Value::Number(Number::Real(expected_f))) => { - if actual_f.is_infinite() || expected_f.is_infinite() { - assert!( - actual_f.is_infinite() && expected_f.is_infinite() && actual_f == expected_f, - "Expected infinite value {}, but got {}", - expected_f, - actual_f - ); - } else if actual_f.is_nan() || expected_f.is_nan() { - assert!(actual_f.is_nan() && expected_f.is_nan(), "Expected NaN, but got {}", actual_f); - } else { - assert!((actual_f - expected_f).abs() < EPSILON, "Expected {}, but got {}", expected_f, actual_f); - } - } - // Handle mismatched types - _ => panic!("Mismatched types: expected {:?}, got {:?}", expected_value, actual_value), - } + fn run_end_to_end_test(input: &str, expected_value: Value) { + let expr = match ast::Node::try_parse_from_str(input) { + Ok(expr) => expr, + Err(err) => { + err.print(); + panic!("failed to parse `{input}`"); + } + }; + dbg!(&expr); + let context = EvalContext::default(); - } - )* + let actual_value = match expr.eval(&context) { + Ok(v) => v, + Err(err) => panic!("failed to evaluate {input} becuase of error {err}"), }; + + // compare + match (actual_value, expected_value) { + (Value::Number(Number::Complex(a)), Value::Number(Number::Complex(e))) => { + // real part + if a.re.is_infinite() || e.re.is_infinite() { + assert!(a.re == e.re, "`{}` → real part: expected {:?}, got {:?}", input, e.re, a.re); + } else { + assert!((a.re - e.re).abs() < EPSILON, "`{}` → real part: expected {}, got {}", input, e.re, a.re); + } + + // imag part + if a.im.is_infinite() || e.im.is_infinite() { + assert!(a.im == e.im, "`{}` → imag part: expected {:?}, got {:?}", input, e.im, a.im); + } else { + assert!((a.im - e.im).abs() < EPSILON, "`{}` → imag part: expected {}, got {}", input, e.im, a.im); + } + } + + (Value::Number(Number::Real(a)), Value::Number(Number::Real(e))) => { + if a.is_infinite() || e.is_infinite() { + // both must be infinite and equal (i.e. both +∞ or both −∞) + assert!(a == e, "`{input}` → expected infinite {e:?}, got {a:?}"); + } else if a.is_nan() || e.is_nan() { + // both must be NaN + assert!(a.is_nan() && e.is_nan(), "`{input}` → expected NaN, got {a:?}"); + } else { + let diff = (a - e).abs(); + assert!(diff < EPSILON, "`{input}` → expected {e}, got {a}, Δ={diff}"); + } + } + + (got, expect) => { + panic!("`{input}` → mismatched types: expected {expect:?}, got {got:?}"); + } + } } + macro_rules! test_end_to_end { + ($($name:ident: $input:expr => $expected:expr),* $(,)?) => { + $( + #[test] + fn $name() { + run_end_to_end_test($input, ($expected).into()); + } + )* + }; + } test_end_to_end! { - // Basic arithmetic and units - infix_addition: "5 + 5" => (10., Unit::BASE_UNIT), - infix_subtraction_units: "5m - 3m" => (2., Unit::LENGTH), - infix_multiplication_units: "4s * 4s" => (16., Unit { length: 0, mass: 0, time: 2 }), - infix_division_units: "8m/2s" => (4., Unit::VELOCITY), + // Basic arithmetic + infix_addition: "5 + 5" => 10., + infix_subtraction: "5 - 3" => 2., + infix_multiplication: "4 * 4" => 16., + infix_division: "8/2" => 4., + modulo_pos_pos: "3.2 % 2" => 1.2, + modulo_pos_neg: "3.2 % -2" => 1.2, + modulo_neg_neg: "(-3.2) % -2" => -1.2, + modulo_neg_pos: "(-3.2) % 2" => -1.2, + exp_pos_pos: "3.2 ^ 2" => 256. / 25., + exp_pos_neg: "3.2 ^ -2" => 25. / 256., + exp_neg_neg: "-3.2 ^ -2" => -25. / 256., + exp_neg_pos: "-3.2 ^ 2" => -256. / 25., // Order of operations - order_of_operations_negative_prefix: "-10 + 5" => (-5., Unit::BASE_UNIT), - order_of_operations_add_multiply: "5+1*1+5" => (11., Unit::BASE_UNIT), - order_of_operations_add_negative_multiply: "5+(-1)*1+5" => (9., Unit::BASE_UNIT), - order_of_operations_sqrt: "sqrt25 + 11" => (16., Unit::BASE_UNIT), - order_of_operations_sqrt_expression: "sqrt(25+11)" => (6., Unit::BASE_UNIT), + order_of_operations_negative_prefix: "-10 + 5" => -5., + order_of_operations_add_multiply: "5+1*1+5" => 11., + order_of_operations_add_negative_multiply: "5+(-1)*1+5" => 9., + order_of_operations_sqrt: "sqrt(25) + 11" => 16., + order_of_operations_sqrt_expression: "sqrt(25+11)" => 6., // Parentheses and nested expressions - parentheses_nested_multiply: "(5 + 3) * (2 + 6)" => (64., Unit::BASE_UNIT), - parentheses_mixed_operations: "2 * (3 + 5 * (2 + 1))" => (36., Unit::BASE_UNIT), - parentheses_divide_add_multiply: "10 / (2 + 3) + (7 * 2)" => (16., Unit::BASE_UNIT), + parentheses_nested_multiply: "(5 + 3) * (2 + 6)" => 64., + parentheses_mixed_operations: "2 * (3 + 5 * (2 + 1))" => 36., + parentheses_divide_add_multiply: "10 / (2 + 3) + (7 * 2)" => 16., // Square root and nested square root - sqrt_chain_operations: "sqrt(16) + sqrt(9) * sqrt(4)" => (10., Unit::BASE_UNIT), - sqrt_nested: "sqrt(sqrt(81))" => (3., Unit::BASE_UNIT), - sqrt_divide_expression: "sqrt((25 + 11) / 9)" => (2., Unit::BASE_UNIT), + sqrt_chain_operations: "sqrt(16) + sqrt(9) * sqrt(4)" => 10., + sqrt_nested: "sqrt(sqrt(81))" => 3., + sqrt_divide_expression: "sqrt((25 + 11) / 9)" => 2., // Mixed square root and units - sqrt_multiply_units: "sqrt(16) * 2g + 5g" => (13., Unit::MASS), - sqrt_add_multiply: "sqrt(49) - 1 + 2 * 3" => (12., Unit::BASE_UNIT), - sqrt_addition_multiply: "(sqrt(36) + 2) * 2" => (16., Unit::BASE_UNIT), + sqrt_add_multiply: "sqrt(49) - 1 + 2 * 3" => 12., + sqrt_addition_multiply: "(sqrt(36) + 2) * 2" => 16., // Exponentiation - exponent_single: "2^3" => (8., Unit::BASE_UNIT), - exponent_mixed_operations: "2^3 + 4^2" => (24., Unit::BASE_UNIT), - exponent_nested: "2^(3+1)" => (16., Unit::BASE_UNIT), + exponent_single: "2^3" => 8., + exponent_mixed_operations: "2^3 + 4^2" => 24., + exponent_nested: "2^(3+1)" => 16., + + // Factorial (postfix !) + factorial_simple: "5!" => 120., + factorial_nested: "(3 + 2)!" => 120., + factorial_zero: "0!" => 1., + factorial_chain: "3!!" => 720., // (3!)! = 6! = 720 // Operations with negative values - negative_units_add_multiply: "-5s + (-3 * 2)s" => (-11., Unit::TIME), - negative_nested_parentheses: "-(5 + 3 * (2 - 1))" => (-8., Unit::BASE_UNIT), - negative_sqrt_addition: "-(sqrt(16) + sqrt(9))" => (-7., Unit::BASE_UNIT), - multiply_sqrt_subtract: "5 * 2 + sqrt(16) / 2 - 3" => (9., Unit::BASE_UNIT), - add_multiply_subtract_sqrt: "4 + 3 * (2 + 1) - sqrt(25)" => (8., Unit::BASE_UNIT), - add_sqrt_subtract_nested_multiply: "10 + sqrt(64) - (5 * (2 + 1))" => (3., Unit::BASE_UNIT), + negative_nested_parentheses: "-(5 + 3 * (2 - 1))" => -8., + negative_sqrt_addition: "-(sqrt(16) + sqrt(9))" => -7., + multiply_sqrt_subtract: "5 * 2 + sqrt(16) / 2 - 3" => 9., + add_multiply_subtract_sqrt: "4 + 3 * (2 + 1) - sqrt(25)" => 8., + add_sqrt_subtract_nested_multiply: "10 + sqrt(64) - (5 * (2 + 1))" => 3., // Mathematical constants - constant_pi: "pi" => (std::f64::consts::PI, Unit::BASE_UNIT), - constant_e: "e" => (std::f64::consts::E, Unit::BASE_UNIT), - constant_phi: "phi" => (1.61803398875, Unit::BASE_UNIT), - constant_tau: "tau" => (2.0 * std::f64::consts::PI, Unit::BASE_UNIT), - constant_infinity: "inf" => (f64::INFINITY, Unit::BASE_UNIT), - constant_infinity_symbol: "∞" => (f64::INFINITY, Unit::BASE_UNIT), - multiply_pi: "2 * pi" => (2.0 * std::f64::consts::PI, Unit::BASE_UNIT), - add_e_constant: "e + 1" => (std::f64::consts::E + 1.0, Unit::BASE_UNIT), - multiply_phi_constant: "phi * 2" => (1.61803398875 * 2.0, Unit::BASE_UNIT), - exponent_tau: "2^tau" => (2f64.powf(2.0 * std::f64::consts::PI), Unit::BASE_UNIT), - infinity_subtract_large_number: "inf - 1000" => (f64::INFINITY, Unit::BASE_UNIT), + constant_pi: "pi" => std::f64::consts::PI, + constant_e: "e" => std::f64::consts::E, + constant_phi: "phi" => 1.61803398875, + constant_tau: "tau" => 2.0 * std::f64::consts::PI, + constant_infinity: "if(inf == ∞, inf, 0)" => f64::INFINITY, + multiply_pi: "2 * pi" => 2.0 * std::f64::consts::PI, + add_e_constant: "e + 1" => std::f64::consts::E + 1.0, + multiply_phi_constant: "phi * 2" => 1.61803398875 * 2.0, + exponent_tau: "2^tau" => 2f64.powf(2.0 * std::f64::consts::PI), + infinity_subtract_large_number: "inf - 1000" => f64::INFINITY, // Trigonometric functions - trig_sin_pi: "sin(pi)" => (0.0, Unit::BASE_UNIT), - trig_cos_zero: "cos(0)" => (1.0, Unit::BASE_UNIT), - trig_tan_pi_div_four: "tan(pi/4)" => (1.0, Unit::BASE_UNIT), - trig_sin_tau: "sin(tau)" => (0.0, Unit::BASE_UNIT), - trig_cos_tau_div_two: "cos(tau/2)" => (-1.0, Unit::BASE_UNIT), + trig_sin_pi: "sin(pi)" => 0.0, + trig_cos_zero: "cos(0)" => 1.0, + trig_tan_pi_div_four: "tan(pi/4)" => 1.0, + trig_sin_tau: "sin(tau)" => 0.0, + trig_cos_tau_div_two: "cos(tau/2)" => -1.0, + trig_csc: "csc(pi/2)" => 1.0, + trig_sec: "sec(0)" => 1.0, + trig_cot: "cot(pi/4)" => 1.0, + + // Inverse trig aliases + inverse_trig_asin: "asin(1)" => std::f64::consts::FRAC_PI_2, + inverse_trig_acos: "acos(1)" => 0.0, + inverse_trig_atan: "atan(1)" => std::f64::consts::FRAC_PI_4, + inverse_trig_acsc: "acsc(1)" => std::f64::consts::FRAC_PI_2, + inverse_trig_asec: "asec(1)" => 0.0, + inverse_trig_acot: "acot(1)" => std::f64::consts::FRAC_PI_4, + + // Hyperbolic and reciprocal hyperbolic + hyperbolic_sinh: "sinh(0)" => 0.0, + hyperbolic_cosh: "cosh(0)" => 1.0, + hyperbolic_tanh: "tanh(0)" => 0.0, + hyperbolic_csch: "csch(1)" => 1f64.sinh().recip(), + hyperbolic_sech: "sech(0)" => 1.0, + hyperbolic_coth: "coth(1)" => 1f64.tanh().recip(), + + // Inverse hyperbolic + inverse_hyperbolic_asinh: "asinh(0)" => 0.0, + inverse_hyperbolic_acosh: "acosh(1)" => 0.0, + inverse_hyperbolic_atanh: "atanh(0)" => 0.0, + inverse_hyperbolic_acsch: "acsch(1)" => 1.0f64.asinh(), + inverse_hyperbolic_asech: "asech(1)" => 1.0f64.acosh(), + inverse_hyperbolic_acoth: "acoth(2)" => 0.5f64.atanh(), + + // Basic if statements + if_true_condition: "if(1,5,3)" => 5., + if_false_condition: "if(0, 5, 3)" => 3., + + // Arithmetic conditions + if_arithmetic_true: "if(2+2-4, 1 , 0)" => 0., + if_arithmetic_false: "if(3*2-5, 1, 0)" => 1., + + // Nested arithmetic + if_complex_arithmetic: "if((5+3)*(2-1), 10, 20)" => 10., + if_with_division: "if(8/4-2 == 0, 15, 25)" => 15., + if_with_division_ne: "if(8/4-2 ≠ 0, 15, 25)" => 25., + + // Constants in conditions + if_with_pi: "if(pi > 3, 1, 0)" => 1., + if_with_e: "if(e < 3, 1, 0)" => 1., + + // Functions in conditions + if_with_sqrt: "if(sqrt(16) == 4, 1, 0)" => 1., + if_with_sin: "if(sin(pi) == 0.0, 1, 0)" => 0., + + // Logical NOT (prefix !) + logical_not_zero: "!0" => 1.0, + logical_not_nonzero: "!5" => 0.0, + logical_not_expression: "!(2 - 2)" => 1.0, + + // Logical helpers as functions + logical_isnan: "isnan(0/0)" => 1.0, + logical_eq: "eq(2, 2)" => 1.0, + logical_greater: "greater(3, 2)" => 1.0, + + // Log / exp / pow / root + log_ln: "ln(e)" => 1.0, + log_log10: "log(100)" => 2.0, + log_log2: "log2(8)" => 3.0, + log_change_of_base: "log(8, 2)" => 3.0, + exp_function: "exp(1)" => std::f64::consts::E, + pow_real: "pow(2, 3)" => 8.0, + root_square: "root(9, 2)" => 3.0, + root_cube: "root(8, 3)" => 2.0, + + // Nested if statements + nested_if: "if(1, if(0, 1, 2), 3)" => 2., + nested_if_complex: "if(2-2 == 0, if(1, 5, 6), if(1, 7, 8))" => 5., + + // Mixed operations in conditions and blocks + if_complex_condition: "if(sqrt(16) + sin(pi) < 5, 2*pi, 3*e)" => 2. * std::f64::consts::PI, + if_complex_blocks: "if(1, 2*sqrt(16) + sin(pi/2), 3*cos(0) + 4)" => 9., + + // Mapping helpers + mapping_trunc: "trunc(3.7)" => 3.0, + mapping_fract: "fract(3.25)" => 0.25, + mapping_sign_pos: "sign(5)" => 1.0, + mapping_sign_neg: "sign(-5)" => -1.0, + + // Geometry / mapping extras + geometry_hypot: "hypot(3, 4)" => 5.0, + mapping_remap: "remap(5, 0, 10, 0, 100)" => 50.0, + + // GCD / LCM + gcd_simple: "gcd(24, 18)" => 6.0, + lcm_simple: "lcm(4, 6)" => 12.0, + + // atan2 + trig_atan2_axis: "atan2(1, 0)" => std::f64::consts::FRAC_PI_2, + + // Comparison operators combined with logical AND + comparison_operators: "if(1 <= 2 && 1 ≤ 2 && 2 >= 1 && 2 ≥ 1, 1., 0.)" => 1., + + // Logical AND / OR + logical_and_true: "if(1 <= 2 && 2 < 3, 1., 0.)" => 1., + logical_and_false: "if(1 <= 2 && 3 < 2, 1., 0.)" => 0., + logical_or_true_left: "if(1 > 2 || 2 < 3, 1., 0.)" => 1., + logical_or_true_right: "if(2 < 1 || 2 < 3, 1., 0.)" => 1., + logical_or_false: "if(1 > 2 || 3 < 2, 1., 0.)" => 0., + logical_precedence_and_over_or: "if(0 == 1 || 1 == 1 && 0 == 0, 1., 0.)" => 1., + + // Edge cases + if_zero: "if(0.0, 1, 2)" => 2., + + // Complex nested expressions + if_nested_expr: "if((sqrt(16) + 2) * (sin(pi) + 1), 3 + 4 * 2, 5 - 2 / 1)" => 11., } } diff --git a/libraries/math-parser/src/parser.rs b/libraries/math-parser/src/parser.rs index e707b500f4..792c3be46a 100644 --- a/libraries/math-parser/src/parser.rs +++ b/libraries/math-parser/src/parser.rs @@ -1,316 +1,158 @@ use crate::ast::{BinaryOp, Literal, Node, UnaryOp, Unit}; use crate::context::EvalContext; +use crate::diagnostic::{CompileError, make_compile_error}; +use crate::lexer::{Lexer, Span, Token}; use crate::value::{Complex, Number, Value}; +use chumsky::container::Seq; +use chumsky::input::{BorrowInput, ValueInput}; +use chumsky::{Parser, prelude::*}; use lazy_static::lazy_static; use num_complex::ComplexFloat; -use pest::Parser; -use pest::iterators::{Pair, Pairs}; -use pest::pratt_parser::{Assoc, Op, PrattParser}; -use pest_derive::Parser; use std::num::{ParseFloatError, ParseIntError}; use thiserror::Error; -#[derive(Parser)] -#[grammar = "./grammer.pest"] // Point to the grammar file -struct ExprParser; - -lazy_static! { - static ref PRATT_PARSER: PrattParser = { - PrattParser::new() - .op(Op::infix(Rule::add, Assoc::Left) | Op::infix(Rule::sub, Assoc::Left)) - .op(Op::infix(Rule::mul, Assoc::Left) | Op::infix(Rule::div, Assoc::Left) | Op::infix(Rule::paren, Assoc::Left)) - .op(Op::infix(Rule::pow, Assoc::Right)) - .op(Op::postfix(Rule::fac) | Op::postfix(Rule::EOI)) - .op(Op::prefix(Rule::sqrt)) - .op(Op::prefix(Rule::neg)) - }; -} - -#[derive(Error, Debug)] -pub enum TypeError { - #[error("Invalid BinOp: {0:?} {1:?} {2:?}")] - InvalidBinaryOp(Unit, BinaryOp, Unit), - - #[error("Invalid UnaryOp: {0:?}")] - InvalidUnaryOp(Unit, UnaryOp), -} - -#[derive(Error, Debug)] -pub enum ParseError { - #[error("ParseIntError: {0}")] - ParseInt(#[from] ParseIntError), - #[error("ParseFloatError: {0}")] - ParseFloat(#[from] ParseFloatError), - - #[error("TypeError: {0}")] - Type(#[from] TypeError), - - #[error("PestError: {0}")] - Pest(#[from] Box>), -} - impl Node { - pub fn try_parse_from_str(s: &str) -> Result<(Node, Unit), ParseError> { - let pairs = ExprParser::parse(Rule::program, s).map_err(Box::new)?; - let (node, metadata) = parse_expr(pairs)?; - Ok((node, metadata.unit)) - } -} - -struct NodeMetadata { - pub unit: Unit, -} - -impl NodeMetadata { - pub fn new(unit: Unit) -> Self { - Self { unit } - } -} - -fn parse_unit(pairs: Pairs) -> Result<(Unit, f64), ParseError> { - let mut scale = 1.0; - let mut length = 0; - let mut mass = 0; - let mut time = 0; - - for pair in pairs { - println!("found rule: {:?}", pair.as_rule()); - match pair.as_rule() { - Rule::nano => scale *= 1e-9, - Rule::micro => scale *= 1e-6, - Rule::milli => scale *= 1e-3, - Rule::centi => scale *= 1e-2, - Rule::deci => scale *= 1e-1, - Rule::deca => scale *= 1e1, - Rule::hecto => scale *= 1e2, - Rule::kilo => scale *= 1e3, - Rule::mega => scale *= 1e6, - Rule::giga => scale *= 1e9, - Rule::tera => scale *= 1e12, - - Rule::meter => length = 1, - Rule::gram => mass = 1, - Rule::second => time = 1, - - _ => unreachable!(), // All possible rules should be covered + pub fn try_parse_from_str(src: &str) -> Result { + let tokens = Lexer::new(src); + + match parser().parse(tokens).into_result() { + Ok(ast) => Ok(ast), + Err(parse_errs) => { + let errs = parse_errs.into_iter().map(|e| { + let primary = e.span(); + let mut secondary = Vec::new(); + for (msg, ctx_span) in e.contexts() { + secondary.push((msg.to_string(), *ctx_span)); + } + (e.to_string(), *primary, secondary) + }); + Err(make_compile_error("expression", src, errs)) + } } } - - Ok((Unit { length, mass, time }, scale)) } -fn parse_const(pair: Pair) -> Literal { - match pair.as_rule() { - Rule::infinity => Literal::Float(f64::INFINITY), - Rule::imaginary_unit => Literal::Complex(Complex::new(0.0, 1.0)), - Rule::pi => Literal::Float(std::f64::consts::PI), - Rule::tau => Literal::Float(2.0 * std::f64::consts::PI), - Rule::euler_number => Literal::Float(std::f64::consts::E), - Rule::golden_ratio => Literal::Float(1.61803398875), - _ => unreachable!("Unexpected constant: {:?}", pair), - } -} +pub fn parser<'src, I>() -> impl Parser<'src, I, Node, extra::Err, Span>>> +where + I: ValueInput<'src, Token = Token<'src>, Span = Span>, +{ + recursive(|expr| { + let constant = select! { + Token::Float(f) => Node::Lit(Literal::Float(f)), + Token::Const(c) => Node::Lit(c.value()) + }; -fn parse_lit(mut pairs: Pairs) -> Result<(Literal, Unit), ParseError> { - let literal = match pairs.next() { - Some(lit) => match lit.as_rule() { - Rule::int => { - let value = lit.as_str().parse::()? as f64; - Literal::Float(value) - } - Rule::float => { - let value = lit.as_str().parse::()?; - Literal::Float(value) - } - Rule::unit => { - let (unit, scale) = parse_unit(lit.into_inner())?; - return Ok((Literal::Float(scale), unit)); + let args = expr.clone().separated_by(just(Token::Comma)).collect::>().delimited_by(just(Token::LParen), just(Token::RParen)); + + let if_expr = just(Token::If) + .ignore_then(args.clone()) // Parses (cond, a, b) + .try_map(|args: Vec, span| { + if args.len() != 3 { + return Err(Rich::custom(span, "Expected 3 arguments in if(cond, a, b)")); + } + let mut iter = args.into_iter(); + let cond = iter.next().unwrap(); + let if_b = iter.next().unwrap(); + let else_b = iter.next().unwrap(); + Ok(Node::Conditional { + condition: Box::new(cond), + if_block: Box::new(if_b), + else_block: Box::new(else_b), + }) } - rule => unreachable!("unexpected rule: {:?}", rule), - }, - None => unreachable!("expected rule"), // No literal found - }; - - if let Some(unit_pair) = pairs.next() { - let unit_pairs = unit_pair.into_inner(); // Get the inner pairs for the unit - let (unit, scale) = parse_unit(unit_pairs)?; - - println!("found unit: {unit:?}"); - - Ok(( - match literal { - Literal::Float(num) => Literal::Float(num * scale), - Literal::Complex(num) => Literal::Complex(num * scale), - }, - unit, - )) - } else { - Ok((literal, Unit::BASE_UNIT)) - } -} - -fn parse_expr(pairs: Pairs) -> Result<(Node, NodeMetadata), ParseError> { - PRATT_PARSER - .map_primary(|primary| { - Ok(match primary.as_rule() { - Rule::lit => { - let (lit, unit) = parse_lit(primary.into_inner())?; - - (Node::Lit(lit), NodeMetadata { unit }) - } - Rule::fn_call => { - let mut pairs = primary.into_inner(); - let name = pairs.next().expect("fn_call always has 2 children").as_str().to_string(); - - ( - Node::FnCall { - name, - expr: pairs.map(|p| parse_expr(p.into_inner()).map(|expr| expr.0)).collect::, ParseError>>()?, - }, - NodeMetadata::new(Unit::BASE_UNIT), - ) - } - Rule::constant => { - let lit = parse_const(primary.into_inner().next().expect("constant should have atleast 1 child")); - - (Node::Lit(lit), NodeMetadata::new(Unit::BASE_UNIT)) - } - Rule::ident => { - let name = primary.as_str().to_string(); - - (Node::Var(name), NodeMetadata::new(Unit::BASE_UNIT)) - } - Rule::expr => parse_expr(primary.into_inner())?, - Rule::float => { - let value = primary.as_str().parse::()?; - (Node::Lit(Literal::Float(value)), NodeMetadata::new(Unit::BASE_UNIT)) - } - rule => unreachable!("unexpected rule: {:?}", rule), + ); + + let ident = select! {Token::Ident(s) => s}.labelled("ident"); + + let call = ident.then(args).map(|(name, args): (&str, Vec)| Node::FnCall { name: name.to_string(), expr: args }); + + let parens = expr.clone().delimited_by(just(Token::LParen), just(Token::RParen)); + let var = ident.map(|s| Node::Var(s.to_string())); + + let atom = choice((constant, if_expr, call, parens, var)).labelled("atom").boxed(); + + let add_op = choice((just(Token::Plus).to(BinaryOp::Add), just(Token::Minus).to(BinaryOp::Sub))); + let mul_op = choice((just(Token::Star).to(BinaryOp::Mul), just(Token::Slash).to(BinaryOp::Div), just(Token::Modulo).to(BinaryOp::Modulo))); + let pow_op = just(Token::Caret).to(BinaryOp::Pow); + let unary_op = choice((just(Token::Minus).to(UnaryOp::Neg), just(Token::Bang).to(UnaryOp::Not))); + let and_op = just(Token::AndAnd).to(BinaryOp::And); + let or_op = just(Token::OrOr).to(BinaryOp::Or); + let cmp_op = choice(( + just(Token::Lt).to(BinaryOp::Lt), + just(Token::Le).to(BinaryOp::Leq), + just(Token::Gt).to(BinaryOp::Gt), + just(Token::Ge).to(BinaryOp::Geq), + just(Token::Neq).to(BinaryOp::Neq), + just(Token::EqEq).to(BinaryOp::Eq), + )); + + // Postfix factorial: expr! → UnaryOp::Fac + let postfix = atom + .clone() + .foldl(just(Token::Bang).repeated(), |expr, _| Node::UnaryOp { + op: UnaryOp::Fac, + expr: Box::new(expr), }) - }) - .map_prefix(|op, rhs| { - let (rhs, rhs_metadata) = rhs?; - let op = match op.as_rule() { - Rule::neg => UnaryOp::Neg, - Rule::sqrt => UnaryOp::Sqrt, - - rule => unreachable!("unexpected rule: {:?}", rule), - }; - - let node = Node::UnaryOp { expr: Box::new(rhs), op }; - let unit = rhs_metadata.unit; - - let unit = if !unit.is_base() { - match op { - UnaryOp::Sqrt if unit.length % 2 == 0 && unit.mass % 2 == 0 && unit.time % 2 == 0 => Unit { - length: unit.length / 2, - mass: unit.mass / 2, - time: unit.time / 2, - }, - UnaryOp::Neg => unit, - op => return Err(ParseError::Type(TypeError::InvalidUnaryOp(unit, op))), - } - } else { - Unit::BASE_UNIT - }; - - Ok((node, NodeMetadata::new(unit))) - }) - .map_postfix(|lhs, op| { - let (lhs_node, lhs_metadata) = lhs?; - - let op = match op.as_rule() { - Rule::EOI => return Ok((lhs_node, lhs_metadata)), - Rule::fac => UnaryOp::Fac, - rule => unreachable!("unexpected rule: {:?}", rule), - }; - - if !lhs_metadata.unit.is_base() { - return Err(ParseError::Type(TypeError::InvalidUnaryOp(lhs_metadata.unit, op))); - } - - Ok((Node::UnaryOp { expr: Box::new(lhs_node), op }, lhs_metadata)) - }) - .map_infix(|lhs, op, rhs| { - let (lhs, lhs_metadata) = lhs?; - let (rhs, rhs_metadata) = rhs?; - - let op = match op.as_rule() { - Rule::add => BinaryOp::Add, - Rule::sub => BinaryOp::Sub, - Rule::mul => BinaryOp::Mul, - Rule::div => BinaryOp::Div, - Rule::pow => BinaryOp::Pow, - Rule::paren => BinaryOp::Mul, - rule => unreachable!("unexpected rule: {:?}", rule), - }; - - let (lhs_unit, rhs_unit) = (lhs_metadata.unit, rhs_metadata.unit); + .boxed(); - let unit = match (!lhs_unit.is_base(), !rhs_unit.is_base()) { - (true, true) => match op { - BinaryOp::Mul => Unit { - length: lhs_unit.length + rhs_unit.length, - mass: lhs_unit.mass + rhs_unit.mass, - time: lhs_unit.time + rhs_unit.time, - }, - BinaryOp::Div => Unit { - length: lhs_unit.length - rhs_unit.length, - mass: lhs_unit.mass - rhs_unit.mass, - time: lhs_unit.time - rhs_unit.time, - }, - BinaryOp::Add | BinaryOp::Sub => { - if lhs_unit == rhs_unit { - lhs_unit - } else { - return Err(ParseError::Type(TypeError::InvalidBinaryOp(lhs_unit, op, rhs_unit))); - } - } - BinaryOp::Pow => { - return Err(ParseError::Type(TypeError::InvalidBinaryOp(lhs_unit, op, rhs_unit))); - } - }, + let pow = postfix.clone().foldl( + pow_op + .then(unary_op.clone().repeated().foldr(postfix, |op, expr| Node::UnaryOp { op, expr: Box::new(expr) }).boxed()) + .repeated(), + |lhs, (op, rhs)| Node::BinOp { + lhs: Box::new(lhs), + op, + rhs: Box::new(rhs), + }, + ); - (true, false) => match op { - BinaryOp::Add | BinaryOp::Sub => return Err(ParseError::Type(TypeError::InvalidBinaryOp(lhs_unit, op, Unit::BASE_UNIT))), - BinaryOp::Pow => { - //TODO: improve error type - //TODO: support 1 / int - if let Ok(Value::Number(Number::Real(val))) = rhs.eval(&EvalContext::default()) { - if (val - val as i32 as f64).abs() <= f64::EPSILON { - Unit { - length: lhs_unit.length * val as i32, - mass: lhs_unit.mass * val as i32, - time: lhs_unit.time * val as i32, - } - } else { - return Err(ParseError::Type(TypeError::InvalidBinaryOp(lhs_unit, op, Unit::BASE_UNIT))); - } - } else { - return Err(ParseError::Type(TypeError::InvalidBinaryOp(lhs_unit, op, Unit::BASE_UNIT))); - } - } - _ => lhs_unit, - }, - (false, true) => match op { - BinaryOp::Add | BinaryOp::Sub | BinaryOp::Pow => return Err(ParseError::Type(TypeError::InvalidBinaryOp(Unit::BASE_UNIT, op, rhs_unit))), - _ => rhs_unit, - }, - (false, false) => Unit::BASE_UNIT, - }; + let unary = unary_op.repeated().foldr(pow, |op, expr| Node::UnaryOp { op, expr: Box::new(expr) }).boxed(); - let node = Node::BinOp { + let product = unary + .clone() + .foldl(mul_op.then(unary).repeated(), |lhs, (op, rhs)| Node::BinOp { lhs: Box::new(lhs), op, rhs: Box::new(rhs), - }; - - Ok((node, NodeMetadata::new(unit))) - }) - .parse(pairs) + }) + .boxed(); + + let add = product.clone().foldl(add_op.then(product).repeated(), |lhs, (op, rhs)| Node::BinOp { + lhs: Box::new(lhs), + op, + rhs: Box::new(rhs), + }); + + let cmp = add.clone().foldl(cmp_op.then(add).repeated(), |lhs: Node, (op, rhs)| Node::BinOp { + lhs: Box::new(lhs), + op, + rhs: Box::new(rhs), + }); + + // Chain comparisons like `a < b < c` by multiplying the boolean + // (1.0 / 0.0) results, preserving the existing semantics. + let chained_cmp = cmp.clone().foldl(cmp.repeated(), |lhs, rhs| Node::BinOp { + lhs: Box::new(lhs), + op: BinaryOp::Mul, + rhs: Box::new(rhs), + }); + + let and = chained_cmp.clone().foldl(and_op.then(chained_cmp).repeated(), |lhs, (op, rhs)| Node::BinOp { + lhs: Box::new(lhs), + op, + rhs: Box::new(rhs), + }); + + let or = and.clone().foldl(or_op.then(and).repeated(), |lhs, (op, rhs)| Node::BinOp { + lhs: Box::new(lhs), + op, + rhs: Box::new(rhs), + }); + + or + }) } -//TODO: set up Unit test for Units #[cfg(test)] mod tests { use super::*; @@ -319,8 +161,15 @@ mod tests { $( #[test] fn $name() { - let result = Node::try_parse_from_str($input).unwrap(); - assert_eq!(result.0, $expected); + + let result = match Node::try_parse_from_str($input){ + Ok(expr) => expr, + Err(err) => { + err.print(); + panic!(concat!("failed to parse `", $input, "`")); + } + }; + assert_eq!(result, $expected); } )* }; @@ -349,16 +198,20 @@ mod tests { op: BinaryOp::Pow, rhs: Box::new(Node::Lit(Literal::Float(3.0))), }, - test_parse_unary_sqrt: "sqrt(16)" => Node::UnaryOp { - expr: Box::new(Node::Lit(Literal::Float(16.0))), - op: UnaryOp::Sqrt, + test_parse_unary_sqrt: "sqrt(16)" => Node::FnCall { + name: "sqrt".to_string(), + expr: vec![Node::Lit(Literal::Float(16.0))], }, - test_parse_sqr_ident: "sqr(16)" => Node::FnCall { - name:"sqr".to_string(), + test_parse_ii_call: "ii(16)" => Node::FnCall { + name:"ii".to_string(), expr: vec![Node::Lit(Literal::Float(16.0))] }, - - test_parse_complex_expr: "(1 + 2) 3 - 4 ^ 2" => Node::BinOp { + test_parse_i_mul: "i(16)" => Node::BinOp { + lhs: Box::new(Node::Lit(Literal::Complex(Complex::new(0.0, 1.0)))), + op: BinaryOp::Mul, + rhs: Box::new(Node::Lit(Literal::Float(16.0))), + }, + test_parse_complex_expr: "(1 + 2) * 3 - 4 ^ 2" => Node::BinOp { lhs: Box::new(Node::BinOp { lhs: Box::new(Node::BinOp { lhs: Box::new(Node::Lit(Literal::Float(1.0))), @@ -374,6 +227,15 @@ mod tests { op: BinaryOp::Pow, rhs: Box::new(Node::Lit(Literal::Float(2.0))), }), + }, + test_conditional_expr: "if (x+3, 0, 1)" => Node::Conditional{ + condition: Box::new(Node::BinOp{ + lhs: Box::new(Node::Var("x".to_string())), + op: BinaryOp::Add, + rhs: Box::new(Node::Lit(Literal::Float(3.0))), + }), + if_block: Box::new(Node::Lit(Literal::Float(0.0))), + else_block: Box::new(Node::Lit(Literal::Float(1.0))), } } } diff --git a/libraries/math-parser/src/value.rs b/libraries/math-parser/src/value.rs index 3577f3ea60..74184c0575 100644 --- a/libraries/math-parser/src/value.rs +++ b/libraries/math-parser/src/value.rs @@ -52,28 +52,74 @@ impl std::fmt::Display for Number { } impl Number { - pub fn binary_op(self, op: BinaryOp, other: Number) -> Number { + pub fn binary_op(self, op: BinaryOp, other: Number) -> Option { match (self, other) { (Number::Real(lhs), Number::Real(rhs)) => { let result = match op { + BinaryOp::And => { + let l = lhs != 0.0; + let r = rhs != 0.0; + if l && r { 1.0 } else { 0.0 } + } + BinaryOp::Or => { + let l = lhs != 0.0; + let r = rhs != 0.0; + if l || r { 1.0 } else { 0.0 } + } BinaryOp::Add => lhs + rhs, BinaryOp::Sub => lhs - rhs, BinaryOp::Mul => lhs * rhs, BinaryOp::Div => lhs / rhs, + BinaryOp::Modulo => lhs % rhs, BinaryOp::Pow => lhs.powf(rhs), + BinaryOp::Leq => (lhs <= rhs) as u8 as f64, + BinaryOp::Lt => (lhs < rhs) as u8 as f64, + BinaryOp::Geq => (lhs >= rhs) as u8 as f64, + BinaryOp::Gt => (lhs > rhs) as u8 as f64, + BinaryOp::Neq => (lhs != rhs) as u8 as f64, + BinaryOp::Eq => (lhs == rhs) as u8 as f64, }; - Number::Real(result) + + Some(Number::Real(result)) } (Number::Complex(lhs), Number::Complex(rhs)) => { let result = match op { + BinaryOp::And => { + let l = lhs != Complex::new(0.0, 0.0); + let r = rhs != Complex::new(0.0, 0.0); + return Some(Number::Real(if l && r { 1.0 } else { 0.0 })); + } + BinaryOp::Or => { + let l = lhs != Complex::new(0.0, 0.0); + let r = rhs != Complex::new(0.0, 0.0); + return Some(Number::Real(if l || r { 1.0 } else { 0.0 })); + } BinaryOp::Add => lhs + rhs, BinaryOp::Sub => lhs - rhs, BinaryOp::Mul => lhs * rhs, BinaryOp::Div => lhs / rhs, + BinaryOp::Modulo => lhs % rhs, BinaryOp::Pow => lhs.powc(rhs), + BinaryOp::Leq | BinaryOp::Lt | BinaryOp::Geq | BinaryOp::Gt => { + return None; + } + BinaryOp::Neq => { + if lhs != rhs { + return Some(Number::Real(1.0)); + } else { + return Some(Number::Real(0.0)); + } + } + BinaryOp::Eq => { + if lhs == rhs { + return Some(Number::Real(1.0)); + } else { + return Some(Number::Real(0.0)); + } + } }; - Number::Complex(result) + Some(Number::Complex(result)) } (Number::Real(lhs), Number::Complex(rhs)) => { @@ -84,8 +130,9 @@ impl Number { BinaryOp::Mul => lhs_complex * rhs, BinaryOp::Div => lhs_complex / rhs, BinaryOp::Pow => lhs_complex.powc(rhs), + _ => return None, }; - Number::Complex(result) + Some(Number::Complex(result)) } (Number::Complex(lhs), Number::Real(rhs)) => { @@ -96,8 +143,9 @@ impl Number { BinaryOp::Mul => lhs * rhs_complex, BinaryOp::Div => lhs / rhs_complex, BinaryOp::Pow => lhs.powf(rhs), + _ => return None, }; - Number::Complex(result) + Some(Number::Complex(result)) } } } @@ -107,15 +155,37 @@ impl Number { Number::Real(real) => match op { UnaryOp::Neg => Number::Real(-real), UnaryOp::Sqrt => Number::Real(real.sqrt()), - - UnaryOp::Fac => todo!("Implement factorial"), + UnaryOp::Fac => { + // n! for real n: use integer semantics when n is a + // non-negative integer, otherwise return NaN. + if !real.is_finite() { + return Number::Real(f64::NAN); + } + let truncated = real.trunc(); + if truncated < 0.0 || (real - truncated).abs() > f64::EPSILON { + return Number::Real(f64::NAN); + } + let n = truncated as u64; + let mut acc = 1.0_f64; + for k in 1..=n { + acc *= k as f64; + } + Number::Real(acc) + } + UnaryOp::Not => { + let is_zero = real == 0.0; + Number::Real(if is_zero { 1.0 } else { 0.0 }) + } }, Number::Complex(complex) => match op { UnaryOp::Neg => Number::Complex(-complex), UnaryOp::Sqrt => Number::Complex(complex.sqrt()), - - UnaryOp::Fac => todo!("Implement factorial"), + UnaryOp::Fac => Number::Complex(Complex::new(f64::NAN, f64::NAN)), + UnaryOp::Not => { + let is_zero = complex == Complex::new(0.0, 0.0); + Number::Real(if is_zero { 1.0 } else { 0.0 }) + } }, } } diff --git a/node-graph/gmath-nodes/src/lib.rs b/node-graph/gmath-nodes/src/lib.rs new file mode 100644 index 0000000000..64a8f3e1db --- /dev/null +++ b/node-graph/gmath-nodes/src/lib.rs @@ -0,0 +1,780 @@ +use glam::DVec2; +use graphene_core::gradient::GradientStops; +use graphene_core::registry::types::{Fraction, Percentage, TextArea}; +use graphene_core::{Color, Ctx, num_traits}; +use log::warn; +use math_parser::ast; +use math_parser::context::{EvalContext, NothingMap, ValueProvider}; +use math_parser::value::{Number, Value}; +use num_traits::Pow; +use rand::{Rng, SeedableRng}; +use std::ops::{Add, Div, Mul, Rem, Sub}; + +/// The struct that stores the context for the maths parser. +/// This is currently just limited to supplying `a` and `b` until we add better node graph support and UI for variadic inputs. +struct MathNodeContext { + a: f64, + b: f64, +} + +impl ValueProvider for MathNodeContext { + fn get_value(&self, name: &str) -> Option { + if name.eq_ignore_ascii_case("a") { + Some(Value::from_f64(self.a)) + } else if name.eq_ignore_ascii_case("b") { + Some(Value::from_f64(self.b)) + } else { + None + } + } +} + +/// Calculates a mathematical expression with input values "A" and "B" +#[node_macro::node(category("Math: Arithmetic"), properties("math_properties"))] +fn math( + _: impl Ctx, + /// The value of "A" when calculating the expression + #[implementations(f64, f32)] + operand_a: U, + /// A math expression that may incorporate "A" and/or "B", such as "sqrt(A + B) - B^2" + #[default(A + B)] + expression: String, + /// The value of "B" when calculating the expression + #[implementations(f64, f32)] + #[default(1.)] + operand_b: U, +) -> U { + let node = match ast::Node::try_parse_from_str(&expression) { + Ok(expr) => expr, + Err(e) => { + warn!("Invalid expression: `{expression}`\n"); + // Print colored error to terminal + e.print(); + // Render error to html + _ = e.render_html(&Default::default()); + return U::from(0.).unwrap(); + } + }; + let context = EvalContext::new( + MathNodeContext { + a: operand_a.to_f64().unwrap(), + b: operand_b.to_f64().unwrap(), + }, + NothingMap, + ); + + let value = match node.eval(&context) { + Ok(value) => value, + Err(e) => { + warn!("Expression evaluation error: {e:?}"); + return U::from(0.).unwrap(); + } + }; + + let Value::Number(num) = value; + match num { + Number::Real(val) => U::from(val).unwrap(), + Number::Complex(c) => U::from(c.re).unwrap(), + } +} + +/// The addition operation (+) calculates the sum of two numbers. +#[node_macro::node(category("Math: Arithmetic"))] +fn add, T>( + _: impl Ctx, + /// The left-hand side of the addition operation. + #[implementations(f64, f32, u32, DVec2, f64, DVec2)] + augend: U, + /// The right-hand side of the addition operation. + #[implementations(f64, f32, u32, DVec2, DVec2, f64)] + addend: T, +) -> >::Output { + augend + addend +} + +/// The subtraction operation (-) calculates the difference between two numbers. +#[node_macro::node(category("Math: Arithmetic"))] +fn subtract, T>( + _: impl Ctx, + /// The left-hand side of the subtraction operation. + #[implementations(f64, f32, u32, DVec2, f64, DVec2)] + minuend: U, + /// The right-hand side of the subtraction operation. + #[implementations(f64, f32, u32, DVec2, DVec2, f64)] + subtrahend: T, +) -> >::Output { + minuend - subtrahend +} + +/// The multiplication operation (×) calculates the product of two numbers. +#[node_macro::node(category("Math: Arithmetic"))] +fn multiply, T>( + _: impl Ctx, + /// The left-hand side of the multiplication operation. + #[implementations(f64, f32, u32, DVec2, f64, DVec2)] + multiplier: U, + /// The right-hand side of the multiplication operation. + #[default(1.)] + #[implementations(f64, f32, u32, DVec2, DVec2, f64)] + multiplicand: T, +) -> >::Output { + multiplier * multiplicand +} + +/// The division operation (÷) calculates the quotient of two numbers. +/// +/// Produces 0 if the denominator is 0. +#[node_macro::node(category("Math: Arithmetic"))] +fn divide + Default + PartialEq, T: Default + PartialEq>( + _: impl Ctx, + /// The left-hand side of the division operation. + #[implementations(f64, f64, f32, f32, u32, u32, DVec2, DVec2, f64)] + numerator: U, + /// The right-hand side of the division operation. + #[default(1.)] + #[implementations(f64, f64, f32, f32, u32, u32, DVec2, f64, DVec2)] + denominator: T, +) -> >::Output +where + >::Output: Default, +{ + if denominator == T::default() { + return >::Output::default(); + } + numerator / denominator +} + +/// The modulo operation (%) calculates the remainder from the division of two numbers. The sign of the result shares the sign of the numerator unless "Always Positive" is enabled. +#[node_macro::node(category("Math: Arithmetic"))] +fn modulo>>, T: Copy>( + _: impl Ctx, + /// The left-hand side of the modulo operation. + #[implementations(f64, f32, u32, DVec2, DVec2, f64)] + numerator: U, + /// The right-hand side of the modulo operation. + #[default(2.)] + #[implementations(f64, f32, u32, DVec2, f64, DVec2)] + modulus: T, + /// Ensures the result will always be positive, even if the numerator is negative. + #[default(true)] + always_positive: bool, +) -> >::Output { + if always_positive { (numerator % modulus + modulus) % modulus } else { numerator % modulus } +} + +/// The exponent operation (^) calculates the result of raising a number to a power. +#[node_macro::node(category("Math: Arithmetic"))] +fn exponent, T>( + _: impl Ctx, + /// The base number that will be raised to the power. + #[implementations(f64, f32, u32)] + base: U, + /// The power to which the base number will be raised. + #[default(2.)] + #[implementations(f64, f32, u32)] + power: T, +) -> >::Output { + base.pow(power) +} + +/// The square root operation (√) calculates the nth root of a number, equivalent to raising the number to the power of 1/n. +#[node_macro::node(category("Math: Arithmetic"))] +fn root( + _: impl Ctx, + /// The number for which the nth root will be calculated. + #[default(2.)] + #[implementations(f64, f32)] + radicand: U, + /// The degree of the root to be calculated. Square root is 2, cube root is 3, and so on. + #[default(2.)] + #[implementations(f64, f32)] + degree: U, +) -> U { + if degree == U::from(2.).unwrap() { + radicand.sqrt() + } else if degree == U::from(3.).unwrap() { + radicand.cbrt() + } else { + radicand.powf(U::from(1.).unwrap() / degree) + } +} + +/// The logarithmic function (log) calculates the logarithm of a number with a specified base. If the natural logarithm function (ln) is desired, set the base to "e". +#[node_macro::node(category("Math: Arithmetic"))] +fn logarithm( + _: impl Ctx, + /// The number for which the logarithm will be calculated. + #[implementations(f64, f32)] + value: U, + /// The base of the logarithm, such as 2 (binary), 10 (decimal), and e (natural logarithm). + #[default(2.)] + #[implementations(f64, f32)] + base: U, +) -> U { + if base == U::from(2.).unwrap() { + value.log2() + } else if base == U::from(10.).unwrap() { + value.log10() + } else if base - U::from(std::f64::consts::E).unwrap() < U::epsilon() * U::from(1e6).unwrap() { + value.ln() + } else { + value.log(base) + } +} + +/// The sine trigonometric function (sin) calculates the ratio of the angle's opposite side length to its hypotenuse length. +#[node_macro::node(category("Math: Trig"))] +fn sine( + _: impl Ctx, + /// The given angle. + #[implementations(f64, f32)] + theta: U, + /// Whether the given angle should be interpreted as radians instead of degrees. + radians: bool, +) -> U { + if radians { theta.sin() } else { theta.to_radians().sin() } +} + +/// The cosine trigonometric function (cos) calculates the ratio of the angle's adjacent side length to its hypotenuse length. +#[node_macro::node(category("Math: Trig"))] +fn cosine( + _: impl Ctx, + /// The given angle. + #[implementations(f64, f32)] + theta: U, + /// Whether the given angle should be interpreted as radians instead of degrees. + radians: bool, +) -> U { + if radians { theta.cos() } else { theta.to_radians().cos() } +} + +/// The tangent trigonometric function (tan) calculates the ratio of the angle's opposite side length to its adjacent side length. +#[node_macro::node(category("Math: Trig"))] +fn tangent( + _: impl Ctx, + /// The given angle. + #[implementations(f64, f32)] + theta: U, + /// Whether the given angle should be interpreted as radians instead of degrees. + radians: bool, +) -> U { + if radians { theta.tan() } else { theta.to_radians().tan() } +} + +/// The inverse sine trigonometric function (asin) calculates the angle whose sine is the specified value. +#[node_macro::node(category("Math: Trig"))] +fn sine_inverse( + _: impl Ctx, + /// The given value for which the angle will be calculated. Must be in the range [-1, 1] or else the result will be NaN. + #[implementations(f64, f32)] + value: U, + /// Whether the resulting angle should be given in as radians instead of degrees. + radians: bool, +) -> U { + if radians { value.asin() } else { value.asin().to_degrees() } +} + +/// The inverse cosine trigonometric function (acos) calculates the angle whose cosine is the specified value. +#[node_macro::node(category("Math: Trig"))] +fn cosine_inverse( + _: impl Ctx, + /// The given value for which the angle will be calculated. Must be in the range [-1, 1] or else the result will be NaN. + #[implementations(f64, f32)] + value: U, + /// Whether the resulting angle should be given in as radians instead of degrees. + radians: bool, +) -> U { + if radians { value.acos() } else { value.acos().to_degrees() } +} + +/// The inverse tangent trigonometric function (atan or atan2, depending on input type) calculates: +/// atan: the angle whose tangent is the specified scalar number. +/// atan2: the angle of a ray from the origin to the specified coordinate. +/// +/// The resulting angle is always in the range [0°, 180°] or, in radians, [-π/2, π/2]. +#[node_macro::node(category("Math: Trig"))] +fn tangent_inverse( + _: impl Ctx, + /// The given value for which the angle will be calculated. + #[implementations(f64, f32, DVec2)] + value: U, + /// Whether the resulting angle should be given in as radians instead of degrees. + radians: bool, +) -> U::Output { + value.atan(radians) +} + +pub trait TangentInverse { + type Output: num_traits::float::Float; + fn atan(self, radians: bool) -> Self::Output; +} +impl TangentInverse for f32 { + type Output = f32; + fn atan(self, radians: bool) -> Self::Output { + if radians { self.atan() } else { self.atan().to_degrees() } + } +} +impl TangentInverse for f64 { + type Output = f64; + fn atan(self, radians: bool) -> Self::Output { + if radians { self.atan() } else { self.atan().to_degrees() } + } +} +impl TangentInverse for DVec2 { + type Output = f64; + fn atan(self, radians: bool) -> Self::Output { + if radians { self.y.atan2(self.x) } else { self.y.atan2(self.x).to_degrees() } + } +} + +/// The random function (rand) converts a seed into a random number within the specified range, inclusive of the minimum and exclusive of the maximum. The minimum and maximum values are automatically swapped if they are reversed. +#[node_macro::node(category("Math: Numeric"))] +fn random( + _: impl Ctx, + _primary: (), + /// Seed to determine the unique variation of which number will be generated. + seed: u64, + /// The smaller end of the range within which the random number will be generated. + #[implementations(f64, f32)] + #[default(0.)] + min: U, + /// The larger end of the range within which the random number will be generated. + #[implementations(f64, f32)] + #[default(1.)] + max: U, +) -> f64 { + let mut rng = rand::rngs::StdRng::seed_from_u64(seed); + let result = rng.random::(); + let (min, max) = if min < max { (min, max) } else { (max, min) }; + let (min, max) = (min.to_f64().unwrap(), max.to_f64().unwrap()); + result * (max - min) + min +} + +/// Convert a number to an integer of the type u32, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented. +#[node_macro::node(name("To u32"), category("Math: Numeric"))] +fn to_u32(_: impl Ctx, #[implementations(f64, f32)] value: U) -> u32 { + let value = U::clamp(value, U::from(0.).unwrap(), U::from(u32::MAX as f64).unwrap()); + value.to_u32().unwrap() +} + +/// Convert a number to an integer of the type u64, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented. +#[node_macro::node(name("To u64"), category("Math: Numeric"))] +fn to_u64(_: impl Ctx, #[implementations(f64, f32)] value: U) -> u64 { + let value = U::clamp(value, U::from(0.).unwrap(), U::from(u64::MAX as f64).unwrap()); + value.to_u64().unwrap() +} + +/// Convert an integer to a decimal number of the type f64, which may be the required type for certain node inputs. This will be removed in the future when automatic type conversion is implemented. +#[node_macro::node(name("To f64"), category("Math: Numeric"))] +fn to_f64(_: impl Ctx, #[implementations(u32, u64)] value: U) -> f64 { + value.to_f64().unwrap() +} + +/// The rounding function (round) maps an input value to its nearest whole number. Halfway values are rounded away from zero. +#[node_macro::node(category("Math: Numeric"))] +fn round( + _: impl Ctx, + /// The number which will be rounded. + #[implementations(f64, f32)] + value: U, +) -> U { + value.round() +} + +/// The floor function (floor) rounds down an input value to the nearest whole number, unless the input number is already whole. +#[node_macro::node(category("Math: Numeric"))] +fn floor( + _: impl Ctx, + /// The number which will be rounded down. + #[implementations(f64, f32)] + value: U, +) -> U { + value.floor() +} + +/// The ceiling function (ceil) rounds up an input value to the nearest whole number, unless the input number is already whole. +#[node_macro::node(category("Math: Numeric"))] +fn ceiling( + _: impl Ctx, + /// The number which will be rounded up. + #[implementations(f64, f32)] + value: U, +) -> U { + value.ceil() +} + +/// The absolute value function (abs) removes the negative sign from an input value, if present. +#[node_macro::node(category("Math: Numeric"))] +fn absolute_value( + _: impl Ctx, + /// The number which will be made positive. + #[implementations(f64, f32)] + value: U, +) -> U { + value.abs() +} + +/// The minimum function (min) picks the smaller of two numbers. +#[node_macro::node(category("Math: Numeric"))] +fn min( + _: impl Ctx, + /// One of the two numbers, of which the lesser will be returned. + #[implementations(f64, f32, u32, &str)] + value: T, + /// The other of the two numbers, of which the lesser will be returned. + #[implementations(f64, f32, u32, &str)] + other_value: T, +) -> T { + if value < other_value { value } else { other_value } +} + +/// The maximum function (max) picks the larger of two numbers. +#[node_macro::node(category("Math: Numeric"))] +fn max( + _: impl Ctx, + /// One of the two numbers, of which the greater will be returned. + #[implementations(f64, f32, u32, &str)] + value: T, + /// The other of the two numbers, of which the greater will be returned. + #[implementations(f64, f32, u32, &str)] + other_value: T, +) -> T { + if value > other_value { value } else { other_value } +} + +/// The clamp function (clamp) restricts a number to a specified range between a minimum and maximum value. The minimum and maximum values are automatically swapped if they are reversed. +#[node_macro::node(category("Math: Numeric"))] +fn clamp( + _: impl Ctx, + /// The number to be clamped, which will be restricted to the range between the minimum and maximum values. + #[implementations(f64, f32, u32, &str)] + value: T, + /// The left (smaller) side of the range. The output will never be less than this number. + #[implementations(f64, f32, u32, &str)] + min: T, + /// The right (greater) side of the range. The output will never be greater than this number. + #[implementations(f64, f32, u32, &str)] + max: T, +) -> T { + let (min, max) = if min < max { (min, max) } else { (max, min) }; + if value < min { + min + } else if value > max { + max + } else { + value + } +} + +/// The greatest common divisor (GCD) calculates the largest positive integer that divides both of the two input numbers without leaving a remainder. +#[node_macro::node(category("Math: Numeric"))] +fn greatest_common_divisor + std::ops::SubAssign>( + _: impl Ctx, + /// One of the two numbers for which the GCD will be calculated. + #[implementations(u32, u64, i32)] + value: T, + /// The other of the two numbers for which the GCD will be calculated. + #[implementations(u32, u64, i32)] + other_value: T, +) -> T { + if value == T::zero() { + return other_value; + } + if other_value == T::zero() { + return value; + } + binary_gcd(value, other_value) +} + +/// The least common multiple (LCM) calculates the smallest positive integer that is a multiple of both of the two input numbers. +#[node_macro::node(category("Math: Numeric"))] +fn least_common_multiple( + _: impl Ctx, + /// One of the two numbers for which the LCM will be calculated. + #[implementations(u32, u64, i32)] + value: T, + /// The other of the two numbers for which the LCM will be calculated. + #[implementations(u32, u64, i32)] + other_value: T, +) -> T { + let value = value.to_i128().unwrap(); + let other_value = other_value.to_i128().unwrap(); + + if value == 0 || other_value == 0 { + return T::zero(); + } + let gcd = binary_gcd(value, other_value); + + T::from_i128((value * other_value).abs() / gcd).unwrap() +} + +fn binary_gcd + std::ops::SubAssign>(mut a: T, mut b: T) -> T { + if a == T::zero() { + return b; + } + if b == T::zero() { + return a; + } + + let mut shift = 0; + while (a | b) & T::one() == T::zero() { + a >>= 1; + b >>= 1; + shift += 1; + } + + while a & T::one() == T::zero() { + a >>= 1; + } + + while b != T::zero() { + while b & T::one() == T::zero() { + b >>= 1; + } + if a > b { + std::mem::swap(&mut a, &mut b); + } + b -= a; + } + + a << shift +} + +/// The equality operation (==) compares two values and returns true if they are equal, or false if they are not. +#[node_macro::node(category("Math: Logic"))] +fn equals, T>( + _: impl Ctx, + /// One of the two numbers to compare for equality. + #[implementations(f64, f32, u32, DVec2, &str, String)] + value: T, + /// The other of the two numbers to compare for equality. + #[implementations(f64, f32, u32, DVec2, &str, String)] + other_value: U, +) -> bool { + other_value == value +} + +/// The inequality operation (!=) compares two values and returns true if they are not equal, or false if they are. +#[node_macro::node(category("Math: Logic"))] +fn not_equals, T>( + _: impl Ctx, + /// One of the two numbers to compare for inequality. + #[implementations(f64, f32, u32, DVec2, &str)] + value: T, + /// The other of the two numbers to compare for inequality. + #[implementations(f64, f32, u32, DVec2, &str)] + other_value: U, +) -> bool { + other_value != value +} + +/// The less-than operation (<) compares two values and returns true if the first value is less than the second, or false if it is not. +/// If enabled with "Or Equal", the less-than-or-equal operation (<=) will be used instead. +#[node_macro::node(category("Math: Logic"))] +fn less_than>( + _: impl Ctx, + /// The number on the left-hand side of the comparison. + #[implementations(f64, f32, u32)] + value: T, + /// The number on the right-hand side of the comparison. + #[implementations(f64, f32, u32)] + other_value: T, + /// Uses the less-than-or-equal operation (<=) instead of the less-than operation (<). + or_equal: bool, +) -> bool { + if or_equal { value <= other_value } else { value < other_value } +} + +/// The greater-than operation (>) compares two values and returns true if the first value is greater than the second, or false if it is not. +/// If enabled with "Or Equal", the greater-than-or-equal operation (>=) will be used instead. +#[node_macro::node(category("Math: Logic"))] +fn greater_than>( + _: impl Ctx, + /// The number on the left-hand side of the comparison. + #[implementations(f64, f32, u32)] + value: T, + /// The number on the right-hand side of the comparison. + #[implementations(f64, f32, u32)] + other_value: T, + /// Uses the greater-than-or-equal operation (>=) instead of the greater-than operation (>). + or_equal: bool, +) -> bool { + if or_equal { value >= other_value } else { value > other_value } +} + +/// The logical or operation (||) returns true if either of the two inputs are true, or false if both are false. +#[node_macro::node(category("Math: Logic"))] +fn logical_or( + _: impl Ctx, + /// One of the two boolean values, either of which may be true for the node to output true. + value: bool, + /// The other of the two boolean values, either of which may be true for the node to output true. + other_value: bool, +) -> bool { + value || other_value +} + +/// The logical and operation (&&) returns true if both of the two inputs are true, or false if any are false. +#[node_macro::node(category("Math: Logic"))] +fn logical_and( + _: impl Ctx, + /// One of the two boolean values, both of which must be true for the node to output true. + value: bool, + /// The other of the two boolean values, both of which must be true for the node to output true. + other_value: bool, +) -> bool { + value && other_value +} + +/// The logical not operation (!) reverses true and false value of the input. +#[node_macro::node(category("Math: Logic"))] +fn logical_not( + _: impl Ctx, + /// The boolean value to be reversed. + input: bool, +) -> bool { + !input +} + +/// Constructs a bool value which may be set to true or false. +#[node_macro::node(category("Value"))] +fn bool_value(_: impl Ctx, _primary: (), #[name("Bool")] bool_value: bool) -> bool { + bool_value +} + +/// Constructs a number value which may be set to any real number. +#[node_macro::node(category("Value"))] +fn number_value(_: impl Ctx, _primary: (), number: f64) -> f64 { + number +} + +/// Constructs a number value which may be set to any value from 0% to 100% by dragging the slider. +#[node_macro::node(category("Value"))] +fn percentage_value(_: impl Ctx, _primary: (), percentage: Percentage) -> f64 { + percentage +} + +/// Constructs a two-dimensional vector value which may be set to any XY coordinate. +#[node_macro::node(category("Value"))] +fn coordinate_value(_: impl Ctx, _primary: (), x: f64, y: f64) -> DVec2 { + DVec2::new(x, y) +} + +/// Constructs a color value which may be set to any color, or no color. +#[node_macro::node(category("Value"))] +fn color_value(_: impl Ctx, _primary: (), #[default(Color::BLACK)] color: Option) -> Option { + color +} + +/// Gets the color at the specified position along the gradient, given a position from 0 (left) to 1 (right). +#[node_macro::node(category("Color"))] +fn sample_gradient(_: impl Ctx, _primary: (), gradient: GradientStops, position: Fraction) -> Color { + let position = position.clamp(0., 1.); + gradient.evaluate(position) +} + +/// Constructs a gradient value which may be set to any sequence of color stops to represent the transition between colors. +#[node_macro::node(category("Value"))] +fn gradient_value(_: impl Ctx, _primary: (), gradient: GradientStops) -> GradientStops { + gradient +} + +/// Constructs a string value which may be set to any plain text. +#[node_macro::node(category("Value"))] +fn string_value(_: impl Ctx, _primary: (), string: TextArea) -> String { + string +} + +#[node_macro::node(category("Math: Vector"))] +fn dot_product(_: impl Ctx, vector_a: DVec2, vector_b: DVec2) -> f64 { + vector_a.dot(vector_b) +} + +/// Gets the length or magnitude of a vector. +#[node_macro::node(category("Math: Vector"))] +fn length(_: impl Ctx, vector: DVec2) -> f64 { + vector.length() +} + +/// Scales the input vector to unit length while preserving it's direction. This is equivalent to dividing the input vector by it's own magnitude. +/// +/// Returns zero when the input vector is zero. +#[node_macro::node(category("Math: Vector"))] +fn normalize(_: impl Ctx, vector: DVec2) -> DVec2 { + vector.normalize_or_zero() +} + +#[cfg(test)] +mod test { + use super::*; + use graphene_core::Node; + use graphene_core::generic::FnNode; + + #[test] + pub fn dot_product_function() { + let vector_a = DVec2::new(1., 2.); + let vector_b = DVec2::new(3., 4.); + assert_eq!(dot_product((), vector_a, vector_b), 11.); + } + + #[test] + pub fn length_function() { + let vector = DVec2::new(3., 4.); + assert_eq!(length((), vector), 5.); + } + + #[test] + fn test_basic_expression() { + let result = math((), 0., "2 + 2".to_string(), 0.); + assert_eq!(result, 4.); + } + + #[test] + fn test_complex_expression() { + let result = math((), 0., "(5 * 3) + (10 / 2)".to_string(), 0.); + assert_eq!(result, 20.); + } + + #[test] + fn test_default_expression() { + let result = math((), 0., "0".to_string(), 0.); + assert_eq!(result, 0.); + } + + #[test] + fn test_invalid_expression() { + let result = math((), 0., "invalid".to_string(), 0.); + assert_eq!(result, 0.); + } + + #[test] + pub fn foo() { + let fnn = FnNode::new(|(a, b)| (b, a)); + assert_eq!(fnn.eval((1u32, 2u32)), (2, 1)); + } + + #[test] + pub fn add_vectors() { + assert_eq!(super::add((), DVec2::ONE, DVec2::ONE), DVec2::ONE * 2.); + } + + #[test] + pub fn subtract_f64() { + assert_eq!(super::subtract((), 5_f64, 3_f64), 2.); + } + + #[test] + pub fn divide_vectors() { + assert_eq!(super::divide((), DVec2::ONE, 2_f64), DVec2::ONE / 2.); + } + + #[test] + pub fn modulo_positive() { + assert_eq!(super::modulo((), -5_f64, 2_f64, true), 1_f64); + } + + #[test] + pub fn modulo_negative() { + assert_eq!(super::modulo((), -5_f64, 2_f64, false), -1_f64); + } +}