diff --git a/Cargo.lock b/Cargo.lock index de1062ca..9fd403b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,82 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "2.0.0-rc.3" @@ -21,11 +97,74 @@ dependencies = [ "virtue", ] +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "built" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" + [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + +[[package]] +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cc" +version = "1.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] [[package]] name = "cfg-if" @@ -33,16 +172,257 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "exr" +version = "1.73.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "image" +version = "0.25.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", ] +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libfuzzer-sys" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" +dependencies = [ + "arbitrary", + "cc", +] + [[package]] name = "libm" version = "0.2.11" @@ -51,9 +431,122 @@ checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] [[package]] name = "once_cell" @@ -61,55 +554,290 @@ version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + [[package]] name = "syn" -version = "2.0.90" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "texpresso" version = "2.0.1" @@ -119,11 +847,93 @@ dependencies = [ "libm", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "virtue" @@ -138,25 +948,50 @@ dependencies = [ "bincode", "texpresso", "wasm-bindgen", +] + +[[package]] +name = "vtf-canvas" +version = "0.1.0" +dependencies = [ + "vtf", + "wasm-bindgen", "web-sys", ] +[[package]] +name = "vtf-png" +version = "0.1.0" +dependencies = [ + "base64", + "image", + "vtf", + "wasm-bindgen", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -168,9 +1003,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -178,9 +1013,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -191,16 +1026,79 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", ] + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] +name = "winnow" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e49d2d35d3fad69b39b94139037ecfb4f359f08958b9c11e7315ce770462419" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index cfbe8b16..9beecb3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,9 @@ [workspace] -members = ["packages/vtf"] +members = ["packages/vtf", "packages/vtf-canvas", "packages/vtf-png"] resolver = "2" [profile.release] opt-level = 3 + +[workspace.dependencies] +wasm-bindgen = "0.2.95" diff --git a/apps/extension/browser/client/webpack.config.ts b/apps/extension/browser/client/webpack.config.ts index a5fd3119..05e49467 100644 --- a/apps/extension/browser/client/webpack.config.ts +++ b/apps/extension/browser/client/webpack.config.ts @@ -8,6 +8,10 @@ export default { entry: { extension: join(import.meta.dirname, "src/extension.ts") }, + experiments: { + asyncWebAssembly: true, + syncWebAssembly: true, + }, output: { path: join(import.meta.dirname, "dist"), libraryTarget: "commonjs" diff --git a/apps/extension/desktop/client/webpack.config.ts b/apps/extension/desktop/client/webpack.config.ts index 33f4af9a..8203fce5 100644 --- a/apps/extension/desktop/client/webpack.config.ts +++ b/apps/extension/desktop/client/webpack.config.ts @@ -7,6 +7,10 @@ export default { entry: { extension: join(import.meta.dirname, "src/extension.ts") }, + experiments: { + asyncWebAssembly: true, + syncWebAssembly: true, + }, output: { path: join(import.meta.dirname, "dist"), libraryTarget: "commonjs2" diff --git a/apps/vtf-editor/package.json b/apps/vtf-editor/package.json index a0dc0f3a..3862b682 100644 --- a/apps/vtf-editor/package.json +++ b/apps/vtf-editor/package.json @@ -12,7 +12,7 @@ "client": "workspace:^", "svelte": "^5.10.0", "vite": "^6.0.3", - "vtf": "workspace:^" + "vtf-canvas": "workspace:^" }, "type": "module" } diff --git a/apps/vtf-editor/src/VTFViewer.svelte b/apps/vtf-editor/src/VTFViewer.svelte index b84f2983..1d10c66f 100644 --- a/apps/vtf-editor/src/VTFViewer.svelte +++ b/apps/vtf-editor/src/VTFViewer.svelte @@ -2,7 +2,7 @@ import type { VTFEditor } from "client/VTF/VTFEditor" import { distinctUntilChanged, filter, fromEvent, map, merge, Observable, scan, startWith, switchMap } from "rxjs" import { toStore } from "svelte/store" - import { VTF, VTFImageFormat } from "vtf" + import { VTF, VTFImageFormat, VTFPutImageData } from "vtf-canvas" import { z } from "zod" interface Props { @@ -83,7 +83,7 @@ function extract(node: HTMLCanvasElement, vtf: VTF) { requestAnimationFrame(() => { try { - vtf.putImageData(node.getContext("2d")!, vtf.header.mipmap_count - 1, 0) + VTFPutImageData(vtf, node.getContext("2d")!, vtf.header.mipmap_count - 1, 0) } catch (error) { console.error(error) if (error instanceof Error) { diff --git a/apps/vtf-editor/src/index.ts b/apps/vtf-editor/src/index.ts index ec972c60..a2b522f5 100644 --- a/apps/vtf-editor/src/index.ts +++ b/apps/vtf-editor/src/index.ts @@ -1,6 +1,6 @@ import { filter, firstValueFrom, fromEvent } from "rxjs" import { mount } from "svelte" -import init from "vtf" +import init from "vtf-canvas" import App from "./App.svelte" import "./app.css" diff --git a/package.json b/package.json index f060549e..8f49d65e 100644 --- a/package.json +++ b/package.json @@ -438,7 +438,7 @@ "turbo": "^2.3.3", "typescript": "^5.6.2", "vscode-languageserver-textdocument": "^1.0.11", - "webpack": "^5.96.1", + "webpack": "^5.97.1", "webpack-cli": "^5.1.4", "zod": "^3.23.8" }, diff --git a/packages/client/package.json b/packages/client/package.json index 55757af7..e781d716 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -10,6 +10,7 @@ "tsconfig": "workspace:^", "vdf": "workspace:^", "vdf-documentsymbols": "workspace:^", - "vscode-languageclient": "*" + "vscode-languageclient": "*", + "vtf-png": "workspace:^" } } diff --git a/packages/client/src/TRPCClientRouter.ts b/packages/client/src/TRPCClientRouter.ts index 6e4bb606..fdc085a1 100644 --- a/packages/client/src/TRPCClientRouter.ts +++ b/packages/client/src/TRPCClientRouter.ts @@ -2,6 +2,7 @@ import type { CombinedDataTransformer, initTRPC } from "@trpc/server" import { Uri } from "common/Uri" import { firstValueFrom } from "rxjs" import { commands, languages, window, workspace } from "vscode" +import { VTF, VTFToPNG } from "vtf-png" import { z } from "zod" import { decorationTypes, editorDecorations } from "./decorations" import { searchForHUDRoot } from "./searchForHUDRoot" @@ -131,6 +132,15 @@ export function TRPCClientRouter( fileSystems.delete(input.key) }) }), + VTFToPNG: t + .procedure.input( + z.object({ + uri: Uri.schema + }) + ).mutation(async ({ input }) => { + const vtf = new VTF(await workspace.fs.readFile(input.uri)) + return VTFToPNG(vtf, 256) + }), window: t.router({ createTextEditorDecorationType: t .procedure diff --git a/packages/server/src/LanguageServer.ts b/packages/server/src/LanguageServer.ts index aa8037cc..2d9a0ec8 100644 --- a/packages/server/src/LanguageServer.ts +++ b/packages/server/src/LanguageServer.ts @@ -7,11 +7,12 @@ import { devalueTransformer } from "common/devalueTransformer" import { Uri } from "common/Uri" import { VSCodeVDFConfigurationSchema, type VSCodeVDFConfiguration } from "common/VSCodeVDFConfiguration" import { VSCodeVDFLanguageNameSchema, type VSCodeVDFLanguageID } from "common/VSCodeVDFLanguageID" +import { posix } from "path" import { BehaviorSubject, concatMap, defer, distinctUntilChanged, distinctUntilKeyChanged, firstValueFrom, from, map, Observable, shareReplay, Subject, Subscription, switchMap, tap, zip } from "rxjs" import { findBestMatch } from "string-similarity" import { VDFPosition, VDFRange } from "vdf" import type { FileType } from "vscode" -import { CodeAction, CodeActionKind, CodeLensRefreshRequest, CompletionItem, CompletionItemKind, Diagnostic, DidChangeConfigurationNotification, DocumentLink, DocumentSymbol, TextDocumentSyncKind, TextEdit, WorkspaceEdit, type CodeActionParams, type CodeLensParams, type CompletionParams, type Connection, type DefinitionParams, type DidSaveTextDocumentParams, type DocumentFormattingParams, type DocumentLinkParams, type DocumentSymbolParams, type GenericRequestHandler, type PrepareRenameParams, type ReferenceParams, type RenameParams, type ServerCapabilities, type TextDocumentChangeEvent } from "vscode-languageserver" +import { CodeAction, CodeActionKind, CodeLensRefreshRequest, CompletionItem, CompletionItemKind, Diagnostic, DidChangeConfigurationNotification, DocumentLink, DocumentSymbol, MarkupKind, TextDocumentSyncKind, TextEdit, WorkspaceEdit, type CodeActionParams, type CodeLensParams, type CompletionParams, type Connection, type DefinitionParams, type DidSaveTextDocumentParams, type DocumentFormattingParams, type DocumentLinkParams, type DocumentSymbolParams, type GenericRequestHandler, type PrepareRenameParams, type ReferenceParams, type RenameParams, type ServerCapabilities, type TextDocumentChangeEvent } from "vscode-languageserver" import { z } from "zod" import { Definitions, References } from "./DefinitionReferences" import type { HUDAnimationsLanguageServer } from "./HUDAnimations/HUDAnimationsLanguageServer" @@ -30,7 +31,8 @@ const capabilities = { "/", "\"", "#", - ] + ], + resolveProvider: true, }, definitionProvider: true, referencesProvider: true, @@ -67,6 +69,7 @@ export interface CompletionFilesOptions { value: string | null extensionsPattern: `.${string}` | null callbackfn?: (name: string, type: FileType) => Partial> | null + image?: boolean } export abstract class LanguageServer< @@ -277,6 +280,7 @@ export abstract class LanguageServer< this.onTextDocumentRequest(this.connection.onDidSaveTextDocument, this.onDidSaveTextDocument) this.onTextDocumentRequest(this.connection.onCompletion, this.onCompletion) + this.connection.onCompletionResolve((item) => this.onCompletionResolve(item)) this.onTextDocumentRequest(this.connection.onDefinition, this.onDefinition) this.onTextDocumentRequest(this.connection.onReferences, this.onReferences) this.onTextDocumentRequest(this.connection.onDocumentSymbol, this.onDocumentSymbol) @@ -471,6 +475,23 @@ export abstract class LanguageServer< }) } + protected async VTFToPNG(uri: Uri, path: string) { + try { + using document = await this.documents.get(uri, true) + return await firstValueFrom( + document.fileSystem$.pipe( + switchMap((fileSystem) => fileSystem.resolveFile(path)), + concatMap(async (uri) => uri != null ? await this.trpc.servers.vmt.baseTexture.query({ uri }) : null), + concatMap(async (uri) => uri != null ? this.trpc.client.VTFToPNG.mutate({ uri }) : null), + ) + ) + } + catch (error) { + console.error(error) + return null + } + } + protected async onDidOpen(event: TextDocumentChangeEvent): Promise<{ onDidClose: () => void }> { return { onDidClose: () => { @@ -555,7 +576,7 @@ export abstract class LanguageServer< const items = await this.getCompletion( document, new VDFPosition(params.position.line, params.position.character), - async (path: string, { value, extensionsPattern, callbackfn }: CompletionFilesOptions) => { + async (path: string, { value, extensionsPattern, callbackfn, image }: CompletionFilesOptions) => { return await firstValueFrom( zip([document.fileSystem$, document.documentConfiguration$]).pipe( concatMap(async ([fileSystem, documentConfiguration]) => { @@ -606,6 +627,14 @@ export abstract class LanguageServer< ...(incremental && { commitCharacters: ["/"], }), + ...(image && type == 1 && { + data: { + image: { + uri: document.uri, + path: posix.join(path, name) + } + }, + }), ...rest } } @@ -636,6 +665,23 @@ export abstract class LanguageServer< protected abstract getCompletion(document: TDocument, position: VDFPosition, files: CompletionFiles): Promise + protected async onCompletionResolve(item: CompletionItem): Promise { + const result = z.object({ image: z.object({ uri: Uri.schema, path: z.string() }) }).safeParse(item.data) + + if (result.success) { + const { image } = result.data + const uri = await this.VTFToPNG(image.uri, image.path) + if (uri) { + item.documentation = { + kind: MarkupKind.Markdown, + value: `![](${uri})` + } + } + } + + return item + } + private async onDefinition(params: TextDocumentRequestParams) { using document = await this.documents.get(params.textDocument.uri) const definitionReferences = await firstValueFrom(document.definitionReferences$) diff --git a/packages/server/src/VDF/Popfile/PopfileTextDocument.ts b/packages/server/src/VDF/Popfile/PopfileTextDocument.ts index 8701b879..3c06dd2d 100644 --- a/packages/server/src/VDF/Popfile/PopfileTextDocument.ts +++ b/packages/server/src/VDF/Popfile/PopfileTextDocument.ts @@ -8,7 +8,7 @@ import type { DiagnosticCodeAction } from "../../LanguageServer" import type { TeamFortress2FileSystem } from "../../TeamFortress2FileSystem" import type { TextDocumentInit } from "../../TextDocumentBase" import type { TextDocuments } from "../../TextDocuments" -import { VDFTextDocument, type VDFTextDocumentDependencies, type VDFTextDocumentSchema } from "../VDFTextDocument" +import { VDFTextDocument, VGUIAssetType, type VDFTextDocumentDependencies, type VDFTextDocumentSchema } from "../VDFTextDocument" import colours from "./colours.json" import keys from "./keys.json" import values from "./values.json" @@ -82,6 +82,7 @@ export class PopfileTextDocument extends VDFTextDocument { return null } }, + asset: VGUIAssetType.Image }, { name: "sound", diff --git a/packages/server/src/VDF/VDFLanguageServer.ts b/packages/server/src/VDF/VDFLanguageServer.ts index 37ab28f4..99c83dd0 100644 --- a/packages/server/src/VDF/VDFLanguageServer.ts +++ b/packages/server/src/VDF/VDFLanguageServer.ts @@ -7,11 +7,11 @@ import { firstValueFrom, type Observable } from "rxjs" import { VDFIndentation, VDFNewLine, VDFPosition } from "vdf" import { VDFDocumentSymbols } from "vdf-documentsymbols" import { formatVDF, type VDFFormatStringifyOptions } from "vdf-format" -import { Color, CompletionItem, CompletionItemKind, Range, TextEdit, type ColorPresentationParams, type Connection, type DocumentColorParams, type DocumentFormattingParams, type ServerCapabilities, type TextDocumentChangeEvent } from "vscode-languageserver" -import type { z } from "zod" +import { Color, CompletionItem, CompletionItemKind, Hover, Range, TextEdit, type ColorPresentationParams, type Connection, type DocumentColorParams, type DocumentFormattingParams, type HoverParams, type ServerCapabilities, type TextDocumentChangeEvent } from "vscode-languageserver" +import { z } from "zod" import { LanguageServer, type CompletionFiles, type TextDocumentRequestParams } from "../LanguageServer" import type { TextDocumentInit } from "../TextDocumentBase" -import type { VDFTextDocument, VDFTextDocumentDependencies } from "./VDFTextDocument" +import { resolveFileDetail, VGUIAssetType, type VDFTextDocument, type VDFTextDocumentDependencies } from "./VDFTextDocument" export interface VDFLanguageServerConfiguration> { name: "popfile" | "vdf" | "vmt" @@ -31,9 +31,10 @@ export abstract class VDFLanguageServer< constructor(languageId: TLanguageId, name: z.infer[TLanguageId], connection: Connection, VDFLanguageServerConfiguration: VDFLanguageServerConfiguration) { super(languageId, name, connection, { - servers: VDFLanguageServerConfiguration.servers, + servers: new Set(["vmt", ...VDFLanguageServerConfiguration.servers]), capabilities: { ...VDFLanguageServerConfiguration.capabilities, + hoverProvider: true, colorProvider: true, }, createDocument: async (init, documentConfiguration$, refCountDispose) => await VDFLanguageServerConfiguration.createDocument(init, documentConfiguration$, refCountDispose) @@ -42,6 +43,7 @@ export abstract class VDFLanguageServer< this.VDFLanguageServerConfiguration = VDFLanguageServerConfiguration this.documentsColours = new Map() + this.onTextDocumentRequest(this.connection.onHover, this.onHover) this.onTextDocumentRequest(this.connection.onDocumentColor, this.onDocumentColor) this.onTextDocumentRequest(this.connection.onColorPresentation, this.onColorPresentation) } @@ -185,7 +187,8 @@ export abstract class VDFLanguageServer< const { dir, name: nameNoExt } = posix.parse(name) return posix.join(dir, nameNoExt) }) - : undefined + : undefined, + image: fileConfiguration.asset == VGUIAssetType.Image }) } @@ -270,6 +273,35 @@ export abstract class VDFLanguageServer< } } + private async onHover(params: TextDocumentRequestParams): Promise { + using document = await this.documents.get(params.textDocument.uri) + const documentSymbols = await firstValueFrom(document.documentSymbols$) + + const documentSymbol = documentSymbols.getDocumentSymbolAtPosition(params.position) + if (!documentSymbol || !documentSymbol.detailRange || !documentSymbol.detailRange.contains(params.position)) { + return null + } + + const schema = (await firstValueFrom(document.configuration.dependencies$)).schema + const fileSchema = schema.files.find(({ keys }) => keys.has(documentSymbol.key.toLowerCase())) + if (!fileSchema) { + return null + } + + if (fileSchema.asset == VGUIAssetType.Image) { + const path = resolveFileDetail(documentSymbol.detail!, fileSchema) + const uri = await this.VTFToPNG(document.uri, path) + if (uri) { + return { + contents: `![](${uri})`, + range: documentSymbol.detailRange + } + } + } + + return null + } + private async onDocumentColor(params: TextDocumentRequestParams) { using document = await this.documents.get(params.textDocument.uri) diff --git a/packages/server/src/VDF/VDFTextDocument.ts b/packages/server/src/VDF/VDFTextDocument.ts index 942b2ea7..61b0914f 100644 --- a/packages/server/src/VDF/VDFTextDocument.ts +++ b/packages/server/src/VDF/VDFTextDocument.ts @@ -37,7 +37,7 @@ function ArrayEndsWithArray(arr1: T1[], arr2: T2[], comparer: (a: T1, b: return arr2.every((value, index) => comparer(arr1[start + index], value)) } -function resolveFileDetail(detail: string, configuration: VDFTextDocumentSchema["files"][number]) { +export function resolveFileDetail(detail: string, configuration: VDFTextDocumentSchema["files"][number]) { const [basename, ...rest] = detail.replaceAll(/[/\\]+/g, "/").split("/").reverse() return posix.resolve( @@ -87,7 +87,7 @@ export interface VDFTextDocumentSchema { extensionsPattern: `.${string}` | null resolveBaseName: (value: string, withExtension: (extension: `.${string}`) => string) => string, toCompletionItem?: (name: string, type: number, withoutExtension: () => string) => Partial> | null, - + asset?: VGUIAssetType }[] colours: { keys: { @@ -120,6 +120,11 @@ export interface DefinitionResult { nameRange?: VDFRange } +export const enum VGUIAssetType { + None = 0, + Image = 1 +} + export abstract class VDFTextDocument> extends TextDocumentBase { public readonly configuration: VDFTextDocumentConfiguration diff --git a/packages/server/src/VDF/VGUI/schemas/ClientSchemeSchema.ts b/packages/server/src/VDF/VGUI/schemas/ClientSchemeSchema.ts index d043a5c6..fde20da4 100644 --- a/packages/server/src/VDF/VGUI/schemas/ClientSchemeSchema.ts +++ b/packages/server/src/VDF/VGUI/schemas/ClientSchemeSchema.ts @@ -1,6 +1,6 @@ import type { VDFDocumentSymbol } from "vdf-documentsymbols" import { CompletionItemKind } from "vscode-languageserver" -import type { DefinitionMatcher, DefinitionResult, VDFTextDocumentSchema } from "../../VDFTextDocument" +import { VGUIAssetType, type DefinitionMatcher, type DefinitionResult, type VDFTextDocumentSchema } from "../../VDFTextDocument" class SchemeDefinitionMatcher implements DefinitionMatcher { @@ -132,6 +132,7 @@ export const ClientSchemeSchema: VDFTextDocumentSchema = { folder: "materials/vgui", extensionsPattern: ".vmt", resolveBaseName: (value, withExtension) => withExtension(".vmt"), + asset: VGUIAssetType.Image }, ], colours: { diff --git a/packages/server/src/VDF/VGUI/schemas/VGUISchema.ts b/packages/server/src/VDF/VGUI/schemas/VGUISchema.ts index 23b76bc4..8348752b 100644 --- a/packages/server/src/VDF/VGUI/schemas/VGUISchema.ts +++ b/packages/server/src/VDF/VGUI/schemas/VGUISchema.ts @@ -1,5 +1,5 @@ import { CompletionItemKind } from "vscode-languageserver" -import type { VDFTextDocumentSchema } from "../../VDFTextDocument" +import { VGUIAssetType, type VDFTextDocumentSchema } from "../../VDFTextDocument" import clientscheme from "../clientscheme.json" import keys from "../keys.json" import values from "../values.json" @@ -105,6 +105,7 @@ export const VGUISchema: VDFTextDocumentSchema = { extensionsPattern: ".vmt", resolveBaseName: (value, withExtension) => withExtension(".vmt"), toCompletionItem: (name, type, withoutExtension) => ({ insertText: withoutExtension() }), + asset: VGUIAssetType.Image }, { name: "sound", diff --git a/packages/server/src/VDF/VMT/VMTLanguageServer.ts b/packages/server/src/VDF/VMT/VMTLanguageServer.ts index 2d62ec98..11ce3e87 100644 --- a/packages/server/src/VDF/VMT/VMTLanguageServer.ts +++ b/packages/server/src/VDF/VMT/VMTLanguageServer.ts @@ -1,6 +1,11 @@ +import type { CombinedDataTransformer, initTRPC } from "@trpc/server" +import { Uri } from "common/Uri" +import { firstValueFrom, switchMap } from "rxjs" import { type Connection } from "vscode-languageserver" +import { z } from "zod" import type { WorkspaceBase } from "../../WorkspaceBase" import { VDFLanguageServer } from "../VDFLanguageServer" +import { resolveFileDetail } from "../VDFTextDocument" import { VMTTextDocument } from "./VMTTextDocument" import { VMTWorkspace } from "./VMTWorkspace" @@ -48,4 +53,43 @@ export class VMTLanguageServer extends VDFLanguageServer<"vmt", VMTTextDocument> }) this.workspaces = new Map() } + + protected router(t: ReturnType>) { + return t.mergeRouters( + super.router(t), + t.router({ + baseTexture: t + .procedure + .input( + z.object({ + uri: Uri.schema, + }) + ) + .query(async ({ input }) => { + + using document = await this.documents.get(input.uri, true) + const documentSymbols = await firstValueFrom(document.documentSymbols$) + + const header = documentSymbols.find((documentSymbol) => documentSymbol.key.toLowerCase() != "#base") + if (!header || !header.children) { + return null + } + + const baseTexture = header.children.find((documentSymbol) => documentSymbol.key.toLowerCase() == "$baseTexture".toLowerCase() && documentSymbol.detail != undefined) + if (!baseTexture) { + return null + } + + const schema = (await firstValueFrom(document.configuration.dependencies$)).schema + const path = resolveFileDetail(baseTexture.detail!, schema.files.find(({ keys }) => keys.has("$baseTexture".toLowerCase()))!) + + return await firstValueFrom( + document.fileSystem$.pipe( + switchMap((fileSystem) => fileSystem.resolveFile(path)), + ) + ) + }) + }) + ) + } } diff --git a/packages/vtf-canvas/Cargo.toml b/packages/vtf-canvas/Cargo.toml new file mode 100644 index 00000000..ac0b6c2d --- /dev/null +++ b/packages/vtf-canvas/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "vtf-canvas" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +vtf = { version = "0.1.0", path = "../vtf" } +wasm-bindgen = { workspace = true } +web-sys = { version = "0.3.77", features = ["CanvasRenderingContext2d", "ImageData"] } diff --git a/packages/vtf-canvas/package.json b/packages/vtf-canvas/package.json new file mode 100644 index 00000000..b9e5a3fe --- /dev/null +++ b/packages/vtf-canvas/package.json @@ -0,0 +1,12 @@ +{ + "name": "vtf-canvas", + "main": "./pkg/vtf_canvas.js", + "types": "./pkg/vtf_canvas.d.ts", + "files": [ + "pkg" + ], + "scripts": { + "dev": "cargo watch -- wasm-pack build --dev --target web", + "build": "wasm-pack build --release --target web" + } +} diff --git a/packages/vtf-canvas/src/lib.rs b/packages/vtf-canvas/src/lib.rs new file mode 100644 index 00000000..b6476df5 --- /dev/null +++ b/packages/vtf-canvas/src/lib.rs @@ -0,0 +1,11 @@ +use vtf::{VTF, VTFData, VTFError}; +use wasm_bindgen::prelude::wasm_bindgen; +use web_sys::{CanvasRenderingContext2d, ImageData, wasm_bindgen::Clamped}; + +#[wasm_bindgen(js_name = "VTFPutImageData")] +pub fn vtf_put_image_data(vtf: VTF, context: &CanvasRenderingContext2d, mipmap_index: usize, frame_index: usize) -> Result<(), VTFError> { + let VTFData { width, height, rgba } = vtf.extract(mipmap_index, frame_index)?; + let data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&rgba), width as u32, height as u32).unwrap(); + context.put_image_data(&data, 0.0, 0.0).unwrap(); + Ok(()) +} diff --git a/packages/vtf-png/Cargo.toml b/packages/vtf-png/Cargo.toml new file mode 100644 index 00000000..187976d3 --- /dev/null +++ b/packages/vtf-png/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "vtf-png" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +base64 = "0.22.1" +image = "0.25.5" +vtf = { version = "0.1.0", path = "../vtf" } +wasm-bindgen = { workspace = true } diff --git a/packages/vtf-png/package.json b/packages/vtf-png/package.json new file mode 100644 index 00000000..21d71841 --- /dev/null +++ b/packages/vtf-png/package.json @@ -0,0 +1,12 @@ +{ + "name": "vtf-png", + "main": "./pkg/vtf_png.js", + "types": "./pkg/vtf_png.d.ts", + "files": [ + "pkg" + ], + "scripts": { + "dev": "cargo watch -- wasm-pack build --dev --target bundler", + "build": "wasm-pack build --release --target bundler" + } +} diff --git a/packages/vtf-png/src/lib.rs b/packages/vtf-png/src/lib.rs new file mode 100644 index 00000000..9569df81 --- /dev/null +++ b/packages/vtf-png/src/lib.rs @@ -0,0 +1,38 @@ +use std::{cmp, io::Cursor}; + +use base64::{Engine, engine::general_purpose}; +use image::{ColorType, DynamicImage, ImageFormat, RgbaImage}; +use vtf::{VTF, VTFData, VTFError}; +use wasm_bindgen::prelude::wasm_bindgen; + +#[wasm_bindgen(js_name = "VTFToPNG")] +pub fn vtf_to_png(vtf: VTF, size: u16) -> Result { + match &vtf.mipmaps { + Ok(mipmaps) => { + let mipmap_index = if vtf.header.mipmap_count == 1 { + 0 + } else { + mipmaps + .iter() + .enumerate() + .rev() + .find_map(|(index, mipmap)| (cmp::max(mipmap.width, mipmap.height) <= size).then(|| index)) + .unwrap_or(0) + }; + + let VTFData { width, height, rgba } = vtf.extract(mipmap_index, 0)?; + let mut out = vec![]; + + if cmp::max(width, height) > size { + let image_buffer = RgbaImage::from_vec(width as u32, height as u32, rgba).unwrap(); + let thumbnail = DynamicImage::ImageRgba8(image_buffer).thumbnail(512, 512); + thumbnail.write_to(&mut Cursor::new(&mut out), ImageFormat::Png).unwrap(); + } else { + image::write_buffer_with_format(&mut Cursor::new(&mut out), &rgba, width as u32, height as u32, ColorType::Rgba8, ImageFormat::Png).unwrap(); + }; + + Ok(String::from("data:image/png;base64,") + &general_purpose::STANDARD.encode(out)) + } + Err(_) => Err(vtf.mipmaps.unwrap_err()), + } +} diff --git a/packages/vtf/Cargo.toml b/packages/vtf/Cargo.toml index 216db994..1bf3f720 100644 --- a/packages/vtf/Cargo.toml +++ b/packages/vtf/Cargo.toml @@ -9,5 +9,4 @@ crate-type = ["cdylib", "rlib"] [dependencies] bincode = { version = "2.0.0-rc.3", features = ["derive", "serde"] } texpresso = "2.0.1" -wasm-bindgen = "0.2.95" -web-sys = { version = "0.3.74", features = ["CanvasRenderingContext2d", "ImageData"] } +wasm-bindgen = { workspace = true } diff --git a/packages/vtf/package.json b/packages/vtf/package.json index 7da98f38..479f5b7f 100644 --- a/packages/vtf/package.json +++ b/packages/vtf/package.json @@ -1,12 +1,3 @@ { - "name": "vtf", - "main": "./pkg/vtf.js", - "types": "./pkg/vtf.d.ts", - "files": [ - "pkg" - ], - "scripts": { - "dev": "cargo watch -- wasm-pack build --dev --target web", - "build": "wasm-pack build --release --target web" - } + "name": "vtf" } diff --git a/packages/vtf/src/lib.rs b/packages/vtf/src/lib.rs index c62775b8..e15b3b58 100644 --- a/packages/vtf/src/lib.rs +++ b/packages/vtf/src/lib.rs @@ -1,16 +1,418 @@ -use vtf::{VTFData, VTFError, VTF}; -use wasm_bindgen::{prelude::wasm_bindgen, Clamped}; -use web_sys::{CanvasRenderingContext2d, ImageData}; +use std::{ + error::Error, + fmt::Display, + io::{BufReader, Cursor, Seek, SeekFrom}, +}; -pub mod vtf; +use bincode::{ + error::{AllowedEnumVariants, DecodeError}, + impl_borrow_decode, Decode, +}; +use wasm_bindgen::{prelude::wasm_bindgen, JsError, JsValue}; + +#[wasm_bindgen] +#[derive(Debug)] +pub struct VTF { + #[wasm_bindgen(skip)] + pub buf: Vec, + pub header: VTFHeader, + + #[wasm_bindgen(skip)] + pub resources: Option>, + + #[wasm_bindgen(skip)] + pub mipmaps: Result, VTFError>, +} + +#[wasm_bindgen] +#[derive(Debug, Clone, Copy, Decode)] +pub struct VTFHeader { + pub signature: VTFSignature, + pub version_major: u32, + pub version_minor: u32, + pub header_size: u32, + pub width: u16, + pub height: u16, + pub flags: u32, + pub frames: u16, + pub first_frame: u16, + _padding0: [u8; 4], + _reflectivity: [f32; 3], + _padding1: [u8; 4], + pub bumpmap_scale: f32, + pub high_res_image_format: VTFImageFormat, + pub mipmap_count: u8, + pub low_res_image_format: VTFImageFormat, + pub low_res_image_width: u8, + pub low_res_image_height: u8, +} + +#[wasm_bindgen] +#[derive(Debug, Clone, Copy)] +pub struct VTFSignature(); + +impl Display for VTFSignature { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "VTF\0") + } +} + +impl Decode for VTFSignature { + fn decode(decoder: &mut D) -> Result { + match <[u8; 4] as bincode::Decode>::decode(decoder)? { + [b'V', b'T', b'F', b'\0'] => Ok(VTFSignature()), + _ => Err(DecodeError::Other("VTF\0")), + } + } +} + +impl_borrow_decode!(VTFSignature); + +#[wasm_bindgen] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(i32)] +pub enum VTFImageFormat { + None = -1, + RGBA8888, + ABGR8888, + RGB888, + BGR888, + RGB565, + I8, + IA88, + P8, + A8, + RGB888BlueScreen, + BGR888BlueScreen, + ARGB8888, + BGRA8888, + DXT1, + DXT3, + DXT5, + BGRX8888, + BGR565, + BGRX5551, + BGRA4444, + DXT1OneBitAlpha, + BGRA5551, + UV88, + UVWQ8888, + RGBA16161616F, + RGBA16161616, + UVLX8888, +} + +impl Decode for VTFImageFormat { + fn decode(decoder: &mut D) -> Result { + let variant_value = ::decode(decoder)?; + match variant_value { + -1 => Ok(VTFImageFormat::None), + 0 => Ok(VTFImageFormat::RGBA8888), + 1 => Ok(VTFImageFormat::ABGR8888), + 2 => Ok(VTFImageFormat::RGB888), + 3 => Ok(VTFImageFormat::BGR888), + 4 => Ok(VTFImageFormat::RGB565), + 5 => Ok(VTFImageFormat::I8), + 6 => Ok(VTFImageFormat::IA88), + 7 => Ok(VTFImageFormat::P8), + 8 => Ok(VTFImageFormat::A8), + 9 => Ok(VTFImageFormat::RGB888BlueScreen), + 10 => Ok(VTFImageFormat::BGR888BlueScreen), + 11 => Ok(VTFImageFormat::ARGB8888), + 12 => Ok(VTFImageFormat::BGRA8888), + 13 => Ok(VTFImageFormat::DXT1), + 14 => Ok(VTFImageFormat::DXT3), + 15 => Ok(VTFImageFormat::DXT5), + 16 => Ok(VTFImageFormat::BGRX8888), + 17 => Ok(VTFImageFormat::BGR565), + 18 => Ok(VTFImageFormat::BGRX5551), + 19 => Ok(VTFImageFormat::BGRA4444), + 20 => Ok(VTFImageFormat::DXT1OneBitAlpha), + 21 => Ok(VTFImageFormat::BGRA5551), + 22 => Ok(VTFImageFormat::UV88), + 23 => Ok(VTFImageFormat::UVWQ8888), + 24 => Ok(VTFImageFormat::RGBA16161616F), + 25 => Ok(VTFImageFormat::RGBA16161616), + 26 => Ok(VTFImageFormat::UVLX8888), + variant => Err(DecodeError::UnexpectedVariant { + type_name: "VTFImageFormat", + allowed: &AllowedEnumVariants::Range { min: 0, max: 26 }, + found: variant as u32, + }), + } + } +} + +impl VTFImageFormat { + pub fn bytes(&self, width: usize, height: usize) -> Result { + match self { + VTFImageFormat::None => Err(VTFImageFormat::None), + VTFImageFormat::RGBA8888 => Ok(width * height * 4), + VTFImageFormat::ABGR8888 => Ok(width * height * 4), + VTFImageFormat::RGB888 => Ok(width * height * 3), + VTFImageFormat::BGR888 => Ok(width * height * 3), + VTFImageFormat::RGB565 => Err(VTFImageFormat::RGB565), + VTFImageFormat::I8 => Ok(width * height * 1), + VTFImageFormat::IA88 => Err(VTFImageFormat::IA88), + VTFImageFormat::P8 => Err(VTFImageFormat::P8), + VTFImageFormat::A8 => Ok(width * height * 1), + VTFImageFormat::RGB888BlueScreen => Err(VTFImageFormat::RGB888BlueScreen), + VTFImageFormat::BGR888BlueScreen => Err(VTFImageFormat::BGR888BlueScreen), + VTFImageFormat::ARGB8888 => Ok(width * height * 4), + VTFImageFormat::BGRA8888 => Ok(width * height * 4), + VTFImageFormat::DXT1 => Ok(texpresso::Format::Bc1.compressed_size(width, height)), + VTFImageFormat::DXT3 => Ok(texpresso::Format::Bc2.compressed_size(width, height)), + VTFImageFormat::DXT5 => Ok(texpresso::Format::Bc3.compressed_size(width, height)), + VTFImageFormat::BGRX8888 => Err(VTFImageFormat::BGRX8888), + VTFImageFormat::BGR565 => Err(VTFImageFormat::BGR565), + VTFImageFormat::BGRX5551 => Err(VTFImageFormat::BGRX5551), + VTFImageFormat::BGRA4444 => Err(VTFImageFormat::BGRA4444), + VTFImageFormat::DXT1OneBitAlpha => Err(VTFImageFormat::DXT1OneBitAlpha), + VTFImageFormat::BGRA5551 => Err(VTFImageFormat::BGRA5551), + VTFImageFormat::UV88 => Err(VTFImageFormat::UV88), + VTFImageFormat::UVWQ8888 => Err(VTFImageFormat::UVWQ8888), + VTFImageFormat::RGBA16161616F => Err(VTFImageFormat::RGBA16161616F), + VTFImageFormat::RGBA16161616 => Err(VTFImageFormat::RGBA16161616), + VTFImageFormat::UVLX8888 => Err(VTFImageFormat::UVLX8888), + } + } +} + +impl_borrow_decode!(VTFImageFormat); + +#[derive(Debug, Decode)] +pub struct VTFResourceEntryInfo { + _tag: [u8; 3], + pub flags: u8, + pub offset: u32, +} + +#[derive(Debug)] +pub struct VTFMipMap { + pub width: u16, + pub height: u16, + pub frames: Vec, +} + +#[derive(Debug)] +pub struct VTFFrame { + pub offset: usize, + pub bytes: usize, +} + +#[derive(Debug)] +pub struct VTFData { + pub width: u16, + pub height: u16, + pub rgba: Vec, +} + +#[derive(Debug)] +pub enum VTFError { + DecodeError(DecodeError), + FormatError(VTFImageFormat), +} + +impl Error for VTFError {} + +impl Display for VTFError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:#?}", self) + } +} + +impl From for VTFError { + fn from(value: DecodeError) -> Self { + VTFError::DecodeError(value) + } +} + +impl From for VTFError { + fn from(value: VTFImageFormat) -> Self { + VTFError::FormatError(value) + } +} + +impl Into for VTFError { + fn into(self) -> JsValue { + JsValue::from(JsError::new(&format!("{:?}", self))) + } +} #[wasm_bindgen] impl VTF { - #[wasm_bindgen(js_name = "putImageData")] - pub fn put_image_data(self, context: &CanvasRenderingContext2d, mipmap_index: usize, frame_index: usize) -> Result<(), VTFError> { - let VTFData { width, height, rgba } = self.extract(mipmap_index, frame_index)?; - let data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&rgba), width as u32, height as u32).unwrap(); - context.put_image_data(&data, 0.0, 0.0).unwrap(); - Ok(()) + #[wasm_bindgen(constructor)] + pub fn new(buf: Vec) -> Result { + let mut reader = BufReader::new(Cursor::new(&buf)); + let config = bincode::config::standard().with_fixed_int_encoding(); + + let header: VTFHeader = bincode::decode_from_reader(&mut reader, config)?; + + if header.version_major >= 7 && header.version_minor >= 2 { + let _depth: u16 = bincode::decode_from_reader(&mut reader, config)?; + } + + let num_resources_option = if header.version_major >= 7 && header.version_minor >= 3 { + let _padding2: [u8; 3] = bincode::decode_from_reader(&mut reader, config)?; + let num_resources: u32 = bincode::decode_from_reader(&mut reader, config)?; + Some(num_resources) + } else { + None + }; + + let _padding3: [u8; 8] = bincode::decode_from_reader(&mut reader, config)?; + + let resources = match num_resources_option { + Some(num_resources) => Some( + (0..num_resources) + .map(|_| bincode::decode_from_reader::(&mut reader, config)) + .collect::, DecodeError>>()?, + ), + None => None, + }; + + reader.seek(SeekFrom::Start(header.header_size as u64)).or_else(|_| { + Err(DecodeError::UnexpectedEnd { + additional: header.header_size as usize, + }) + })?; + + let thumbnail_bytes = texpresso::Format::Bc1.compressed_size(header.low_res_image_width as usize, header.low_res_image_height as usize); + reader + .seek_relative(thumbnail_bytes as i64) + .or_else(|_| Err(DecodeError::UnexpectedEnd { additional: thumbnail_bytes }))?; + + let mipmaps = (0..header.mipmap_count) + .rev() + .map(|i| -> Result { + let width = (header.width >> i) as usize; + let height = (header.height >> i) as usize; + + let bytes = header.high_res_image_format.bytes(width, height)?; + + let frames = (0..header.frames) + .map(|_| { + let offset = reader.stream_position().unwrap() as usize; + reader.seek_relative(bytes as i64).or_else(|_| Err(DecodeError::UnexpectedEnd { additional: bytes }))?; + Ok(VTFFrame { offset, bytes }) + }) + .collect::, VTFError>>()?; + + Ok(VTFMipMap { + width: width as u16, + height: height as u16, + frames, + }) + }) + .collect::, VTFError>>(); + + Ok(VTF { buf, header, resources, mipmaps }) + } +} + +impl VTF { + pub fn extract(self, mipmap_index: usize, frame_index: usize) -> Result { + let mipmaps = self.mipmaps?; + let mipmap = mipmaps.get(mipmap_index).ok_or_else(|| VTFError::FormatError(self.header.high_res_image_format))?; + let frame = mipmap.frames.get(frame_index).ok_or_else(|| VTFError::FormatError(self.header.high_res_image_format))?; + + let buf = self + .buf + .get(frame.offset..(frame.offset + frame.bytes)) + .ok_or_else(|| DecodeError::UnexpectedEnd { additional: frame.bytes })?; + + let mut rgba = vec![255; mipmap.width as usize * mipmap.height as usize * 4]; + + match self.header.high_res_image_format { + VTFImageFormat::RGBA8888 => { + rgba.copy_from_slice(buf); + } + VTFImageFormat::ABGR8888 => { + let mut i = 0; + for chunk in buf.chunks_exact(4) { + rgba[i] = chunk[3]; + rgba[i + 1] = chunk[2]; + rgba[i + 2] = chunk[1]; + rgba[i + 3] = chunk[0]; + i += 4; + } + } + VTFImageFormat::RGB888 => { + let mut i = 0; + for chunk in buf.chunks_exact(3) { + rgba[i] = chunk[0]; + rgba[i + 1] = chunk[1]; + rgba[i + 2] = chunk[2]; + rgba[i + 3] = 255; + i += 4; + } + } + VTFImageFormat::BGR888 => { + let mut i = 0; + for chunk in buf.chunks_exact(3) { + rgba[i] = chunk[3]; + rgba[i + 1] = chunk[2]; + rgba[i + 2] = chunk[1]; + rgba[i + 3] = 255; + i += 4; + } + } + VTFImageFormat::I8 => { + let mut i = 0; + for byte in buf { + rgba[i] = *byte; + rgba[i + 1] = *byte; + rgba[i + 2] = *byte; + rgba[i + 3] = 255; + i += 4; + } + } + VTFImageFormat::A8 => { + let mut i = 0; + for byte in buf { + rgba[i] = 0; + rgba[i + 1] = 0; + rgba[i + 2] = 0; + rgba[i + 3] = *byte; + i += 4; + } + } + VTFImageFormat::ARGB8888 => { + let mut i = 0; + for chunk in buf.chunks_exact(4) { + rgba[i] = chunk[1]; + rgba[i + 1] = chunk[2]; + rgba[i + 2] = chunk[3]; + rgba[i + 3] = chunk[0]; + i += 4; + } + } + VTFImageFormat::BGRA8888 => { + let mut i = 0; + for chunk in buf.chunks_exact(4) { + rgba[i] = chunk[2]; + rgba[i + 1] = chunk[1]; + rgba[i + 2] = chunk[0]; + rgba[i + 3] = chunk[3]; + i += 4; + } + } + VTFImageFormat::DXT1 => { + texpresso::Format::Bc1.decompress(&buf, mipmap.width as usize, mipmap.height as usize, &mut rgba); + } + VTFImageFormat::DXT3 => { + texpresso::Format::Bc2.decompress(&buf, mipmap.width as usize, mipmap.height as usize, &mut rgba); + } + VTFImageFormat::DXT5 => { + texpresso::Format::Bc3.decompress(&buf, mipmap.width as usize, mipmap.height as usize, &mut rgba); + } + _variant => unreachable!(), + }; + + Ok(VTFData { + width: mipmap.width, + height: mipmap.height, + rgba, + }) } } diff --git a/packages/vtf/src/vtf.rs b/packages/vtf/src/vtf.rs deleted file mode 100644 index e15b3b58..00000000 --- a/packages/vtf/src/vtf.rs +++ /dev/null @@ -1,418 +0,0 @@ -use std::{ - error::Error, - fmt::Display, - io::{BufReader, Cursor, Seek, SeekFrom}, -}; - -use bincode::{ - error::{AllowedEnumVariants, DecodeError}, - impl_borrow_decode, Decode, -}; -use wasm_bindgen::{prelude::wasm_bindgen, JsError, JsValue}; - -#[wasm_bindgen] -#[derive(Debug)] -pub struct VTF { - #[wasm_bindgen(skip)] - pub buf: Vec, - pub header: VTFHeader, - - #[wasm_bindgen(skip)] - pub resources: Option>, - - #[wasm_bindgen(skip)] - pub mipmaps: Result, VTFError>, -} - -#[wasm_bindgen] -#[derive(Debug, Clone, Copy, Decode)] -pub struct VTFHeader { - pub signature: VTFSignature, - pub version_major: u32, - pub version_minor: u32, - pub header_size: u32, - pub width: u16, - pub height: u16, - pub flags: u32, - pub frames: u16, - pub first_frame: u16, - _padding0: [u8; 4], - _reflectivity: [f32; 3], - _padding1: [u8; 4], - pub bumpmap_scale: f32, - pub high_res_image_format: VTFImageFormat, - pub mipmap_count: u8, - pub low_res_image_format: VTFImageFormat, - pub low_res_image_width: u8, - pub low_res_image_height: u8, -} - -#[wasm_bindgen] -#[derive(Debug, Clone, Copy)] -pub struct VTFSignature(); - -impl Display for VTFSignature { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "VTF\0") - } -} - -impl Decode for VTFSignature { - fn decode(decoder: &mut D) -> Result { - match <[u8; 4] as bincode::Decode>::decode(decoder)? { - [b'V', b'T', b'F', b'\0'] => Ok(VTFSignature()), - _ => Err(DecodeError::Other("VTF\0")), - } - } -} - -impl_borrow_decode!(VTFSignature); - -#[wasm_bindgen] -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(i32)] -pub enum VTFImageFormat { - None = -1, - RGBA8888, - ABGR8888, - RGB888, - BGR888, - RGB565, - I8, - IA88, - P8, - A8, - RGB888BlueScreen, - BGR888BlueScreen, - ARGB8888, - BGRA8888, - DXT1, - DXT3, - DXT5, - BGRX8888, - BGR565, - BGRX5551, - BGRA4444, - DXT1OneBitAlpha, - BGRA5551, - UV88, - UVWQ8888, - RGBA16161616F, - RGBA16161616, - UVLX8888, -} - -impl Decode for VTFImageFormat { - fn decode(decoder: &mut D) -> Result { - let variant_value = ::decode(decoder)?; - match variant_value { - -1 => Ok(VTFImageFormat::None), - 0 => Ok(VTFImageFormat::RGBA8888), - 1 => Ok(VTFImageFormat::ABGR8888), - 2 => Ok(VTFImageFormat::RGB888), - 3 => Ok(VTFImageFormat::BGR888), - 4 => Ok(VTFImageFormat::RGB565), - 5 => Ok(VTFImageFormat::I8), - 6 => Ok(VTFImageFormat::IA88), - 7 => Ok(VTFImageFormat::P8), - 8 => Ok(VTFImageFormat::A8), - 9 => Ok(VTFImageFormat::RGB888BlueScreen), - 10 => Ok(VTFImageFormat::BGR888BlueScreen), - 11 => Ok(VTFImageFormat::ARGB8888), - 12 => Ok(VTFImageFormat::BGRA8888), - 13 => Ok(VTFImageFormat::DXT1), - 14 => Ok(VTFImageFormat::DXT3), - 15 => Ok(VTFImageFormat::DXT5), - 16 => Ok(VTFImageFormat::BGRX8888), - 17 => Ok(VTFImageFormat::BGR565), - 18 => Ok(VTFImageFormat::BGRX5551), - 19 => Ok(VTFImageFormat::BGRA4444), - 20 => Ok(VTFImageFormat::DXT1OneBitAlpha), - 21 => Ok(VTFImageFormat::BGRA5551), - 22 => Ok(VTFImageFormat::UV88), - 23 => Ok(VTFImageFormat::UVWQ8888), - 24 => Ok(VTFImageFormat::RGBA16161616F), - 25 => Ok(VTFImageFormat::RGBA16161616), - 26 => Ok(VTFImageFormat::UVLX8888), - variant => Err(DecodeError::UnexpectedVariant { - type_name: "VTFImageFormat", - allowed: &AllowedEnumVariants::Range { min: 0, max: 26 }, - found: variant as u32, - }), - } - } -} - -impl VTFImageFormat { - pub fn bytes(&self, width: usize, height: usize) -> Result { - match self { - VTFImageFormat::None => Err(VTFImageFormat::None), - VTFImageFormat::RGBA8888 => Ok(width * height * 4), - VTFImageFormat::ABGR8888 => Ok(width * height * 4), - VTFImageFormat::RGB888 => Ok(width * height * 3), - VTFImageFormat::BGR888 => Ok(width * height * 3), - VTFImageFormat::RGB565 => Err(VTFImageFormat::RGB565), - VTFImageFormat::I8 => Ok(width * height * 1), - VTFImageFormat::IA88 => Err(VTFImageFormat::IA88), - VTFImageFormat::P8 => Err(VTFImageFormat::P8), - VTFImageFormat::A8 => Ok(width * height * 1), - VTFImageFormat::RGB888BlueScreen => Err(VTFImageFormat::RGB888BlueScreen), - VTFImageFormat::BGR888BlueScreen => Err(VTFImageFormat::BGR888BlueScreen), - VTFImageFormat::ARGB8888 => Ok(width * height * 4), - VTFImageFormat::BGRA8888 => Ok(width * height * 4), - VTFImageFormat::DXT1 => Ok(texpresso::Format::Bc1.compressed_size(width, height)), - VTFImageFormat::DXT3 => Ok(texpresso::Format::Bc2.compressed_size(width, height)), - VTFImageFormat::DXT5 => Ok(texpresso::Format::Bc3.compressed_size(width, height)), - VTFImageFormat::BGRX8888 => Err(VTFImageFormat::BGRX8888), - VTFImageFormat::BGR565 => Err(VTFImageFormat::BGR565), - VTFImageFormat::BGRX5551 => Err(VTFImageFormat::BGRX5551), - VTFImageFormat::BGRA4444 => Err(VTFImageFormat::BGRA4444), - VTFImageFormat::DXT1OneBitAlpha => Err(VTFImageFormat::DXT1OneBitAlpha), - VTFImageFormat::BGRA5551 => Err(VTFImageFormat::BGRA5551), - VTFImageFormat::UV88 => Err(VTFImageFormat::UV88), - VTFImageFormat::UVWQ8888 => Err(VTFImageFormat::UVWQ8888), - VTFImageFormat::RGBA16161616F => Err(VTFImageFormat::RGBA16161616F), - VTFImageFormat::RGBA16161616 => Err(VTFImageFormat::RGBA16161616), - VTFImageFormat::UVLX8888 => Err(VTFImageFormat::UVLX8888), - } - } -} - -impl_borrow_decode!(VTFImageFormat); - -#[derive(Debug, Decode)] -pub struct VTFResourceEntryInfo { - _tag: [u8; 3], - pub flags: u8, - pub offset: u32, -} - -#[derive(Debug)] -pub struct VTFMipMap { - pub width: u16, - pub height: u16, - pub frames: Vec, -} - -#[derive(Debug)] -pub struct VTFFrame { - pub offset: usize, - pub bytes: usize, -} - -#[derive(Debug)] -pub struct VTFData { - pub width: u16, - pub height: u16, - pub rgba: Vec, -} - -#[derive(Debug)] -pub enum VTFError { - DecodeError(DecodeError), - FormatError(VTFImageFormat), -} - -impl Error for VTFError {} - -impl Display for VTFError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:#?}", self) - } -} - -impl From for VTFError { - fn from(value: DecodeError) -> Self { - VTFError::DecodeError(value) - } -} - -impl From for VTFError { - fn from(value: VTFImageFormat) -> Self { - VTFError::FormatError(value) - } -} - -impl Into for VTFError { - fn into(self) -> JsValue { - JsValue::from(JsError::new(&format!("{:?}", self))) - } -} - -#[wasm_bindgen] -impl VTF { - #[wasm_bindgen(constructor)] - pub fn new(buf: Vec) -> Result { - let mut reader = BufReader::new(Cursor::new(&buf)); - let config = bincode::config::standard().with_fixed_int_encoding(); - - let header: VTFHeader = bincode::decode_from_reader(&mut reader, config)?; - - if header.version_major >= 7 && header.version_minor >= 2 { - let _depth: u16 = bincode::decode_from_reader(&mut reader, config)?; - } - - let num_resources_option = if header.version_major >= 7 && header.version_minor >= 3 { - let _padding2: [u8; 3] = bincode::decode_from_reader(&mut reader, config)?; - let num_resources: u32 = bincode::decode_from_reader(&mut reader, config)?; - Some(num_resources) - } else { - None - }; - - let _padding3: [u8; 8] = bincode::decode_from_reader(&mut reader, config)?; - - let resources = match num_resources_option { - Some(num_resources) => Some( - (0..num_resources) - .map(|_| bincode::decode_from_reader::(&mut reader, config)) - .collect::, DecodeError>>()?, - ), - None => None, - }; - - reader.seek(SeekFrom::Start(header.header_size as u64)).or_else(|_| { - Err(DecodeError::UnexpectedEnd { - additional: header.header_size as usize, - }) - })?; - - let thumbnail_bytes = texpresso::Format::Bc1.compressed_size(header.low_res_image_width as usize, header.low_res_image_height as usize); - reader - .seek_relative(thumbnail_bytes as i64) - .or_else(|_| Err(DecodeError::UnexpectedEnd { additional: thumbnail_bytes }))?; - - let mipmaps = (0..header.mipmap_count) - .rev() - .map(|i| -> Result { - let width = (header.width >> i) as usize; - let height = (header.height >> i) as usize; - - let bytes = header.high_res_image_format.bytes(width, height)?; - - let frames = (0..header.frames) - .map(|_| { - let offset = reader.stream_position().unwrap() as usize; - reader.seek_relative(bytes as i64).or_else(|_| Err(DecodeError::UnexpectedEnd { additional: bytes }))?; - Ok(VTFFrame { offset, bytes }) - }) - .collect::, VTFError>>()?; - - Ok(VTFMipMap { - width: width as u16, - height: height as u16, - frames, - }) - }) - .collect::, VTFError>>(); - - Ok(VTF { buf, header, resources, mipmaps }) - } -} - -impl VTF { - pub fn extract(self, mipmap_index: usize, frame_index: usize) -> Result { - let mipmaps = self.mipmaps?; - let mipmap = mipmaps.get(mipmap_index).ok_or_else(|| VTFError::FormatError(self.header.high_res_image_format))?; - let frame = mipmap.frames.get(frame_index).ok_or_else(|| VTFError::FormatError(self.header.high_res_image_format))?; - - let buf = self - .buf - .get(frame.offset..(frame.offset + frame.bytes)) - .ok_or_else(|| DecodeError::UnexpectedEnd { additional: frame.bytes })?; - - let mut rgba = vec![255; mipmap.width as usize * mipmap.height as usize * 4]; - - match self.header.high_res_image_format { - VTFImageFormat::RGBA8888 => { - rgba.copy_from_slice(buf); - } - VTFImageFormat::ABGR8888 => { - let mut i = 0; - for chunk in buf.chunks_exact(4) { - rgba[i] = chunk[3]; - rgba[i + 1] = chunk[2]; - rgba[i + 2] = chunk[1]; - rgba[i + 3] = chunk[0]; - i += 4; - } - } - VTFImageFormat::RGB888 => { - let mut i = 0; - for chunk in buf.chunks_exact(3) { - rgba[i] = chunk[0]; - rgba[i + 1] = chunk[1]; - rgba[i + 2] = chunk[2]; - rgba[i + 3] = 255; - i += 4; - } - } - VTFImageFormat::BGR888 => { - let mut i = 0; - for chunk in buf.chunks_exact(3) { - rgba[i] = chunk[3]; - rgba[i + 1] = chunk[2]; - rgba[i + 2] = chunk[1]; - rgba[i + 3] = 255; - i += 4; - } - } - VTFImageFormat::I8 => { - let mut i = 0; - for byte in buf { - rgba[i] = *byte; - rgba[i + 1] = *byte; - rgba[i + 2] = *byte; - rgba[i + 3] = 255; - i += 4; - } - } - VTFImageFormat::A8 => { - let mut i = 0; - for byte in buf { - rgba[i] = 0; - rgba[i + 1] = 0; - rgba[i + 2] = 0; - rgba[i + 3] = *byte; - i += 4; - } - } - VTFImageFormat::ARGB8888 => { - let mut i = 0; - for chunk in buf.chunks_exact(4) { - rgba[i] = chunk[1]; - rgba[i + 1] = chunk[2]; - rgba[i + 2] = chunk[3]; - rgba[i + 3] = chunk[0]; - i += 4; - } - } - VTFImageFormat::BGRA8888 => { - let mut i = 0; - for chunk in buf.chunks_exact(4) { - rgba[i] = chunk[2]; - rgba[i + 1] = chunk[1]; - rgba[i + 2] = chunk[0]; - rgba[i + 3] = chunk[3]; - i += 4; - } - } - VTFImageFormat::DXT1 => { - texpresso::Format::Bc1.decompress(&buf, mipmap.width as usize, mipmap.height as usize, &mut rgba); - } - VTFImageFormat::DXT3 => { - texpresso::Format::Bc2.decompress(&buf, mipmap.width as usize, mipmap.height as usize, &mut rgba); - } - VTFImageFormat::DXT5 => { - texpresso::Format::Bc3.decompress(&buf, mipmap.width as usize, mipmap.height as usize, &mut rgba); - } - _variant => unreachable!(), - }; - - Ok(VTFData { - width: mipmap.width, - height: mipmap.height, - rgba, - }) - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 55dc61c1..0531a176 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,7 +35,7 @@ importers: version: 7.8.1 ts-loader: specifier: ^9.5.1 - version: 9.5.1(typescript@5.6.3)(webpack@5.96.1) + version: 9.5.1(typescript@5.6.3)(webpack@5.97.1) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@22.9.0)(typescript@5.6.3) @@ -49,11 +49,11 @@ importers: specifier: ^1.0.11 version: 1.0.12 webpack: - specifier: ^5.96.1 - version: 5.96.1(webpack-cli@5.1.4) + specifier: ^5.97.1 + version: 5.97.1(webpack-cli@5.1.4) webpack-cli: specifier: ^5.1.4 - version: 5.1.4(webpack@5.96.1) + version: 5.1.4(webpack@5.97.1) zod: specifier: ^3.23.8 version: 3.23.8 @@ -183,9 +183,9 @@ importers: vite: specifier: ^6.0.3 version: 6.0.3(@types/node@22.9.0)(jiti@1.21.7)(terser@5.36.0)(yaml@2.7.0) - vtf: + vtf-canvas: specifier: workspace:^ - version: link:../../packages/vtf + version: link:../../packages/vtf-canvas packages/client: devDependencies: @@ -210,6 +210,9 @@ importers: vscode-languageclient: specifier: ^9.0.1 version: 9.0.1 + vtf-png: + specifier: workspace:^ + version: link:../vtf-png publishDirectory: src packages/common: @@ -335,6 +338,10 @@ importers: packages/vtf: {} + packages/vtf-canvas: {} + + packages/vtf-png: {} + packages: '@alloc/quick-lru@5.2.0': @@ -1619,11 +1626,6 @@ packages: browserify-zlib@0.1.4: resolution: {integrity: sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==} - browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - browserslist@4.24.4: resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -2145,9 +2147,6 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.54: - resolution: {integrity: sha512-TX6vHleisn5i/4pekTyy1sdoLXQNy8VFvBK/fJRXSyp7GUO27KioLTG0Qo5wFjM3ZF4ryKinDo4m+IJ+rwUWSw==} - electron-to-chromium@1.5.83: resolution: {integrity: sha512-LcUDPqSt+V0QmI47XLzZrz5OqILSMGsPFkDYus22rIbgorSvBYEFqq854ltTmUdHkY92FSdAAvsh4jWEULMdfQ==} @@ -3193,9 +3192,6 @@ packages: node-addon-api@4.3.0: resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} - node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -4123,12 +4119,6 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} - update-browserslist-db@1.1.1: - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - update-browserslist-db@1.1.2: resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} hasBin: true @@ -4272,8 +4262,8 @@ packages: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} - webpack@5.96.1: - resolution: {integrity: sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==} + webpack@5.97.1: + resolution: {integrity: sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -5491,20 +5481,20 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.96.1)': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.97.1)': dependencies: - webpack: 5.96.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.96.1) + webpack: 5.97.1(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.97.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.96.1)': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.97.1)': dependencies: - webpack: 5.96.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.96.1) + webpack: 5.97.1(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.97.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.96.1)': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.97.1)': dependencies: - webpack: 5.96.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack@5.96.1) + webpack: 5.97.1(webpack-cli@5.1.4) + webpack-cli: 5.1.4(webpack@5.97.1) '@xtuc/ieee754@1.2.0': {} @@ -5667,13 +5657,6 @@ snapshots: dependencies: pako: 0.2.9 - browserslist@4.24.2: - dependencies: - caniuse-lite: 1.0.30001692 - electron-to-chromium: 1.5.54 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) - browserslist@4.24.4: dependencies: caniuse-lite: 1.0.30001692 @@ -6209,8 +6192,6 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.54: {} - electron-to-chromium@1.5.83: {} emoji-regex-xs@1.0.0: {} @@ -7770,8 +7751,6 @@ snapshots: node-addon-api@4.3.0: optional: true - node-releases@2.0.18: {} - node-releases@2.0.19: {} normalize-path@3.0.0: {} @@ -8678,14 +8657,14 @@ snapshots: fast-fifo: 1.3.2 streamx: 2.20.1 - terser-webpack-plugin@5.3.10(webpack@5.96.1): + terser-webpack-plugin@5.3.10(webpack@5.97.1): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.36.0 - webpack: 5.96.1(webpack-cli@5.1.4) + webpack: 5.97.1(webpack-cli@5.1.4) terser@5.36.0: dependencies: @@ -8733,7 +8712,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-loader@9.5.1(typescript@5.6.3)(webpack@5.96.1): + ts-loader@9.5.1(typescript@5.6.3)(webpack@5.97.1): dependencies: chalk: 4.1.2 enhanced-resolve: 5.17.1 @@ -8741,7 +8720,7 @@ snapshots: semver: 7.6.3 source-map: 0.7.4 typescript: 5.6.3 - webpack: 5.96.1(webpack-cli@5.1.4) + webpack: 5.97.1(webpack-cli@5.1.4) ts-node@10.9.2(@types/node@22.9.0)(typescript@5.6.3): dependencies: @@ -8909,12 +8888,6 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - update-browserslist-db@1.1.1(browserslist@4.24.2): - dependencies: - browserslist: 4.24.2 - escalade: 3.2.0 - picocolors: 1.1.1 - update-browserslist-db@1.1.2(browserslist@4.24.4): dependencies: browserslist: 4.24.4 @@ -8998,12 +8971,12 @@ snapshots: web-namespaces@2.0.1: {} - webpack-cli@5.1.4(webpack@5.96.1): + webpack-cli@5.1.4(webpack@5.97.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.96.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.96.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.96.1) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.97.1) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.97.1) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack@5.97.1) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.5 @@ -9012,7 +8985,7 @@ snapshots: import-local: 3.2.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.96.1(webpack-cli@5.1.4) + webpack: 5.97.1(webpack-cli@5.1.4) webpack-merge: 5.10.0 webpack-merge@5.10.0: @@ -9023,7 +8996,7 @@ snapshots: webpack-sources@3.2.3: {} - webpack@5.96.1(webpack-cli@5.1.4): + webpack@5.97.1(webpack-cli@5.1.4): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.6 @@ -9031,7 +9004,7 @@ snapshots: '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.14.0 - browserslist: 4.24.2 + browserslist: 4.24.4 chrome-trace-event: 1.0.4 enhanced-resolve: 5.17.1 es-module-lexer: 1.5.4 @@ -9045,11 +9018,11 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.96.1) + terser-webpack-plugin: 5.3.10(webpack@5.97.1) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: - webpack-cli: 5.1.4(webpack@5.96.1) + webpack-cli: 5.1.4(webpack@5.97.1) transitivePeerDependencies: - '@swc/core' - esbuild diff --git a/packages/vtf/rustfmt.toml b/rustfmt.toml similarity index 100% rename from packages/vtf/rustfmt.toml rename to rustfmt.toml