diff --git a/.forgejo/workflows/build-release.yml b/.forgejo/workflows/build-release.yml index 69aea21..91efadd 100644 --- a/.forgejo/workflows/build-release.yml +++ b/.forgejo/workflows/build-release.yml @@ -15,7 +15,9 @@ jobs: - name: 🚀 Setup & Run tests run: | - nix-shell -p cargo rustc --run " + nix-shell --run " + git-lfs fetch + git-lfs pull cargo test --release --all " @@ -29,47 +31,41 @@ jobs: target: - x86_64-unknown-linux-gnu - x86_64-pc-windows-msvc - #- x86_64-apple-darwin + - x86_64-apple-darwin - aarch64-unknown-linux-gnu - aarch64-pc-windows-msvc - #- aarch64-apple-darwin + - aarch64-apple-darwin include: - target: x86_64-unknown-linux-gnu binary_name: zenyx-x86_64-linux ext: "" - linker: /lib64/ld-linux-x86-64.so.2 command: zigbuild args: --target x86_64-unknown-linux-gnu --release - target: aarch64-unknown-linux-gnu binary_name: zenyx-aarch64-linux ext: "" - linker: /lib/ld-linux-aarch64.so.1 command: zigbuild args: --target aarch64-unknown-linux-gnu --release - target: x86_64-pc-windows-msvc binary_name: zenyx-x86_64-windows ext: ".exe" - linker: "" command: xwin build args: --target x86_64-pc-windows-msvc --release - target: aarch64-pc-windows-msvc binary_name: zenyx-aarch64-windows ext: ".exe" - linker: "" command: xwin build args: --target aarch64-pc-windows-msvc --release - #- target: x86_64-apple-darwin - # binary_name: zenyx-x86_64-macos - # ext: "" - # linker: "" - #command: zigbuild - #args: --target x86_64-apple-darwin --release - #target: aarch64-apple-darwin - #binary_name: zenyx-aarch64-macos - #ext: "" - #linker: "" - #command: zigbuild - #args: --target aarch64-apple-darwin --release + - target: x86_64-apple-darwin + binary_name: zenyx-x86_64-macos + ext: "" + command: zigbuild + args: --target x86_64-apple-darwin --release + - target: aarch64-apple-darwin + binary_name: zenyx-aarch64-macos + ext: "" + command: zigbuild + args: --target aarch64-apple-darwin --release steps: - name: 📥 Checkout source @@ -78,6 +74,8 @@ jobs: - name: 🚀 Install Target & Build release binary run: | nix-shell --run " + git-lfs fetch --all + git-lfs pull cargo ${{ matrix.command }} ${{ matrix.args }} " @@ -86,19 +84,10 @@ jobs: mkdir -p artifacts cp target/${{ matrix.target }}/release/zenyx${{ matrix.ext }} artifacts/${{ matrix.binary_name }}${{ matrix.ext }} - - name: 🛠️ Patchelf - if: ${{ - matrix.target == 'x86_64-unknown-linux-gnu' || - matrix.target == 'aarch64-unknown-linux-gnu' - }} - run: | - nix run --extra-experimental-features nix-command --extra-experimental-features flakes nixpkgs#patchelf -- --set-interpreter ${{ matrix.linker }} \ - artifacts/${{ matrix.binary_name }}${{ matrix.ext }} - - name: ⬆️ Upload artifact uses: https://code.forgejo.org/forgejo/upload-artifact@v4 with: - name: ${{ matrix.binary_name }}.zip + name: ${{ matrix.binary_name }}${{ matrix.ext }}.zip path: artifacts/${{ matrix.binary_name }}${{ matrix.ext }} compression-level: 9 - if-no-files-found: error + if-no-files-found: error \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 77318c1..ab4c1ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.15", + "getrandom 0.2.16", "once_cell", "version_check", "zerocopy 0.7.35", @@ -173,14 +173,15 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" dependencies = [ "async-task", "concurrent-queue", "fastrand", "futures-lite", + "pin-project-lite", "slab", ] @@ -300,7 +301,7 @@ dependencies = [ "anyhow", "arrayvec", "log", - "nom", + "nom 7.1.3", "num-rational", "v_frame", ] @@ -384,12 +385,6 @@ dependencies = [ "piper", ] -[[package]] -name = "build-print" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a2128d00b7061b82b72844a351e80acd29e05afc60e9261e2ac90dca9ecc2ac" - [[package]] name = "built" version = "0.7.7" @@ -404,9 +399,9 @@ checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "bytemuck" -version = "1.22.0" +version = "1.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" dependencies = [ "bytemuck_derive", ] @@ -462,9 +457,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.19" +version = "1.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" +checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" dependencies = [ "jobserver", "libc", @@ -511,14 +506,15 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", + "serde", "wasm-bindgen", "windows-link", ] @@ -559,6 +555,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "convert_case" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -569,6 +574,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -582,8 +597,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", "foreign-types", "libc", ] @@ -595,7 +610,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.9.0", + "core-foundation 0.10.0", "libc", ] @@ -654,6 +680,34 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "detect-desktop-environment" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff7f16599c3ba6b4ab9a3195bcd9413a7ee8d51e7651f3e9efd6a5db5315008d" + [[package]] name = "diff" version = "0.1.13" @@ -666,6 +720,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.0", + "objc2 0.6.1", +] + [[package]] name = "dlib" version = "0.5.2" @@ -855,9 +919,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", @@ -946,7 +1010,7 @@ dependencies = [ "log", "presser", "thiserror 1.0.69", - "windows", + "windows 0.58.0", ] [[package]] @@ -983,9 +1047,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "allocator-api2", "equivalent", @@ -1016,6 +1080,28 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" +[[package]] +name = "hidapi" +version = "2.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b876ecf37e86b359573c16c8366bc3eba52b689884a0fc42ba3f67203d2a8b" +dependencies = [ + "cc", + "cfg-if", + "libc", + "pkg-config", + "windows-sys 0.48.0", +] + +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + [[package]] name = "iana-time-zone" version = "0.1.63" @@ -1028,7 +1114,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.61.0", ] [[package]] @@ -1100,6 +1186,15 @@ dependencies = [ "syn", ] +[[package]] +name = "isolang" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe50d48c77760c55188549098b9a7f6e37ae980c586a24693d6b01c3b2010c3c" +dependencies = [ + "phf", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1109,6 +1204,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.15" @@ -1194,9 +1298,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libfuzzer-sys" @@ -1220,9 +1324,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72" [[package]] name = "libredox" @@ -1323,7 +1427,22 @@ checksum = "f569fb946490b5743ad69813cb19629130ce9374034abe31614a36402d18f99e" dependencies = [ "bitflags 2.9.0", "block", - "core-graphics-types", + "core-graphics-types 0.1.3", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "metal" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" +dependencies = [ + "bitflags 2.9.0", + "block", + "core-graphics-types 0.2.0", "foreign-types", "log", "objc", @@ -1365,10 +1484,9 @@ dependencies = [ "num-traits", "once_cell", "petgraph", - "pp-rs", "rustc-hash", "spirv", - "strum", + "strum 0.26.3", "thiserror 2.0.12", "unicode-ident", ] @@ -1428,12 +1546,30 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + [[package]] name = "noop_proc_macro" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1543,9 +1679,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" dependencies = [ "objc2-encode", ] @@ -1604,12 +1740,13 @@ dependencies = [ [[package]] name = "objc2-core-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.0", - "objc2 0.6.0", + "dispatch2", + "objc2 0.6.1", ] [[package]] @@ -1657,12 +1794,12 @@ dependencies = [ [[package]] name = "objc2-foundation" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags 2.9.0", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", ] @@ -1692,13 +1829,13 @@ dependencies = [ [[package]] name = "objc2-metal" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c41bc8b0e50ea7a5304a56f25e0066f526e99641b46fd7b9ad4421dd35bff6" +checksum = "7f246c183239540aab1782457b35ab2040d4259175bd1d0c58e46ada7b47a874" dependencies = [ "bitflags 2.9.0", - "objc2 0.6.0", - "objc2-foundation 0.3.0", + "objc2 0.6.1", + "objc2-foundation 0.3.1", ] [[package]] @@ -1716,15 +1853,15 @@ dependencies = [ [[package]] name = "objc2-quartz-core" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb3794501bb1bee12f08dcad8c61f2a5875791ad1c6f47faa71a0f033f20071" +checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" dependencies = [ "bitflags 2.9.0", - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", - "objc2-foundation 0.3.0", - "objc2-metal 0.3.0", + "objc2-foundation 0.3.1", + "objc2-metal 0.3.1", ] [[package]] @@ -1874,6 +2011,24 @@ dependencies = [ "serde", ] +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -1951,22 +2106,13 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" -[[package]] -name = "pp-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" -dependencies = [ - "unicode-xid", -] - [[package]] name = "ppv-lite86" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.24", + "zerocopy 0.8.25", ] [[package]] @@ -1996,9 +2142,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -2039,9 +2185,9 @@ checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" [[package]] name = "quick-xml" -version = "0.37.4" +version = "0.37.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369" +checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb" dependencies = [ "memchr", ] @@ -2088,7 +2234,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", ] [[package]] @@ -2111,7 +2257,7 @@ dependencies = [ "built", "cfg-if", "interpolate_name", - "itertools", + "itertools 0.12.1", "libc", "libfuzzer-sys", "log", @@ -2159,10 +2305,10 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" dependencies = [ - "objc2 0.6.0", + "objc2 0.6.1", "objc2-core-foundation", - "objc2-foundation 0.3.0", - "objc2-quartz-core 0.3.0", + "objc2-foundation 0.3.1", + "objc2-quartz-core 0.3.1", ] [[package]] @@ -2386,9 +2532,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -2408,6 +2554,12 @@ dependencies = [ "quote", ] +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -2516,9 +2668,15 @@ version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ - "strum_macros", + "strum_macros 0.26.4", ] +[[package]] +name = "strum" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" + [[package]] name = "strum_macros" version = "0.26.4" @@ -2533,16 +2691,52 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.100" +name = "strum_macros" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + +[[package]] +name = "sysinfo" +version = "0.34.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b93974b3d3aeaa036504b8eefd4c039dced109171c1ae973f1dc63b2c7e4b2" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "serde", + "windows 0.57.0", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -2562,6 +2756,30 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +[[package]] +name = "telemetry" +version = "0.1.0" +dependencies = [ + "ash", + "chrono", + "derive_more", + "detect-desktop-environment", + "hidapi", + "humansize", + "metal 0.32.0", + "serde", + "serde_json", + "strum 0.27.1", + "strum_macros 0.27.1", + "sys-locale", + "sysinfo", + "thiserror 2.0.12", + "timeago", + "versions", + "wgpu", + "winit", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -2638,6 +2856,16 @@ dependencies = [ "weezl", ] +[[package]] +name = "timeago" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1710e589de0a76aaf295cd47a6699f6405737dbfd3cf2b75c92d000b548d0e6" +dependencies = [ + "chrono", + "isolang", +] + [[package]] name = "tiny-skia" version = "0.11.4" @@ -2674,9 +2902,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "05ae329d1f08c4d17a59bed7ff5b5a769d062e64a62d34a3261b219e62cd5aae" dependencies = [ "serde", "serde_spanned", @@ -2686,18 +2914,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" dependencies = [ "indexmap", "serde", @@ -2826,6 +3054,17 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "versions" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80a7e511ce1795821207a837b7b1c8d8aca0c648810966ad200446ae58f6667f" +dependencies = [ + "itertools 0.14.0", + "nom 8.0.0", + "serde", +] + [[package]] name = "vk-parse" version = "0.15.0" @@ -2849,7 +3088,7 @@ dependencies = [ "heck 0.4.1", "indexmap", "libloading", - "nom", + "nom 7.1.3", "once_cell", "parking_lot", "proc-macro2", @@ -2977,9 +3216,9 @@ dependencies = [ [[package]] name = "wayland-backend" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf" +checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" dependencies = [ "cc", "downcast-rs", @@ -2991,9 +3230,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f" +checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" dependencies = [ "bitflags 2.9.0", "rustix", @@ -3014,9 +3253,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.8" +version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d" +checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" dependencies = [ "rustix", "wayland-client", @@ -3025,9 +3264,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.6" +version = "0.32.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc" +checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a" dependencies = [ "bitflags 2.9.0", "wayland-backend", @@ -3037,9 +3276,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccaacc76703fefd6763022ac565b590fcade92202492381c95b2edfdf7d46b3" +checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175" dependencies = [ "bitflags 2.9.0", "wayland-backend", @@ -3050,9 +3289,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2" +checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf" dependencies = [ "bitflags 2.9.0", "wayland-backend", @@ -3212,7 +3451,7 @@ dependencies = [ "bytemuck", "cfg-if", "cfg_aliases", - "core-graphics-types", + "core-graphics-types 0.1.3", "glow", "glutin_wgl_sys", "gpu-alloc", @@ -3224,7 +3463,7 @@ dependencies = [ "libc", "libloading", "log", - "metal", + "metal 0.31.0", "naga", "ndk-sys 0.5.0+25.2.9519653", "objc", @@ -3240,8 +3479,8 @@ dependencies = [ "wasm-bindgen", "web-sys", "wgpu-types", - "windows", - "windows-core", + "windows 0.58.0", + "windows-core 0.58.0", ] [[package]] @@ -3289,13 +3528,35 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" dependencies = [ - "windows-core", + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", "windows-targets 0.52.6", ] @@ -3305,13 +3566,37 @@ version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-strings", + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement 0.60.0", + "windows-interface 0.59.1", + "windows-link", + "windows-result 0.3.2", + "windows-strings 0.4.0", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-implement" version = "0.58.0" @@ -3323,6 +3608,28 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-interface" version = "0.58.0" @@ -3334,12 +3641,32 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-link" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -3349,16 +3676,34 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-strings" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -3368,6 +3713,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3566,9 +3920,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.9" +version = "0.30.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" +checksum = "b0d05bd8908e14618c9609471db04007e644fd9cce6529756046cfc577f9155e" dependencies = [ "ahash", "android-activity", @@ -3579,7 +3933,7 @@ dependencies = [ "calloop", "cfg_aliases", "concurrent-queue", - "core-foundation", + "core-foundation 0.9.4", "core-graphics", "cursor-icon", "dpi", @@ -3618,9 +3972,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" +checksum = "9e27d6ad3dac991091e4d35de9ba2d2d00647c5d0fc26c5496dee55984ae111b" dependencies = [ "memchr", ] @@ -3708,11 +4062,11 @@ name = "zenyx" version = "0.1.0" dependencies = [ "allocator-api2", - "build-print", "bytemuck", "cgmath", "image", - "naga", + "serde", + "serde_json", "smol", "terminator", "thiserror 2.0.12", @@ -3736,11 +4090,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ - "zerocopy-derive 0.8.24", + "zerocopy-derive 0.8.25", ] [[package]] @@ -3756,9 +4110,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 9cb8778..f29ab09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["cdylib"] [workspace] resolver = "2" -members = ["subcrates/renderer", "subcrates/zlog"] +members = ["subcrates/renderer", "subcrates/telemetry", "subcrates/zlog"] [workspace.dependencies] zlog = { path = "subcrates/zlog" } @@ -55,12 +55,8 @@ vulkano = "0.35.1" wgpu = { version = "25.0.0", features = ["spirv"] } zlog.workspace = true allocator-api2 = "0.2.21" +serde_json = "1.0.140" +serde = "1.0.219" [target.aarch64-linux-android.dependencies] winit = { version = "0.30.9", features = ["android-native-activity"] } - -[build-dependencies] -build-print = "0.1.1" -bytemuck = "1.22.0" -naga = { version = "25.0.1", features = ["glsl-in", "spv-out"] } -thiserror = "2.0.12" diff --git a/README.md b/README.md index 22c9743..a3e525d 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Distribute, and use Zenyx for any purpose you wish. | Windows | Primary | ✅ | | | Linux/*BSD | Primary | ✅ | | | macOS | Secondary | ⚠️ | The current main set of maintainers do not own any native MacOS devices to perform tests with. | -| Android | Secondary | ✅ | | +| Android | Help wanted | ❓ | | | iOS | Not planned | ❓ | | | Web | TBD | ❓ | | | Consoles | Not planned | ⛔ | Consoles require specific dev kits,proprietary licenses, and substantial fees that we (Nonsensical-dev,the Zenyx maintainers,and the open source contributors) currently do not have the capacity for. This may change in the future but most likely will not be soon. | diff --git a/build.rs b/build.rs index c7aec40..5235544 100644 --- a/build.rs +++ b/build.rs @@ -1,100 +1,26 @@ -use build_print::{info, warn}; -use naga::{ - ShaderStage, - back::spv::{self, WriterFlags}, - front::glsl::{self, Options as GlslOptions, ParseErrors}, - valid::{ValidationError, ValidationFlags, Validator}, -}; -use std::{ - env, fs, - path::{Path, PathBuf}, -}; -use thiserror::Error; +use std::{env, process::Command}; -#[derive(Debug, Error)] -pub enum BuildError { - #[error("I/O error: {0}")] - Io(#[from] std::io::Error), - #[error("environment variable error: {0}")] - EnvVar(#[from] env::VarError), - #[error("unsupported shader extension: {0}")] - UnsupportedExt(String), - #[error("GLSL parse errors in `{0}`:\n{1}")] - ParseErrors(String, ParseErrors), - #[error("validation errors in `{0}`: {1}")] - ValidateErrors(String, ValidationError), - #[error("SPIR-V write error for `{0}`: {1}")] - Spv(String, spv::Error), -} - -impl From<(String, ParseErrors)> for BuildError { - fn from((s, e): (String, ParseErrors)) -> Self { - BuildError::ParseErrors(s, e) +fn main() { + println!("cargo::rerun-if-changed=shaders"); + let outdir = env::var("OUT_DIR").unwrap(); + let vert = Command::new("glslc") + .args(["shaders/shader.vert", "-o", &format!("{outdir}/vert.spv")]) + .output() + .expect("Failed to execute 'glslc'"); + let frag = Command::new("glslc") + .args(["shaders/shader.frag", "-o", &format!("{outdir}/frag.spv")]) + .output() + .expect("Failed to execute 'glslc'"); + if !vert.status.success() { + panic!( + "Failed to compile vertex shader: {}", + String::from_utf8(vert.stderr).unwrap() + ) + } + if !frag.status.success() { + panic!( + "Failed to compile fragment shader: {}", + String::from_utf8(frag.stderr).unwrap() + ) } } - -impl From<(String, ValidationError)> for BuildError { - fn from((s, e): (String, ValidationError)) -> Self { - BuildError::ValidateErrors(s, e) - } -} - -impl From<(String, spv::Error)> for BuildError { - fn from((s, e): (String, spv::Error)) -> Self { - BuildError::Spv(s, e) - } -} - -fn compile_shader(path: &Path, out_dir: &Path) -> Result<(), BuildError> { - let ext = path - .extension() - .and_then(|e| e.to_str()) - .map(str::to_string) - .ok_or_else(|| BuildError::UnsupportedExt(path.display().to_string()))?; - let stage = match ext.as_str() { - "vert" => ShaderStage::Vertex, - "frag" => ShaderStage::Fragment, - "comp" => ShaderStage::Compute, - _ => return Err(BuildError::UnsupportedExt(ext)), - }; - let src = fs::read_to_string(path)?; - - let module = glsl::Frontend::default() - .parse(&GlslOptions::from(stage), &src) - .map_err(|e| (ext.clone(), e))?; - let info = Validator::new(ValidationFlags::all(), Default::default()) - .validate(&module) - .map_err(|e| (ext.clone(), e.into_inner()))?; - let mut writer = spv::Writer::new(&spv::Options { - flags: WriterFlags::empty(), - ..Default::default() - }) - .map_err(|e| (ext.clone(), e))?; - let mut spirv = Vec::new(); - writer - .write(&module, &info, None, &None, &mut spirv) - .map_err(|e| (ext.clone(), e))?; - let out_path = out_dir.join(format!("{}.spv", ext)); - fs::write(&out_path, bytemuck::cast_slice(&spirv))?; - info!("Compiled {} → {}", path.display(), out_path.display()); - Ok(()) -} - -fn main() -> Result<(), BuildError> { - println!("cargo:rerun-if-changed=shaders"); - let out_dir = PathBuf::from(env::var("OUT_DIR")?); - for entry in fs::read_dir("shaders")? { - let path = entry?.path(); - if !path.is_file() { - continue; - } - if let Err(e) = compile_shader(&path, &out_dir) { - if matches!(e, BuildError::UnsupportedExt(_)) { - warn!("{}", e); - continue; - } - return Err(e); - } - } - Ok(()) -} diff --git a/default.nix b/default.nix index 02ab55a..1aa9adf 100644 --- a/default.nix +++ b/default.nix @@ -13,7 +13,7 @@ stdenv, targetPackages ? pkgs, }: let - version = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).package.version; + version = (builtins.fromTOML (builtins.readFile ./engine/Cargo.toml)).package.version; src = nix-gitignore.gitignoreSource [] ./.; in rustPlatform.buildRustPackage rec { @@ -61,7 +61,7 @@ rustPlatform.buildRustPackage rec { --set LD_LIBRARY_PATH ${lib.makeLibraryPath buildInputs} '' + lib.optionalString stdenv.targetPlatform.isWindows '' mkdir -p $out/bin - cp ${pkgs.vulkan-loader}/bin/vulkan-1.dll $out/bin/ + cp ${targetPackages.vulkan-loader}/bin/vulkan-1.dll $out/bin/ ''; doCheck = false; @@ -72,4 +72,4 @@ rustPlatform.buildRustPackage rec { platforms = lib.platforms.all; mainProgram = "zenyx"; }; -} +} \ No newline at end of file diff --git a/flake.nix b/flake.nix index f6f029f..21466a2 100644 --- a/flake.nix +++ b/flake.nix @@ -31,7 +31,7 @@ (import rust-overlay) ]; }; - + nativeBuildInputs = with pkgs; [ vulkan-tools vulkan-tools-lunarg @@ -41,7 +41,6 @@ cargo-cross cargo-xwin cargo-wizard - cargo-zigbuild wine64 pkg-config ]; @@ -61,7 +60,7 @@ packages = { inherit (pkgs) zenyx; default = pkgs.zenyx; - windows = let + windows = let pkgsCross = import nixpkgs { system = "x86_64-linux"; crossSystem = nixpkgs.lib.systems.examples.mingwW64; @@ -74,14 +73,8 @@ nativeBuildInputs = with pkgs; [ (rust-bin.stable.latest.default.override { extensions = ["rust-src" "cargo" "rustfmt" "clippy"]; - targets = [ - "x86_64-pc-windows-msvc" - "x86_64-unknown-linux-gnu" - "x86_64-apple-darwin" - "aarch64-pc-windows-msvc" - "aarch64-unknown-linux-gnu" - "aarch64-apple-darwin" - ]; + targets = [ "x86_64-pc-windows-msvc" "x86_64-unknown-linux-gnu" ]; + }) pkg-config ] ++ nativeBuildInputs; diff --git a/src/collections/sparse_set.rs b/src/collections/sparse_set.rs index 5e0ec84..72c7381 100644 --- a/src/collections/sparse_set.rs +++ b/src/collections/sparse_set.rs @@ -236,7 +236,10 @@ mod tests { assert_eq!(sparse_set.remove(SPARSE_PAGESIZE + 2).unwrap(), 3); assert_eq!(sparse_set.sparse[1].as_ref().unwrap().1, 2); - assert_eq!(sparse_set.keys(), [10, 11, 12, SPARSE_PAGESIZE, SPARSE_PAGESIZE + 1]); + assert_eq!( + sparse_set.keys(), + [10, 11, 12, SPARSE_PAGESIZE, SPARSE_PAGESIZE + 1] + ); assert_eq!(sparse_set.values(), [1, 2, 2, 1, 2]); assert_eq!(sparse_set.remove(SPARSE_PAGESIZE + 1).unwrap(), 2); @@ -249,25 +252,44 @@ mod tests { assert_eq!(sparse_set.keys(), [10, 11, 12]); assert_eq!(sparse_set.values(), [1, 2, 2]); - sparse_set.insert(SPARSE_PAGESIZE, 1); sparse_set.insert(SPARSE_PAGESIZE + 1, 2); sparse_set.insert(SPARSE_PAGESIZE + 2, 3); assert_eq!(sparse_set.remove(10).unwrap(), 1); assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 2); - // swap-remove - assert_eq!(sparse_set.keys(), [SPARSE_PAGESIZE + 2, 11, 12, SPARSE_PAGESIZE, SPARSE_PAGESIZE + 1]); + // swap-remove + assert_eq!( + sparse_set.keys(), + [ + SPARSE_PAGESIZE + 2, + 11, + 12, + SPARSE_PAGESIZE, + SPARSE_PAGESIZE + 1 + ] + ); assert_eq!(sparse_set.values(), [3, 2, 2, 1, 2]); assert_eq!(sparse_set.remove(11).unwrap(), 2); assert_eq!(sparse_set.sparse[0].as_ref().unwrap().1, 1); - assert_eq!(sparse_set.keys(), [SPARSE_PAGESIZE + 2, SPARSE_PAGESIZE + 1, 12, SPARSE_PAGESIZE]); + assert_eq!( + sparse_set.keys(), + [ + SPARSE_PAGESIZE + 2, + SPARSE_PAGESIZE + 1, + 12, + SPARSE_PAGESIZE + ] + ); assert_eq!(sparse_set.values(), [3, 2, 2, 1]); assert_eq!(sparse_set.remove(12).unwrap(), 2); assert!(sparse_set.sparse[0].is_none()); - assert_eq!(sparse_set.keys(), [SPARSE_PAGESIZE + 2, SPARSE_PAGESIZE + 1, SPARSE_PAGESIZE]); + assert_eq!( + sparse_set.keys(), + [SPARSE_PAGESIZE + 2, SPARSE_PAGESIZE + 1, SPARSE_PAGESIZE] + ); assert_eq!(sparse_set.values(), [3, 2, 1]); } } diff --git a/src/main.rs b/src/main.rs index 0105e37..2764eed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -141,6 +141,9 @@ struct WgpuState { instance: wgpu::Instance, } +static _ICON: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/Badge.png")); +static _PUMPKIN: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/Pumpkin.obj")); + impl WgpuState { fn new() -> Self { let backends = Backends::PRIMARY; diff --git a/subcrates/telemetry/Cargo.toml b/subcrates/telemetry/Cargo.toml new file mode 100644 index 0000000..7a483ae --- /dev/null +++ b/subcrates/telemetry/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "telemetry" +version = "0.1.0" +edition = "2024" + +[dependencies] +ash = "0.38.0" +chrono = { version = "0.4.40", features = ["serde"] } +derive_more = { version = "2.0.1", features = ["add", "add_assign", "as_ref", "deref_mut", "from", "from_str", "full", "into", "mul", "mul_assign", "not", "sum", "try_from", "try_into", "try_unwrap", "unwrap"] } +detect-desktop-environment = "1.2.0" +hidapi = "2.6.3" +humansize = "2.1.3" +metal = { version = "0.32.0", optional = true } +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.140" +strum = "0.27.1" +strum_macros = "0.27.1" +sys-locale = "0.3.2" +sysinfo = { version = "0.34.2", features = ["serde"] } +thiserror = "2.0.12" +timeago = "0.4.2" +versions = { version = "7.0.0", features = ["serde"] } +wgpu = "25.0.0" +winit = "0.30.9" + +[features] +metal = ["dep:metal"] diff --git a/subcrates/telemetry/build.rs b/subcrates/telemetry/build.rs new file mode 100644 index 0000000..d012c62 --- /dev/null +++ b/subcrates/telemetry/build.rs @@ -0,0 +1,21 @@ +use std::{env, fs::File, io::Write, process::Command}; + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let mut f = File::create(format!("{}/built.rs", out_dir)).unwrap(); + + let commit_hash = Command::new("git") + .args(["rev-parse", "HEAD"]) + .output() + .ok() + .and_then(|o| String::from_utf8(o.stdout).ok()) + .unwrap_or_else(|| "unknown".into()); + + writeln!(f, "#[allow(dead_code)]").unwrap(); + writeln!( + f, + "pub const GIT_COMMIT_HASH: &str = \"{}\";", + commit_hash.trim() + ) + .unwrap(); +} diff --git a/subcrates/telemetry/src/lib.rs b/subcrates/telemetry/src/lib.rs new file mode 100644 index 0000000..4b1b333 --- /dev/null +++ b/subcrates/telemetry/src/lib.rs @@ -0,0 +1,70 @@ +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +#[macro_use] +mod modules; +pub use crate::modules::{cpu, devices, external, gpu, memory, meta, network, os, storage, uptime}; +use thiserror::Error; + +#[derive(Debug, Serialize, Deserialize)] +pub struct TelemetryInfo { + telemetry: AllInfo, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct AllInfo { + gpu: gpu::GPUInfo, + cpu: Vec, + memory: memory::MemoryInfo, + os: os::OSInfo, + storage: Vec, + network: network::NetworkInfo, + external: external::ExternalInfo, + devices: Vec, + meta: meta::MetaInfo, + uptime: uptime::UptimeInfo, +} + +#[derive(Debug, Error)] +pub enum TelemetryError { + // #[error("Failed to get GPU information")] + // GPUError(#[from] gpu::GPUError), + #[error("Failed to get CPU information")] + CPUError(#[from] cpu::CPUError), + #[error("Failed to get OS information")] + OSError(#[from] os::OSError), + #[error("Failed to get storage information")] + StorageError(#[from] storage::StorageError), + // #[error("Failed to get external information")] + // ExternalError(#[from] external::ExternalError), + #[error("Failed to get devices information")] + DevicesError(#[from] devices::DevicesError), + #[error("Failed to get meta information")] + MetaError(#[from] meta::MetaError), + #[error("Failed to get uptime information")] + UptimeError(#[from] uptime::UptimeError), + #[error("Failed to build JSON for TelemetryInfo")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_struct() -> Result { + Ok(TelemetryInfo { + telemetry: AllInfo { + gpu: gpu::get_struct(), + cpu: cpu::get_struct()?, + memory: memory::get_struct(), + os: os::get_struct()?, + storage: storage::get_list()?, + network: network::get_struct(), + external: external::get_struct(), + devices: devices::get_struct()?, + meta: meta::get_struct()?, + uptime: uptime::get_struct()?, + }, + }) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_struct()?)) +} diff --git a/subcrates/telemetry/src/main.rs b/subcrates/telemetry/src/main.rs new file mode 100644 index 0000000..37405d5 --- /dev/null +++ b/subcrates/telemetry/src/main.rs @@ -0,0 +1,13 @@ +use serde_json; + +fn main() { + //println!("{:#?}", telemetry::get_struct()); + //println!("{:#?}", telemetry::os::get_json()); + //telemetry::os::get_json(); + + match telemetry::get_struct() { + //Ok(telemetry) => println!("{:#?}", serde_json::from_value(telemetry)), + Ok(telemetry) => println!("{:#?}", telemetry), + Err(e) => eprintln!("Error: {}", e), + } +} diff --git a/subcrates/telemetry/src/modules/cpu.rs b/subcrates/telemetry/src/modules/cpu.rs new file mode 100644 index 0000000..7548feb --- /dev/null +++ b/subcrates/telemetry/src/modules/cpu.rs @@ -0,0 +1,67 @@ +use crate::modules::{FmtCores, FmtThreads}; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use std::collections::HashMap; +use sysinfo::{CpuRefreshKind, RefreshKind, System}; +use thiserror::Error; + +#[derive(Debug, Serialize, Deserialize)] +pub struct CPUInfo { + vendor: String, + brand: String, + total_system_cores: FmtCores, + threads: FmtThreads, + architecture: String, + byte_order: String, +} + +#[derive(Debug, Error)] +pub enum CPUError { + #[error("No CPU information available")] + NoCpusFound, + #[error("Failed to build JSON for Vec")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_struct() -> Result, CPUError> { + let mut system = + System::new_with_specifics(RefreshKind::nothing().with_cpu(CpuRefreshKind::everything())); + system.refresh_cpu_all(); + + let mut processor_map: HashMap = HashMap::new(); + + for cpu in system.cpus() { + let brand = cpu.brand().trim().to_string(); + let entry = processor_map + .entry(brand.clone()) + .or_insert_with(|| CPUInfo { + vendor: cpu.vendor_id().trim().to_string(), + brand: brand.clone(), + total_system_cores: System::physical_core_count() + .map(|cores| cores.into()) + .unwrap_or_else(|| 0.into()), + threads: 0.into(), + architecture: System::cpu_arch().trim().to_string(), + byte_order: if cfg!(target_endian = "little") { + String::from("little-endian") + } else { + String::from("big-endian") + }, + }); + + entry.threads += 1.into(); + } + + let cpus: Vec<_> = processor_map.into_values().collect(); + if cpus.is_empty() { + return Err(CPUError::NoCpusFound); + } + + Ok(cpus) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_struct()?)) +} diff --git a/subcrates/telemetry/src/modules/devices.rs b/subcrates/telemetry/src/modules/devices.rs new file mode 100644 index 0000000..6a74d2f --- /dev/null +++ b/subcrates/telemetry/src/modules/devices.rs @@ -0,0 +1,59 @@ +use super::UNKNOWN; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use thiserror::Error; +extern crate hidapi; +use hidapi::{HidApi, HidError}; +use std::collections::HashMap; + +#[derive(Debug, Serialize, Deserialize)] +pub struct DeviceInfo { + manufacturer: String, + products: Vec, +} + +#[derive(Debug, Error)] +pub enum DevicesError { + #[error("Failed to initialize HID API: {0}")] + HidApiInitError(#[from] HidError), + #[error("Failed to build JSON for Vec")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_struct() -> Result, DevicesError> { + let api = HidApi::new()?; + let mut grouped: HashMap> = HashMap::new(); + + for device in api.device_list() { + let manufacturer = device + .manufacturer_string() + .unwrap_or(UNKNOWN) + .to_ascii_lowercase(); + let product = device.product_string().unwrap_or(UNKNOWN).to_string(); + + if !manufacturer.trim().is_empty() && !product.trim().is_empty() { + grouped.entry(manufacturer).or_default().push(product) + } + } + + let mut sorted_devices: Vec<_> = grouped.into_iter().collect(); + sorted_devices.sort_by(|a, b| a.0.cmp(&b.0)); + + Ok(sorted_devices + .into_iter() + .map(|(manufacturer, mut products)| { + products.sort(); // optional: sort product names + products.dedup(); // remove duplicates + DeviceInfo { + manufacturer, + products, + } + }) + .collect()) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_struct()?)) +} diff --git a/subcrates/telemetry/src/modules/external.rs b/subcrates/telemetry/src/modules/external.rs new file mode 100644 index 0000000..a89e9d5 --- /dev/null +++ b/subcrates/telemetry/src/modules/external.rs @@ -0,0 +1,63 @@ +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use std::{cmp::Ordering::Equal, collections::HashMap}; +use sysinfo::{System, Users}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct SoftwareInfo { + name: String, + count: usize, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ExternalInfo { + softwares: Vec, +} + +#[allow(dead_code)] +pub fn get_struct() -> ExternalInfo { + let mut system = System::new_all(); + system.refresh_all(); + + let users = &Users::new_with_refreshed_list(); + let mut grouped_processes: HashMap> = HashMap::new(); + + for process in system.processes().values() { + let name = process.name().to_str().unwrap().to_string(); + let user_id = process.user_id(); + let is_user_owned = user_id.is_some_and(|uid| { + users + .list() + .iter() + .any(|u| u.id() == uid && u.name() != "root") + }); + + if is_user_owned && !name.trim().is_empty() && !name.starts_with('[') { + grouped_processes + .entry(name) + .or_default() + .push(process.pid().as_u32() as i32); + } + } + + let mut softwares = Vec::new(); + let mut grouped_vec: Vec<_> = grouped_processes.into_iter().collect(); + grouped_vec.sort_by(|a, b| match b.1.len().cmp(&a.1.len()) { + Equal => a.0.to_lowercase().cmp(&b.0.to_lowercase()), + other => other, + }); + + for (name, pids) in grouped_vec { + softwares.push(SoftwareInfo { + name, + count: pids.len(), + }); + } + + ExternalInfo { softwares } +} + +#[allow(dead_code)] +pub fn get_json() -> Value { + json!(get_struct()) +} diff --git a/subcrates/telemetry/src/modules/formatted/architecture.rs b/subcrates/telemetry/src/modules/formatted/architecture.rs new file mode 100644 index 0000000..fad7499 --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/architecture.rs @@ -0,0 +1,69 @@ +use serde::{Serialize, Serializer, Deserialize, Deserializer, de::Error as DeError}; +use std::{ + fmt::{Debug, Display, Formatter, Result as FmtResult}, + ops::Deref, +}; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize)] +pub enum TargetPointerWidth { + W32Bit, + W64Bit, +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct FmtOSArchitecture(pub TargetPointerWidth); + +impl FmtOSArchitecture { + pub const W32_BIT: Self = FmtOSArchitecture(TargetPointerWidth::W32Bit); + pub const W64_BIT: Self = FmtOSArchitecture(TargetPointerWidth::W64Bit); +} + +impl Display for FmtOSArchitecture { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + write!( + f, + "{}", + match self.0 { + TargetPointerWidth::W32Bit => "32 Bit", + TargetPointerWidth::W64Bit => "64 Bit", + } + ) + } +} + +impl Debug for FmtOSArchitecture { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + Display::fmt(self, f) + } +} + +impl Serialize for FmtOSArchitecture { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for FmtOSArchitecture { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + match s.as_str() { + "32 Bit" => Ok(FmtOSArchitecture(TargetPointerWidth::W32Bit)), + "64 Bit" => Ok(FmtOSArchitecture(TargetPointerWidth::W64Bit)), + _ => Err(DeError::custom(format!("Invalid architecture: {}", s))), + } + } +} + +impl Deref for FmtOSArchitecture { + type Target = TargetPointerWidth; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/subcrates/telemetry/src/modules/formatted/date_time.rs b/subcrates/telemetry/src/modules/formatted/date_time.rs new file mode 100644 index 0000000..efd8bbe --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/date_time.rs @@ -0,0 +1,144 @@ +use chrono::{DateTime, Local, TimeZone, Utc}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use std::{ + fmt::{Debug, Display, Formatter, Result as FMTResult}, + ops::Deref, +}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct DateTimeInfo { + date: String, + time: String, +} + +#[derive(Clone)] +pub struct FmtDateTime(pub DateTime); + +impl Display for FmtDateTime +where + Tz: TimeZone, + Tz::Offset: std::fmt::Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> FMTResult { + write!( + f, + "{:#?}", + DateTimeInfo { + date: self.0.format("%Y-%m-%d").to_string(), + time: self.0.format("%H:%M:%S").to_string() + } + ) + } +} + +impl Debug for FmtDateTime +where + Tz::Offset: std::fmt::Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> FMTResult { + Display::fmt(self, f) + } +} + +impl Serialize for FmtDateTime +where + DateTime: Display, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de, Tz> Deserialize<'de> for FmtDateTime +where + Tz: TimeZone, + DateTime: ToString + std::str::FromStr, + as std::str::FromStr>::Err: std::fmt::Display, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // 1. Pull a String out of the deserializer + let s = String::deserialize(deserializer)?; + // 2. Parse it, mapping any parse-error into a Serde error + as std::str::FromStr>::from_str(&s) // explicit, no ambiguity + .map(FmtDateTime) + .map_err(serde::de::Error::custom) + } +} + +impl Deref for FmtDateTime { + type Target = DateTime; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl Eq for FmtDateTime where DateTime: Eq {} +impl PartialEq for FmtDateTime +where + DateTime: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl PartialOrd for FmtDateTime +where + DateTime: PartialOrd, +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for FmtDateTime +where + DateTime: Ord, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl From> for FmtDateTime { + fn from(dt: FmtDateTime) -> Self { + FmtDateTime(dt.0.with_timezone(&Local)) + } +} + +impl From> for FmtDateTime { + fn from(dt: FmtDateTime) -> Self { + FmtDateTime(dt.0.with_timezone(&Utc)) + } +} + +#[allow(dead_code)] +pub trait IntoDateTime { + fn into_utc(self) -> FmtDateTime; + fn into_local(self) -> FmtDateTime; +} + +impl IntoDateTime for FmtDateTime { + fn into_utc(self) -> FmtDateTime { + FmtDateTime(self.0.with_timezone(&Utc)) + } + fn into_local(self) -> FmtDateTime { + self + } +} + +impl IntoDateTime for FmtDateTime { + fn into_local(self) -> FmtDateTime { + FmtDateTime(self.0.with_timezone(&Local)) + } + fn into_utc(self) -> FmtDateTime { + self + } +} diff --git a/subcrates/telemetry/src/modules/formatted/desktop_environment.rs b/subcrates/telemetry/src/modules/formatted/desktop_environment.rs new file mode 100644 index 0000000..5876441 --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/desktop_environment.rs @@ -0,0 +1,44 @@ +use std::str::FromStr; + +use serde::{Serialize, Deserialize}; +use detect_desktop_environment::DesktopEnvironment; +use strum_macros::EnumString; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumString)] +#[strum(serialize_all = "PascalCase", ascii_case_insensitive)] +#[non_exhaustive] +pub enum FmtDE { + Cinnamon, + Cosmic, + CosmicEpoch, + Dde, + Ede, + Endless, + Enlightenment, + Gnome, + Hyprland, + Kde, + Lxde, + Lxqt, + MacOs, + Mate, + Old, + Pantheon, + Razor, + Rox, + Sway, + Tde, + Unity, + Windows, + Xfce, +} + +impl FmtDE { + pub fn detect() -> Option { + DesktopEnvironment::detect().and_then(|inner_de| { + let s = format!("{:?}", inner_de); + + FmtDE::from_str(&s).ok() + }) + } +} \ No newline at end of file diff --git a/subcrates/telemetry/src/modules/formatted/mod.rs b/subcrates/telemetry/src/modules/formatted/mod.rs new file mode 100644 index 0000000..3eeb56b --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/mod.rs @@ -0,0 +1,7 @@ +pub mod architecture; +pub mod date_time; +pub mod desktop_environment; +pub mod offset_time; +pub mod relative_time; +pub mod version; +pub mod numbers; \ No newline at end of file diff --git a/subcrates/telemetry/src/modules/formatted/numbers.rs b/subcrates/telemetry/src/modules/formatted/numbers.rs new file mode 100644 index 0000000..7948537 --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/numbers.rs @@ -0,0 +1,54 @@ +use derive_more::{ + Add, AddAssign, Deref, Div, DivAssign, From, Mul, MulAssign, Sub, SubAssign, +}; +use serde::{Serialize, Deserialize}; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; + +enum DisplayKind { + Plural(&'static str, &'static str), + HumanBytes, +} + +macro_rules! define_fmt_wrapper { + ($name:ident, $ty:ty, $display_kind:expr) => { + #[derive( + Copy, Clone, PartialEq, Eq, PartialOrd, Ord, + Add, Sub, Mul, Div, + AddAssign, SubAssign, MulAssign, DivAssign, + From, Deref, Serialize, Deserialize + )] + pub struct $name(pub $ty); + + impl $name { + #[allow(dead_code)] + pub fn new(value: $ty) -> Self { + Self(value) + } + } + + impl Display for $name { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + match $display_kind { + DisplayKind::Plural(singular, plural) => { + let label = if self.0 == 1 { singular } else { plural }; + write!(f, "{} {}", self.0, label) + }, + DisplayKind::HumanBytes => { + use humansize::{format_size, DECIMAL}; + write!(f, "{}", format_size(self.0, DECIMAL)) + }, + } + } + } + + impl Debug for $name { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + Display::fmt(self, f) + } + } + }; +} + +define_fmt_wrapper!(FmtThreads, u16, DisplayKind::Plural("Thread", "Threads")); +define_fmt_wrapper!(FmtCores, usize, DisplayKind::Plural("Core", "Cores")); +define_fmt_wrapper!(FmtBytes, u64, DisplayKind::HumanBytes); \ No newline at end of file diff --git a/subcrates/telemetry/src/modules/formatted/offset_time.rs b/subcrates/telemetry/src/modules/formatted/offset_time.rs new file mode 100644 index 0000000..37e4fab --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/offset_time.rs @@ -0,0 +1,66 @@ +use chrono::{DateTime, Local, Offset}; +use derive_more::{Deref, Display, From}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use std::{ + cmp::Ordering, + fmt::{Debug, Display, Formatter, Result as FmtResult}, +}; + +#[derive(Copy, Clone, From, Deref, Display)] +#[display("UTC {}", "_0.offset()")] +pub struct FmtOffsetTime(pub DateTime); + +impl Debug for FmtOffsetTime { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + Display::fmt(self, f) + } +} + +impl Serialize for FmtOffsetTime { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for FmtOffsetTime { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Deserialize the input as a string + let s = String::deserialize(deserializer)?; + + // Attempt to parse the string into a DateTime + match DateTime::parse_from_rfc3339(&s) { + Ok(dt) => Ok(FmtOffsetTime(dt.with_timezone(&Local))), + Err(e) => Err(serde::de::Error::custom(format!( + "Failed to parse DateTime: {}", + e + ))), + } + } +} + +impl Eq for FmtOffsetTime {} +impl PartialEq for FmtOffsetTime { + fn eq(&self, other: &Self) -> bool { + self.0.offset().fix() == other.0.offset().fix() + } +} + +impl PartialOrd for FmtOffsetTime { + fn partial_cmp(&self, other: &Self) -> Option { + Some( + self.0.offset().fix().local_minus_utc().cmp(&other.0.offset().fix().local_minus_utc()), + ) + } +} + +impl Ord for FmtOffsetTime { + fn cmp(&self, other: &Self) -> Ordering { + self.0.offset().fix().local_minus_utc().cmp(&other.0.offset().fix().local_minus_utc()) + } +} diff --git a/subcrates/telemetry/src/modules/formatted/relative_time.rs b/subcrates/telemetry/src/modules/formatted/relative_time.rs new file mode 100644 index 0000000..2933fea --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/relative_time.rs @@ -0,0 +1,50 @@ +use derive_more::{From, Deref, with_trait::Display as Display}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use std::{ + fmt::{Debug, Formatter, Result as FmtResult}, + time::Duration, +}; + +#[derive( + Clone, + PartialEq, + Eq, + PartialOrd, + Ord, + From, + Deref, +)] +pub struct FmtRelativeTime(pub Duration); + +impl Display for FmtRelativeTime { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let formatter = timeago::Formatter::new(); + + write!(f, "{}", formatter.convert(self.0)) + } +} + +impl Debug for FmtRelativeTime { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + Display::fmt(self, f) + } +} + +impl Serialize for FmtRelativeTime { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_u64(self.0.as_secs()) + } +} + +impl<'de> Deserialize<'de> for FmtRelativeTime { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let secs = u64::deserialize(deserializer)?; + Ok(FmtRelativeTime(Duration::from_secs(secs))) + } +} \ No newline at end of file diff --git a/subcrates/telemetry/src/modules/formatted/version.rs b/subcrates/telemetry/src/modules/formatted/version.rs new file mode 100644 index 0000000..b83d888 --- /dev/null +++ b/subcrates/telemetry/src/modules/formatted/version.rs @@ -0,0 +1,38 @@ +use derive_more::{Display, From, Deref, with_trait::Display as TDisplay}; +use serde::{Serialize, Serializer, Deserialize, Deserializer}; +use std::{ + fmt::{Debug, Formatter, Result as FmtResult}, + str::FromStr, +}; +use versions::Versioning; + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, From, Deref, Display)] +#[display("{_0}")] +pub struct FmtVersion(pub Versioning); + +impl Debug for FmtVersion { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + TDisplay::fmt(self, f) + } +} + +impl Serialize for FmtVersion { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'de> Deserialize<'de> for FmtVersion { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Versioning::from_str(&s) + .map(FmtVersion) + .map_err(serde::de::Error::custom) + } +} \ No newline at end of file diff --git a/subcrates/telemetry/src/modules/gpu/mod.rs b/subcrates/telemetry/src/modules/gpu/mod.rs new file mode 100644 index 0000000..f1206ad --- /dev/null +++ b/subcrates/telemetry/src/modules/gpu/mod.rs @@ -0,0 +1,131 @@ +use super::UNKNOWN; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use wgpu; +use winit::{ + application::ApplicationHandler, + event::WindowEvent, + event_loop::{ActiveEventLoop, EventLoop}, + window::WindowId, +}; + +mod vram; + +#[derive(Debug, Serialize, Deserialize)] +pub struct DriverInfo { + version: String, + name: String, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct AdapterInfo { + vendor: String, + model: String, + driver: DriverInfo, + vram: String, + display: DisplayInfo, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct GPUInfo { + supported_backends: Vec, + gpus: Vec, +} + +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct DisplayInfo { + resolution: String, + refresh_rate: String, +} + +impl ApplicationHandler for DisplayInfo { + fn resumed(&mut self, event_loop: &ActiveEventLoop) { + if let Some(monitor) = event_loop.primary_monitor() { + let size = monitor.size(); + let refresh_rate = monitor.refresh_rate_millihertz(); + + self.resolution = format!("{}x{}", size.width, size.height); + self.refresh_rate = if let Some(refresh) = refresh_rate { + format!("{} hz", refresh / 1000) + } else { + UNKNOWN.to_string() + } + } else { + self.resolution = UNKNOWN.to_string(); + self.refresh_rate = UNKNOWN.to_string(); + } + + event_loop.exit(); + } + + fn window_event( + &mut self, + _event_loop: &ActiveEventLoop, + _window_id: WindowId, + _event: WindowEvent, + ) { + } +} + +fn vendor_name(vendor: u32) -> &'static str { + match vendor { + 0x10DE => "NVIDIA", + 0x1002 => "AMD(Advanced Micro Devices), Inc.", + 0x8086 => "Intel(integrated electronics)", + 0x13B5 => "ARM(Advanced RISC Machines)", + 0x5143 => "Qualcomm(Quality Communications)", + 0x1010 => "Apple Inc.", + _ => UNKNOWN, + } +} + +#[allow(dead_code)] +pub fn get_struct() -> GPUInfo { + let mut gpu_data: Vec = Vec::new(); + let mut backends: Vec = Vec::new(); + let instance_descriptor = wgpu::InstanceDescriptor { + backends: wgpu::Backends::all(), + flags: wgpu::InstanceFlags::empty(), + backend_options: Default::default(), + }; + let instance = wgpu::Instance::new(&instance_descriptor); + let event_loop = EventLoop::new().unwrap(); + let mut app = DisplayInfo::default(); + + event_loop.run_app(&mut app).unwrap(); + + for adapter in instance.enumerate_adapters(wgpu::Backends::all()) { + let info = adapter.get_info(); + + if !backends.contains(&info.backend.to_string()) { + backends.push(info.backend.to_string()); + } + if info.driver.is_empty() || info.driver_info.is_empty() { + continue; + } + + gpu_data.push(AdapterInfo { + vendor: vendor_name(info.vendor).to_string(), + model: info.name, + driver: DriverInfo { + version: info.driver_info, + name: info.driver, + }, + vram: vram::get(info.vendor, info.device), + display: DisplayInfo { + resolution: app.resolution.to_string(), + refresh_rate: app.refresh_rate.to_string(), + }, + }); + } + + GPUInfo { + supported_backends: backends, + gpus: gpu_data, + } +} + +#[allow(dead_code)] +pub fn get_json() -> Value { + json!(get_struct()) +} diff --git a/subcrates/telemetry/src/modules/gpu/vram.rs b/subcrates/telemetry/src/modules/gpu/vram.rs new file mode 100644 index 0000000..3044104 --- /dev/null +++ b/subcrates/telemetry/src/modules/gpu/vram.rs @@ -0,0 +1,67 @@ +use super::super::UNKNOWN; +use ash::vk::{API_VERSION_1_2, ApplicationInfo, InstanceCreateInfo, MemoryHeapFlags}; +use humansize::{DECIMAL, make_format}; + +#[cfg(not(target_os = "macos"))] +pub fn get_metal() -> u64 { + 0 +} + +#[cfg(target_os = "macos")] +pub fn get_metal() -> u64 { + use metal::Device as MetalDevice; + + let device = MetalDevice::system_default().expect("No Metal-compatible GPU found"); + device.recommended_max_working_set_size() +} + +pub fn get_vulkan(device_id: u32) -> u64 { + let entry = unsafe { ash::Entry::load().unwrap() }; + let app_info = ApplicationInfo { + p_application_name: std::ptr::null(), + application_version: 0, + p_engine_name: std::ptr::null(), + engine_version: 0, + api_version: API_VERSION_1_2, + ..Default::default() + }; + + let create_info = InstanceCreateInfo { + p_application_info: &app_info, + ..Default::default() + }; + + let instance = unsafe { entry.create_instance(&create_info, None).unwrap() }; + + let physical_devices = unsafe { instance.enumerate_physical_devices().unwrap() }; + let mut total_vram = 0; + + for device in physical_devices { + let memory_properties = unsafe { instance.get_physical_device_memory_properties(device) }; + let device_properties = unsafe { instance.get_physical_device_properties(device) }; + + if device_id != device_properties.device_id { + continue; + } + + for heap in memory_properties.memory_heaps { + if heap.flags.contains(MemoryHeapFlags::DEVICE_LOCAL) { + total_vram += heap.size; + } + } + + break; + } + + total_vram +} + +pub fn get(vendor: u32, device_id: u32) -> String { + let formatter = make_format(DECIMAL); + + match vendor { + 0x10DE | 0x1002 | 0x8086 | 0x5143 => formatter(get_vulkan(device_id)), + 0x1010 => formatter(get_metal()), + _ => UNKNOWN.to_string(), + } +} diff --git a/subcrates/telemetry/src/modules/memory.rs b/subcrates/telemetry/src/modules/memory.rs new file mode 100644 index 0000000..9888d3a --- /dev/null +++ b/subcrates/telemetry/src/modules/memory.rs @@ -0,0 +1,50 @@ +use crate::modules::FmtBytes; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use sysinfo::System; + +#[derive(Debug, Serialize, Deserialize)] +pub struct PhysicalInfo { + total: FmtBytes, + used: FmtBytes, + free: FmtBytes, + available: FmtBytes, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct VirtualInfo { + total: FmtBytes, + used: FmtBytes, + free: FmtBytes, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct MemoryInfo { + physical: PhysicalInfo, + virtual_swap: VirtualInfo, +} + +#[allow(dead_code)] +pub fn get_struct() -> MemoryInfo { + let mut system = System::new_all(); + system.refresh_memory(); + + MemoryInfo { + physical: PhysicalInfo { + total: FmtBytes(system.total_memory()), + used: FmtBytes(system.used_memory()), + free: FmtBytes(system.free_memory()), + available: FmtBytes(system.available_memory()), + }, + virtual_swap: VirtualInfo { + total: FmtBytes(system.total_swap()), + used: FmtBytes(system.used_swap()), + free: FmtBytes(system.free_swap()), + }, + } +} + +#[allow(dead_code)] +pub fn get_json() -> Value { + json!(get_struct()) +} diff --git a/subcrates/telemetry/src/modules/meta.rs b/subcrates/telemetry/src/modules/meta.rs new file mode 100644 index 0000000..60d94b3 --- /dev/null +++ b/subcrates/telemetry/src/modules/meta.rs @@ -0,0 +1,40 @@ +use crate::modules::FmtVersion; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use sys_locale::get_locale; +use thiserror::Error; +use versions::Versioning; + +include!(concat!(env!("OUT_DIR"), "/built.rs")); + +#[derive(Debug, Serialize, Deserialize)] +pub struct MetaInfo { + version: FmtVersion, + commit_hash: String, + locale: String, +} + +#[derive(Debug, Error)] +pub enum MetaError { + #[error("Invalid Semver version")] + InvalidVersion, + #[error("Failed to build JSON for MetaInfo")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_struct() -> Result { + let locale = get_locale().unwrap_or_else(|| String::from("en-US")); + let version = Versioning::new(env!("CARGO_PKG_VERSION")).ok_or(MetaError::InvalidVersion)?; + + Ok(MetaInfo { + version: FmtVersion(version), + commit_hash: GIT_COMMIT_HASH.to_string(), + locale, + }) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_struct()?)) +} diff --git a/subcrates/telemetry/src/modules/mod.rs b/subcrates/telemetry/src/modules/mod.rs new file mode 100644 index 0000000..d714f7b --- /dev/null +++ b/subcrates/telemetry/src/modules/mod.rs @@ -0,0 +1,26 @@ +pub mod cpu; +pub mod devices; +pub mod external; +pub mod formatted; +pub mod gpu; +pub mod memory; +pub mod meta; +pub mod network; +pub mod os; +pub mod storage; +pub mod uptime; + +#[allow(unused_imports)] +pub use formatted::{ + architecture::FmtOSArchitecture, + numbers::FmtBytes, + date_time::{FmtDateTime, IntoDateTime}, + desktop_environment::FmtDE, + offset_time::FmtOffsetTime, + relative_time::FmtRelativeTime, + version::FmtVersion, + numbers::FmtCores, + numbers::FmtThreads, +}; + +pub const UNKNOWN: &str = "Unknown"; diff --git a/subcrates/telemetry/src/modules/network.rs b/subcrates/telemetry/src/modules/network.rs new file mode 100644 index 0000000..02155d9 --- /dev/null +++ b/subcrates/telemetry/src/modules/network.rs @@ -0,0 +1,21 @@ +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use sysinfo::Networks; + +#[derive(Debug, Serialize, Deserialize)] +pub struct NetworkInfo { + adapters: Vec, +} + +#[allow(dead_code)] +pub fn get_struct() -> NetworkInfo { + let networks = Networks::new_with_refreshed_list(); + let adapters = networks.iter().map(|(name, _)| name.to_string()).collect(); + + NetworkInfo { adapters } +} + +#[allow(dead_code)] +pub fn get_json() -> Value { + json!(get_struct()) +} diff --git a/subcrates/telemetry/src/modules/os.rs b/subcrates/telemetry/src/modules/os.rs new file mode 100644 index 0000000..8a121a7 --- /dev/null +++ b/subcrates/telemetry/src/modules/os.rs @@ -0,0 +1,59 @@ +use super::UNKNOWN; +use crate::modules::{FmtDE, FmtOSArchitecture}; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +use sysinfo::System; +use thiserror::Error; + +#[derive(Debug, Serialize, Deserialize)] +pub struct OSInfo { + name: String, + edition: String, + version: String, + architecture: FmtOSArchitecture, + kernel: Option, + desktop_environment: Option, +} + +#[derive(Debug, Error)] +pub enum OSError { + #[error("Unsupported pointer width: 16 bit systems are not supported")] + UnsupportedPointerWidth, + #[error("Failed to build JSON for OSInfo")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_struct() -> Result { + let architecture = match std::mem::size_of::() { + 8 => Ok(FmtOSArchitecture::W64_BIT), + 4 => Ok(FmtOSArchitecture::W32_BIT), + _ => Err(OSError::UnsupportedPointerWidth), + }?; + + let kernel = if cfg!(target_os = "linux") || cfg!(target_os = "macos") { + Some(System::kernel_long_version()) + } else { + None + }; + + let desktop_environment = if cfg!(target_os = "linux") { + FmtDE::detect() + } else { + None + }; + + Ok(OSInfo { + name: System::name().unwrap_or(UNKNOWN.to_string()), + edition: System::long_os_version().unwrap_or(UNKNOWN.to_string()), + version: System::os_version().unwrap_or(UNKNOWN.to_string()), + architecture, + kernel, + desktop_environment, + }) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_struct()?)) +} diff --git a/subcrates/telemetry/src/modules/storage.rs b/subcrates/telemetry/src/modules/storage.rs new file mode 100644 index 0000000..625e611 --- /dev/null +++ b/subcrates/telemetry/src/modules/storage.rs @@ -0,0 +1,49 @@ +use crate::modules::FmtBytes; +use serde::{Serialize, Deserialize}; +use serde_json::{Value, json}; +pub use sysinfo::DiskKind; +use sysinfo::Disks; +use thiserror::Error; + +#[derive(Debug, Serialize, Deserialize)] +pub struct StorageInfo { + name: String, + mount_point: String, + disk_kind: DiskKind, + space_left: FmtBytes, + total: FmtBytes, +} + +#[derive(Debug, Error)] +pub enum StorageError { + #[error("No storage drives found")] + NoDisksFound, + #[error("Failed to build JSON for Vec")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_list() -> Result, StorageError> { + let disks = Disks::new_with_refreshed_list(); + let disk_list = disks.list(); + + if disk_list.is_empty() { + return Err(StorageError::NoDisksFound); + } + + Ok(disk_list + .iter() + .map(|disk| StorageInfo { + name: disk.name().to_string_lossy().into_owned(), + mount_point: disk.mount_point().to_string_lossy().replace('\\', ""), + disk_kind: disk.kind(), + space_left: FmtBytes(disk.available_space()), + total: FmtBytes(disk.total_space()), + }) + .collect()) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_list()?)) +} diff --git a/subcrates/telemetry/src/modules/uptime.rs b/subcrates/telemetry/src/modules/uptime.rs new file mode 100644 index 0000000..c6bed58 --- /dev/null +++ b/subcrates/telemetry/src/modules/uptime.rs @@ -0,0 +1,71 @@ +use crate::modules::{FmtDateTime, FmtOffsetTime, FmtRelativeTime}; +use chrono::{DateTime, Local, Utc, TimeZone}; +use serde::{Serialize, Serializer, Deserialize}; +use serde_json::{Value, json}; +use std::{ + time::Duration as StdDuration, + fmt::Display, +}; +use sysinfo::System; +use thiserror::Error; + +fn serialize_datetime(date: &DateTime, serializer: S) -> Result +where + S: Serializer, + Tz::Offset: Display, + Tz: TimeZone, +{ + let formatted = date.format("%+").to_string(); // Format as RFC 3339 + serializer.serialize_str(&formatted) +} + +#[derive(Debug, Serialize, Deserialize)] +struct DateInfo { + #[serde(serialize_with = "serialize_datetime")] + time_offset: FmtOffsetTime, + #[serde(serialize_with = "serialize_datetime")] + local_date_time: FmtDateTime, + #[serde(serialize_with = "serialize_datetime")] + utc_date_time: FmtDateTime, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct UptimeInfo { + boot: DateInfo, + now: DateInfo, + relative: FmtRelativeTime, +} + +#[derive(Debug, Error)] +pub enum UptimeError { + #[error("Invalid or out of range timestamp: check seconds < 8_220_000_000_000")] + InvalidTimestamp, + #[error("Failed to build JSON for UptimeInfo")] + JsonError(#[from] serde_json::Error), +} + +#[allow(dead_code)] +pub fn get_struct() -> Result { + let boot_time_utc = DateTime::::from_timestamp(System::boot_time() as i64, 0) + .ok_or(UptimeError::InvalidTimestamp)?; + let boot_time_local: DateTime = boot_time_utc.with_timezone(&Local); + let relative_time = + StdDuration::from_secs((Local::now() - boot_time_local).num_seconds() as u64); + + let make_info = |utc_dt: DateTime| DateInfo { + time_offset: FmtOffsetTime(Local::now()), + local_date_time: FmtDateTime(utc_dt.with_timezone(&Local)), + utc_date_time: FmtDateTime(utc_dt), + }; + + Ok(UptimeInfo { + boot: make_info(boot_time_utc), + now: make_info(Utc::now()), + relative: FmtRelativeTime(relative_time), + }) +} + +#[allow(dead_code)] +pub fn get_json() -> Result { + Ok(json!(get_struct()?)) +} diff --git a/subcrates/zlog/src/config.rs b/subcrates/zlog/src/config.rs index dc50fbe..b540573 100644 --- a/subcrates/zlog/src/config.rs +++ b/subcrates/zlog/src/config.rs @@ -74,7 +74,7 @@ impl LoggerConfig { self.log_json_show_message = i; self } - + pub fn log_json_show_additional_fields(mut self, i: bool) -> Self { self.log_json_show_additional_fields = i; self @@ -96,7 +96,7 @@ impl Default for LoggerConfig { log_json_show_timestamp: false, log_json_show_level: false, log_json_show_message: false, - log_json_show_additional_fields: false + log_json_show_additional_fields: false, } } } diff --git a/subcrates/zlog/src/lib.rs b/subcrates/zlog/src/lib.rs index e6b64a4..0399099 100644 --- a/subcrates/zlog/src/lib.rs +++ b/subcrates/zlog/src/lib.rs @@ -113,7 +113,7 @@ where level, message, #[cfg(feature = "json")] - additional_fields + additional_fields, }); if let LogEvent::Log(ref entry) = log_entry { @@ -212,13 +212,7 @@ impl Logger { for msg in rx { match msg { LogEvent::Log(mut entry) => { - println!( - "{}", - format_entry( - &mut entry, - &config_clone - ) - ); + println!("{}", format_entry(&mut entry, &config_clone)); } LogEvent::Shutdown => break, } @@ -298,12 +292,12 @@ fn format_entry(entry: &mut LogEntry, log_config: &LoggerConfig) -> String { if log_config.log_use_json { return format_entry_json(entry, log_config); } - + if log_config.log_to_stdout || log_config.log_to_file { return format_entry_string(entry, log_config); } else { return String::new(); - } + } } fn format_entry_string(entry: &LogEntry, log_config: &LoggerConfig) -> String { @@ -327,7 +321,10 @@ fn format_entry_json(entry: &mut LogEntry, log_config: &LoggerConfig) -> String let mut json_object = serde_json::Map::new(); if log_config.log_json_show_timestamp { - json_object.insert("timestamp".to_string(), Value::String(DateTime::::from(entry.timestamp).to_rfc3339())); + json_object.insert( + "timestamp".to_string(), + Value::String(DateTime::::from(entry.timestamp).to_rfc3339()), + ); } if log_config.log_json_show_level { @@ -335,7 +332,10 @@ fn format_entry_json(entry: &mut LogEntry, log_config: &LoggerConfig) -> String } if log_config.log_json_show_message { - json_object.insert("message".to_string(), Value::String(entry.message.to_string())); + json_object.insert( + "message".to_string(), + Value::String(entry.message.to_string()), + ); } if log_config.log_json_show_additional_fields { @@ -343,4 +343,4 @@ fn format_entry_json(entry: &mut LogEntry, log_config: &LoggerConfig) -> String } serde_json::to_string(&json_object).unwrap() -} \ No newline at end of file +} diff --git a/subcrates/zlog/src/tests.rs b/subcrates/zlog/src/tests.rs index 13c90ab..930b909 100644 --- a/subcrates/zlog/src/tests.rs +++ b/subcrates/zlog/src/tests.rs @@ -1,7 +1,7 @@ use pretty_assertions::assert_eq; -use tracing::Level; +use serde::{Deserialize, Serialize}; use serde_json::Map; -use serde::{Serialize, Deserialize}; +use tracing::Level; use super::*; @@ -126,9 +126,15 @@ fn test_logger_sequential_consistency_json() { for log in logger.get_logs(LogQuery::All) { let mut json_object = serde_json::Map::new(); - json_object.insert("timestamp".to_string(), Value::String(DateTime::::from(log.timestamp).to_rfc3339())); + json_object.insert( + "timestamp".to_string(), + Value::String(DateTime::::from(log.timestamp).to_rfc3339()), + ); json_object.insert("level".to_string(), Value::String(log.level.to_string())); - json_object.insert("message".to_string(), Value::String(log.message.to_string())); + json_object.insert( + "message".to_string(), + Value::String(log.message.to_string()), + ); log_json.push(json_object); } @@ -136,4 +142,4 @@ fn test_logger_sequential_consistency_json() { for log in log_json { serde_json::to_string(&log).unwrap(); } -} \ No newline at end of file +}