From d90d4bd1715b8966cf13bff66aba7f189179eba8 Mon Sep 17 00:00:00 2001 From: nicksinas Date: Fri, 2 Oct 2026 16:30:06 -0500 Subject: [PATCH 1/3] copper-rs-pose: add a Copper human pose reference A Copper (copper-rs) task graph in Rust: USB camera through GStreamer, YOLOv8n-pose on the CPU with Candle, results served to a Rerun viewer on the laptop (rerun --connect, port 9876). Based on copper-rs examples/cu_human_pose (release/1.2), with the changes a device needs: - Rerun gRPC server on the device (256 MB history) in place of a local viewer - Model weights downloaded at build time (pinned commit + sha256) and installed in the extension, in place of hf-hub at runtime - Copper log in /var/lib/copper-rs-pose (StateDirectory), 256 MB slabs, no raw frames in the log - Exit non-zero on a run error so systemd restarts the service - consolemon TUI over `ssh -t`; logmon only under systemd - udev link /dev/copper-camera for the USB camera Builds with only `avocado install` and `avocado build` on 2026/next. Copper crates are pinned to =1.2.1 and built with --ignore-rust-version (SDK rust 1.94.1, Copper declares 1.95). Cargo output and cache go in $AVOCADO_BUILD_DIR, because the project file share is too slow for this build. Tested: build-check passes on raspberrypi5; jetson-orin-nano builds. imx8mp-evk compiles, but the runtime image fails in stone validate (feed bootfiles have no rootfs .verity placeholder, not this reference). Not yet tested on hardware. The YOLOv8 weights are AGPL-3.0 (Ultralytics). They are downloaded by the build and are not in this repository. --- copper-rs-pose/.gitignore | 5 + copper-rs-pose/README.md | 28 + copper-rs-pose/app/Cargo.lock | 7896 +++++++++++++++++ copper-rs-pose/app/Cargo.toml | 35 + copper-rs-pose/app/build.rs | 3 + copper-rs-pose/app/copperconfig.ron | 84 + copper-rs-pose/app/src/image.rs | 64 + copper-rs-pose/app/src/main.rs | 57 + copper-rs-pose/app/src/payloads.rs | 113 + copper-rs-pose/app/src/tasks/gst_to_image.rs | 188 + copper-rs-pose/app/src/tasks/mod.rs | 7 + copper-rs-pose/app/src/tasks/rerun_viz.rs | 232 + copper-rs-pose/app/src/tasks/yolo_pose.rs | 131 + copper-rs-pose/app/src/yolo/mod.rs | 7 + copper-rs-pose/app/src/yolo/model.rs | 683 ++ copper-rs-pose/app/src/yolo/postprocess.rs | 220 + copper-rs-pose/app/src/yolo/preprocess.rs | 143 + copper-rs-pose/avocado.yaml | 117 + copper-rs-pose/copper-compile.sh | 65 + copper-rs-pose/copper-install.sh | 30 + copper-rs-pose/getting_started.md | 220 + copper-rs-pose/icon.png | Bin 0 -> 30685 bytes .../lib/systemd/system/copper-rs-pose.service | 26 + .../lib/udev/rules.d/70-copper-camera.rules | 4 + 24 files changed, 10358 insertions(+) create mode 100644 copper-rs-pose/.gitignore create mode 100644 copper-rs-pose/README.md create mode 100644 copper-rs-pose/app/Cargo.lock create mode 100644 copper-rs-pose/app/Cargo.toml create mode 100644 copper-rs-pose/app/build.rs create mode 100644 copper-rs-pose/app/copperconfig.ron create mode 100644 copper-rs-pose/app/src/image.rs create mode 100644 copper-rs-pose/app/src/main.rs create mode 100644 copper-rs-pose/app/src/payloads.rs create mode 100644 copper-rs-pose/app/src/tasks/gst_to_image.rs create mode 100644 copper-rs-pose/app/src/tasks/mod.rs create mode 100644 copper-rs-pose/app/src/tasks/rerun_viz.rs create mode 100644 copper-rs-pose/app/src/tasks/yolo_pose.rs create mode 100644 copper-rs-pose/app/src/yolo/mod.rs create mode 100644 copper-rs-pose/app/src/yolo/model.rs create mode 100644 copper-rs-pose/app/src/yolo/postprocess.rs create mode 100644 copper-rs-pose/app/src/yolo/preprocess.rs create mode 100644 copper-rs-pose/avocado.yaml create mode 100755 copper-rs-pose/copper-compile.sh create mode 100755 copper-rs-pose/copper-install.sh create mode 100644 copper-rs-pose/getting_started.md create mode 100644 copper-rs-pose/icon.png create mode 100644 copper-rs-pose/overlay/usr/lib/systemd/system/copper-rs-pose.service create mode 100644 copper-rs-pose/overlay/usr/lib/udev/rules.d/70-copper-camera.rules diff --git a/copper-rs-pose/.gitignore b/copper-rs-pose/.gitignore new file mode 100644 index 0000000..e99256f --- /dev/null +++ b/copper-rs-pose/.gitignore @@ -0,0 +1,5 @@ +.avocado/ +.avocado-state +.DS_Store +app/target/ +app/.cargo/ diff --git a/copper-rs-pose/README.md b/copper-rs-pose/README.md new file mode 100644 index 0000000..a670649 --- /dev/null +++ b/copper-rs-pose/README.md @@ -0,0 +1,28 @@ +--- +language: Rust +targets: + - raspberrypi5 + - imx8mp-evk + - jetson-orin-nano +topics: + - robotics + - vision + - ai + - camera + - gstreamer + - pose-estimation + - cross-compilation +icon: icon.png +--- + +# Copper Human Pose + +A [Copper](https://github.com/copper-project/copper-rs) robotics task graph in Rust that reads a USB camera, finds human poses with YOLOv8n-pose on the CPU, and serves the results to a [Rerun](https://rerun.io) viewer on your laptop. It is based on the upstream `cu_human_pose` example. + +- Cross-compile a Copper app (a task graph in `copperconfig.ron`, made into code at build time) into one binary +- Camera input through GStreamer, inference with Candle, no Python and no GPU +- Watch the live camera image and the skeletons from your laptop with `rerun --connect` +- Write the Copper log to `/var/lib` on a read-only root filesystem +- See the live task graph in the Copper TUI over SSH + +The YOLOv8 pose weights are from Ultralytics and use the AGPL-3.0 license. The build downloads them, and they are not in this repository. For a product, get a license from Ultralytics or use your own model. diff --git a/copper-rs-pose/app/Cargo.lock b/copper-rs-pose/app/Cargo.lock new file mode 100644 index 0000000..774034a --- /dev/null +++ b/copper-rs-pose/app/Cargo.lock @@ -0,0 +1,7896 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "const-random", + "getrandom 0.3.4", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi-to-tui" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42366bb9d958f042bf58f0a85e1b2d091997c1257ca49bddd7e4827aadc65fd" +dependencies = [ + "nom 8.0.0", + "ratatui-core", + "smallvec", + "thiserror 2.0.21", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" +dependencies = [ + "serde", +] + +[[package]] +name = "arrow" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cfdd0833e32a9874d2b55089333ad310c0be208aafa277385ce2461dec90be3" +dependencies = [ + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-ipc", + "arrow-json", + "arrow-ord", + "arrow-row", + "arrow-schema", + "arrow-select", + "arrow-string", +] + +[[package]] +name = "arrow-arith" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a41203398f0eaa6f7ec8e62c0da742a21abf282c148fc157f6c35c90e29981a" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "num-traits", +] + +[[package]] +name = "arrow-array" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae33dad492b7df00a217563a7b0ef2874df68a0deea1b1a3acf628152f7f7a69" +dependencies = [ + "ahash", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "half", + "hashbrown 0.17.1", + "num-complex", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-buffer" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9552f96391c005e6ab449fa941420935e7e062489b12b8b1b08879b2163f5b5" +dependencies = [ + "bytes", + "half", + "num-bigint", + "num-traits", +] + +[[package]] +name = "arrow-cast" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8a327c9649f30d8406995f27642b68df354713cca3baaaf100f076f18d5f34" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-ord", + "arrow-schema", + "arrow-select", + "atoi", + "base64 0.22.1", + "chrono", + "half", + "lexical-core", + "num-traits", + "ryu", +] + +[[package]] +name = "arrow-data" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b24852db04738907e06c04ea61e42fe7fda962a34513022dc0d0e754fb7976b" +dependencies = [ + "arrow-buffer", + "arrow-schema", + "half", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrow-ipc" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29a908a11fcfb3fb2f6730f4ac15e367bc644e419155e96238f68cf3adde572b" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "flatbuffers", +] + +[[package]] +name = "arrow-json" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a96aed3931c076adee39ec2a40d8219fc7f09e79bcdaca1df16272993e1e14" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-ord", + "arrow-schema", + "arrow-select", + "chrono", + "half", + "indexmap", + "itoa", + "lexical-core", + "memchr", + "num-traits", + "ryu", + "serde_core", + "serde_json", + "simdutf8", +] + +[[package]] +name = "arrow-ord" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63a083ec750f5c043f02946b4baf05fcdbb55f4560a3277055caca5cc99f3eb0" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", +] + +[[package]] +name = "arrow-row" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514ba0ef0d4c5896202dae736251ce415abb43a950bed570fb7981b8716c0e4c" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "half", +] + +[[package]] +name = "arrow-schema" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ca356ad6425cecb6eb7b28e4f659f1ee7880fbb1a16127de7dd62901efee9e" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "arrow-select" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58da39eb3d8350ad4a549e5c2bc49284dac554016c69829310350f1731b0aad" +dependencies = [ + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "num-traits", +] + +[[package]] +name = "arrow-string" +version = "58.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6789b388467525e3271326b6b4915666ecfdf5142aef09779445c954b67543c" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "memchr", + "num-traits", + "regex", + "regex-syntax", +] + +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + +[[package]] +name = "async-channel" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "async-trait" +version = "0.1.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "atomic_refcell" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21e4227379beff4205943696e6c3e0cd809bacdf3f0edd6e3dd153e2269571a4" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "az" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide 0.8.9", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec 0.6.3", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bit-vec" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" +dependencies = [ + "bytemuck", + "serde_core", +] + +[[package]] +name = "bitstream-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] + +[[package]] +name = "bstr" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +dependencies = [ + "memchr", + "regex-automata", + "serde_core", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" + +[[package]] +name = "bytemuck" +version = "1.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "bytestring" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86566c496f2f47d9b8147a4c8b02ffdb69c919fe0c2b2e7195d22cbba0e635c9" +dependencies = [ + "bytes", +] + +[[package]] +name = "camino" +version = "1.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" +dependencies = [ + "serde_core", +] + +[[package]] +name = "candle-core" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ecb245093b0f791b89d3420c3df9c6d49c60ab63ba54db896bf8a3baf486706" +dependencies = [ + "byteorder", + "candle-kernels", + "candle-ug", + "cudarc 0.19.10", + "float8", + "gemm 0.19.0", + "half", + "libc", + "libm", + "memmap2", + "num-traits", + "num_cpus", + "rand 0.9.5", + "rand_distr", + "rayon", + "safetensors 0.8.0", + "thiserror 2.0.21", + "tokenizers", + "yoke 0.8.3", + "zerocopy", + "zip", +] + +[[package]] +name = "candle-kernels" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67450168a281bbb195a14cc85cf164c7a12023a54a03409a3324f476346e0789" +dependencies = [ + "cudaforge", +] + +[[package]] +name = "candle-nn" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaa10b6ccc365b33210ce404fbf45e60d3e0bdac1004463cf1052e6ee1c1739a" +dependencies = [ + "candle-core", + "half", + "libc", + "num-traits", + "rayon", + "safetensors 0.8.0", + "serde", + "thiserror 2.0.21", +] + +[[package]] +name = "candle-ug" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "257411c33abf7d898a31ac20d80813dfe96ff09e23a73039e22ab293aea9b871" +dependencies = [ + "ug", + "ug-cuda", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.28", + "serde", + "serde_json", + "thiserror 2.0.21", +] + +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + +[[package]] +name = "cc" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba9e9ec16c447027685b1f897b720e18e9a8afd00bd7332c483537e38086c9f" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chrono" +version = "0.4.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +dependencies = [ + "iana-time-zone", + "num-traits", + "windows-link", +] + +[[package]] +name = "chunked_transfer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" + +[[package]] +name = "circular-buffer" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662f6b21c6e889ee4e3f449e197c40f03603472fcd40c709093d386e3dca07cf" + +[[package]] +name = "clap" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_derive" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "clap_lex" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "clean-path" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aaa6b4b263a5d737e9bf6b7c09b72c41a5480aec4d7219af827f6564e950b6a5" + +[[package]] +name = "comfy-table" +version = "7.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958c5d6ecf1f214b4c2bbbbf6ab9523a864bd136dcf71a7e8904799acfe1ad47" +dependencies = [ + "crossterm", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "serde", + "static_assertions", +] + +[[package]] +name = "compact_str" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79fcda08c33bb58b97008b2cdada6622500e949e060f5913361763121abd2416" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "serde", + "static_assertions", + "zmij", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "console" +version = "0.16.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width", + "windows-sys 0.61.2", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "convert_case" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "affbf0190ed2caf063e3def54ff444b449371d55c58e513a95ab98eca50adb49" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "copper-rs-pose" +version = "0.1.0" +dependencies = [ + "candle-core", + "candle-nn", + "cu-bincode", + "cu-consolemon", + "cu-gstreamer", + "cu-logmon", + "cu-sensor-payloads", + "cu29", + "cu29-build", + "rerun", + "serde", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cortex-m" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "844b9697e922c99847eed515c6eb6d101e7ce62ff556fcaec243798291427ee8" +dependencies = [ + "bare-metal", + "bitfield", + "cortex-m-macros", + "critical-section", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "volatile-register", +] + +[[package]] +name = "cortex-m-macros" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1922be58519ad40368fc4ca595a2cefa51a7abf947be3b0c90586dc7dbd0e2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "cros-codecs" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f7441b4f31c17b6b6b7f57f6c202944aad11d0ab23739a9ff88d8d34dec621" +dependencies = [ + "log", +] + +[[package]] +name = "crossbeam" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e71406cd8807725f7ac2f999a4cdd32e98f829fdf65f528343cebf945e41df1e" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e8bd762f7479489c70ed6c768ddca99d7296857de437a68dcb2a94365b3fae" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + +[[package]] +name = "crossterm" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" +dependencies = [ + "bitflags 2.13.2", + "crossterm_winapi", + "derive_more", + "document-features", + "mio", + "parking_lot", + "rustix", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csscolorparser" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" +dependencies = [ + "lab", + "phf", +] + +[[package]] +name = "ctrlc" +version = "3.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +dependencies = [ + "dispatch2", + "nix 0.31.3", + "windows-sys 0.61.2", +] + +[[package]] +name = "cu-bincode" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c056e8c9d8cf3f467a1617daddacc4920d32b214ab371f98160033d6b9749138" +dependencies = [ + "cu-bincode-derive", + "serde", + "unty", +] + +[[package]] +name = "cu-bincode-derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02017dde7974608238c1bebbac86a36fdd7d7029400f76b0f400ee260e27ed14" +dependencies = [ + "virtue", +] + +[[package]] +name = "cu-consolemon" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "082bebd63dd421134c53bc78f846f873a813b07f2d68c73686d48bf1ac763dbf" +dependencies = [ + "cu-tuimon", + "cu29", + "libc", + "ratatui", +] + +[[package]] +name = "cu-gstreamer" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4633089e1f825a78db5dfdf996c4cf38b241effe102834cce3d3e084eb308939" +dependencies = [ + "cfg_aliases", + "circular-buffer", + "cu-bincode", + "cu29", + "cu29-build", + "gstreamer", + "gstreamer-app", + "serde", +] + +[[package]] +name = "cu-logmon" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf019a2cfc4fbd8b328e17df0da6b579f96727f51cf89dfe0d548989921b0fe9" +dependencies = [ + "cu29", + "cu29-build", + "cu29-log-runtime", + "spin", +] + +[[package]] +name = "cu-sensor-payloads" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac78c969fd103abe399f8e024ea0f010a93b550a3e6bca378edc8c71e4f61ad6" +dependencies = [ + "cu-bincode", + "cu29", + "cu29-clock", + "cu29-soa-derive", + "serde", +] + +[[package]] +name = "cu-tuimon" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aca3ac26481bf7ce5f769494a0020efb645283da8b01f0cf7a282d479611e15f" +dependencies = [ + "ansi-to-tui", + "cfg_aliases", + "compact_str 0.10.0", + "cu29", + "hostname", + "js-sys", + "ratatui", + "tui-widgets", + "wasm-bindgen", + "web-sys", + "web-time", +] + +[[package]] +name = "cu29" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46cda41925225eeb825c31982994e0ba430351b5f446e1a3de6d3f0d34bde2e7" +dependencies = [ + "ctrlc", + "cu-bincode", + "cu29-build", + "cu29-clock", + "cu29-derive", + "cu29-log", + "cu29-log-derive", + "cu29-log-runtime", + "cu29-reflect-derive", + "cu29-runtime", + "cu29-traits", + "cu29-unifiedlog", + "cu29-units", + "cu29-value", + "rayon", + "serde", + "serde_derive", + "spin", +] + +[[package]] +name = "cu29-build" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4bbd9f74d4ca9667eca1ca99ff3df7bea9b9351dcc23ecfcee9853c7ff26eed" + +[[package]] +name = "cu29-clock" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f14c65e169f80289439c560f744a2feac45a118f224be2874808c067e54366b4" +dependencies = [ + "cortex-m", + "cu-bincode", + "portable-atomic", + "serde", + "web-time", +] + +[[package]] +name = "cu29-derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "717ddf11ce4fdfc52f7d219313e969fe2efe66e86b2025a5591046c8230fc990" +dependencies = [ + "convert_case 0.11.0", + "cu29-build", + "cu29-runtime", + "cu29-traits", + "cu29-unifiedlog", + "cu29-units", + "itertools 0.15.0", + "proc-macro2", + "quote", + "syn 3.0.6", + "walkdir", +] + +[[package]] +name = "cu29-intern-strs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae73cc9ed873534afaa6ba58c48787501e131c9dde20d6f7036b0a3c1ccce071" +dependencies = [ + "anyhow", + "cu-bincode", + "fs2", +] + +[[package]] +name = "cu29-log" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a0addf11630073d05a8c78a3a1fbb2973c76681a8225b9bb51367190852def" +dependencies = [ + "cu-bincode", + "cu29-clock", + "cu29-traits", + "cu29-value", + "serde", + "smallvec", + "strfmt", +] + +[[package]] +name = "cu29-log-derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e367bb86993a6e7d40a4417db162008c66cb90295837622e6f04b743ebdcd36d" +dependencies = [ + "cu29-build", + "cu29-intern-strs", + "cu29-log", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "cu29-log-runtime" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "add78b48f58d4ab9d98433c55fbd5223d7920e846ba2b0e2566670d2da20ad8c" +dependencies = [ + "cu-bincode", + "cu29-build", + "cu29-clock", + "cu29-log", + "cu29-traits", + "log", + "smallvec", + "spin", + "strfmt", +] + +[[package]] +name = "cu29-reflect-derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9d6ac030ad1150f5685d907d098b84b70f47d26a82a739d69636c14f3fbf47" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "cu29-runtime" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139f6eb65e5e5a13104160da71b4a5c94316edb4873a379e91a73511e52532da" +dependencies = [ + "arrayvec", + "clap", + "compact_str 0.10.0", + "cu-bincode", + "cu29-build", + "cu29-clock", + "cu29-log", + "cu29-log-derive", + "cu29-log-runtime", + "cu29-reflect-derive", + "cu29-traits", + "cu29-unifiedlog", + "cu29-units", + "cu29-value", + "erased-serde", + "hashbrown 0.17.1", + "html-escape", + "layout-rs", + "libm", + "memmap2", + "object-pool", + "paste", + "petgraph", + "portable-atomic", + "rayon", + "ron", + "serde", + "serde_derive", + "serde_json", + "smallvec", + "spin", + "svg", + "tempfile", +] + +[[package]] +name = "cu29-soa-derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9db66437beff9f07354a39d35d1436827384abc41a47344dfa9a82aec407c814" +dependencies = [ + "quote", + "syn 3.0.6", +] + +[[package]] +name = "cu29-traits" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1507bd26748d90a6b756372012a7211af0ffcb8d48747436e1902debd3a6a752" +dependencies = [ + "compact_str 0.10.0", + "cu-bincode", + "cu29-clock", + "erased-serde", + "serde", + "spin", +] + +[[package]] +name = "cu29-unifiedlog" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3c0d82d5aceb023bf0307312fceaad3a1dfc90019e4f2e326405b160bd7e9d" +dependencies = [ + "cu-bincode", + "cu29-traits", + "memmap2", + "page_size", + "spin", +] + +[[package]] +name = "cu29-units" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e334dd2c75bbc58eb2892e0e2f5e8ae8d1485991fe422e40a65c2d01e62d150" +dependencies = [ + "cu-bincode", + "cu29-traits", + "serde", + "uom", +] + +[[package]] +name = "cu29-value" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77f762dbf59415c785f14258ec2f95a70696cf2300032c5cd147f27bbba2a82f" +dependencies = [ + "cu-bincode", + "cu29-clock", + "ordered-float 5.5.0", + "serde", +] + +[[package]] +name = "cudaforge" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d475ff95b9e4096878f47fe0ca5dbad0e23849a79fc225305ea06c2f25771cd" +dependencies = [ + "anyhow", + "fs2", + "glob", + "num_cpus", + "rayon", + "serde", + "serde_json", + "sha2", + "thiserror 2.0.21", + "walkdir", + "which", +] + +[[package]] +name = "cudarc" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf99ab37ee7072d64d906aa2dada9a3422f1d975cdf8c8055a573bc84897ed8" +dependencies = [ + "half", + "libloading 0.8.9", +] + +[[package]] +name = "cudarc" +version = "0.19.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7359bf1de037ddada72729c3acec9b040f3468400c6e9e740b01ba0cd2e89562" +dependencies = [ + "float8", + "half", + "libloading 0.9.0", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed17f5901b6630b993ca003def43f2f8ef4014fc13b047b57aad617ff32bc2ec" +dependencies = [ + "darling_core 0.24.1", + "darling_macro 0.24.1", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.119", +] + +[[package]] +name = "darling_core" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6837e2cf7485aaae18f86181d2f0e9a7ed297a025e220aeabf63fdebd3a2ddff" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 3.0.6", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "darling_macro" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" +dependencies = [ + "darling_core 0.24.1", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "dary_heap" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe" +dependencies = [ + "serde", +] + +[[package]] +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror 2.0.21", +] + +[[package]] +name = "deltae" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" + +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.119", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version 0.4.1", + "syn 2.0.119", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.13.2", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "dyn-stack" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4713e43e2886ba72b8271aa66c93d722116acf7a75555cce11dcde84388fe8" +dependencies = [ + "bytemuck", + "dyn-stack-macros", +] + +[[package]] +name = "dyn-stack-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d926b4d407d372f141f93bb444696142c29d32962ccbd3531117cf3aa0bfa9" + +[[package]] +name = "econtext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18aade80d5e09429040243ce1143ddc08a92d7a22820ac512610410a4dd5214f" + +[[package]] +name = "ehttp" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2f1b93eb2e039aaff63ce07cca59bd1dca02f2ce30075a17b619d2c42f56efc" +dependencies = [ + "async-channel", + "document-features", + "js-sys", + "serde", + "serde_json", + "ureq", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "emath" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd4ec073c9898516584d8c6cfdcee95b530b3d941cd5031ef4050aa36812308b" + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "esaxx-rs" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" + +[[package]] +name = "euclid" +version = "0.22.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" +dependencies = [ + "num-traits", +] + +[[package]] +name = "event-listener" +version = "5.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +dependencies = [ + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + +[[package]] +name = "fancy-regex" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +dependencies = [ + "bit-set", + "regex", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "filedescriptor" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +dependencies = [ + "libc", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" + +[[package]] +name = "finl_unicode" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80bb028c8b4148c9ee0cca68fcd9add6044e81d3619f48577ddf13a263d047a2" + +[[package]] +name = "fixed" +version = "1.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9af2cbf772fa6d1c11358f92ef554cb6b386201210bcf0e91fb7fba8a907fb40" +dependencies = [ + "az", + "bytemuck", + "half", + "serde", + "typenum", +] + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flatbuffers" +version = "25.12.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3" +dependencies = [ + "bitflags 2.13.2", + "rustc_version 0.4.1", +] + +[[package]] +name = "flate2" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e634e2e0ebac1ee034020da1ca582e17ffe4e0f5e985823721e168928136dcb" +dependencies = [ + "crc32fast", + "miniz_oxide 0.9.1", + "zlib-rs", +] + +[[package]] +name = "float8" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d1f04709a8ac06e8e8042875a3c466cc4832d3c1a18dbcb9dba3c6e83046bc" +dependencies = [ + "half", + "num-traits", + "rand 0.9.5", + "rand_distr", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "four-cc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "795cbfc56d419a7ce47ccbb7504dd9a5b7c484c083c356e797de08bd988d9629" + +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "futures" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" + +[[package]] +name = "futures-executor" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + +[[package]] +name = "futures-macro" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "futures-sink" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" + +[[package]] +name = "futures-task" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" + +[[package]] +name = "futures-util" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gemm" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab96b703d31950f1aeddded248bc95543c9efc7ac9c4a21fda8703a83ee35451" +dependencies = [ + "dyn-stack", + "gemm-c32 0.18.2", + "gemm-c64 0.18.2", + "gemm-common 0.18.2", + "gemm-f16 0.18.2", + "gemm-f32 0.18.2", + "gemm-f64 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa0673db364b12263d103b68337a68fbecc541d6f6b61ba72fe438654709eacb" +dependencies = [ + "dyn-stack", + "gemm-c32 0.19.0", + "gemm-c64 0.19.0", + "gemm-common 0.19.0", + "gemm-f16 0.19.0", + "gemm-f32 0.19.0", + "gemm-f64 0.19.0", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c32" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6db9fd9f40421d00eea9dd0770045a5603b8d684654816637732463f4073847" +dependencies = [ + "dyn-stack", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c32" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086936dbdcb99e37aad81d320f98f670e53c1e55a98bee70573e83f95beb128c" +dependencies = [ + "dyn-stack", + "gemm-common 0.19.0", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c64" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfcad8a3d35a43758330b635d02edad980c1e143dc2f21e6fd25f9e4eada8edf" +dependencies = [ + "dyn-stack", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c64" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c8aeeeec425959bda4d9827664029ba1501a90a0d1e6228e48bef741db3a3f" +dependencies = [ + "dyn-stack", + "gemm-common 0.19.0", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-common" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a352d4a69cbe938b9e2a9cb7a3a63b7e72f9349174a2752a558a8a563510d0f3" +dependencies = [ + "bytemuck", + "dyn-stack", + "half", + "libm", + "num-complex", + "num-traits", + "once_cell", + "paste", + "pulp 0.21.5", + "raw-cpuid", + "rayon", + "seq-macro", + "sysctl", +] + +[[package]] +name = "gemm-common" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88027625910cc9b1085aaaa1c4bc46bb3a36aad323452b33c25b5e4e7c8e2a3e" +dependencies = [ + "bytemuck", + "dyn-stack", + "half", + "libm", + "num-complex", + "num-traits", + "once_cell", + "paste", + "pulp 0.22.3", + "raw-cpuid", + "rayon", + "seq-macro", + "sysctl", +] + +[[package]] +name = "gemm-f16" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff95ae3259432f3c3410eaa919033cd03791d81cebd18018393dc147952e109" +dependencies = [ + "dyn-stack", + "gemm-common 0.18.2", + "gemm-f32 0.18.2", + "half", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "rayon", + "seq-macro", +] + +[[package]] +name = "gemm-f16" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3df7a55202e6cd6739d82ae3399c8e0c7e1402859b30e4cb780e61525d9486e" +dependencies = [ + "dyn-stack", + "gemm-common 0.19.0", + "gemm-f32 0.19.0", + "half", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "rayon", + "seq-macro", +] + +[[package]] +name = "gemm-f32" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc8d3d4385393304f407392f754cd2dc4b315d05063f62cf09f47b58de276864" +dependencies = [ + "dyn-stack", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-f32" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0b8c9da1fbec6e3e3ab2ce6bc259ef18eb5f6f0d3e4edf54b75f9fd41a81c" +dependencies = [ + "dyn-stack", + "gemm-common 0.19.0", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-f64" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b2a4f76ce4b8b16eadc11ccf2e083252d8237c1b589558a49b0183545015bd" +dependencies = [ + "dyn-stack", + "gemm-common 0.18.2", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-f64" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056131e8f2a521bfab322f804ccd652520c79700d81209e9d9275bbdecaadc6a" +dependencies = [ + "dyn-stack", + "gemm-common 0.19.0", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "gio-sys" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28739f914c15b87a9856000bed9cbd5b3a8afbca5e982d9a299e1601422cb5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "windows-sys 0.61.2", +] + +[[package]] +name = "glib" +version = "0.22.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4cf9e5bd8713f1990a92c422998826e0fb34824277b46bc59757373483c6694" +dependencies = [ + "bitflags 2.13.2", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "smallvec", +] + +[[package]] +name = "glib-macros" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9597c68fa7bdf4154a3079642cd21c4dccac0b0bdd2897d82861523bf91e7b9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "glib-sys" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b38907e67e40dec9b60f858bcada952598719cb512a13eb13d6cdcd16f8295" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "gobject-sys" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07595c9ba696bd9819cb6a8df39f08078f3dd679508fe052dd558492c2053834" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gstreamer" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4237e2066a25ecb7e54be6c066409e30615920265b9799b8d560ef8ac9857c6" +dependencies = [ + "cfg-if", + "futures-channel", + "futures-core", + "futures-util", + "glib", + "gstreamer-sys", + "itertools 0.15.0", + "kstring", + "libc", + "muldiv", + "num-integer", + "num-rational", + "option-operations", + "pastey", + "pin-project-lite", + "smallvec", + "thiserror 2.0.21", +] + +[[package]] +name = "gstreamer-app" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97f8ae9238c2352398dcc084de28df3f7099af216ac6c160b52318d23f25c010" +dependencies = [ + "futures-core", + "futures-sink", + "glib", + "gstreamer", + "gstreamer-app-sys", + "gstreamer-base", + "libc", +] + +[[package]] +name = "gstreamer-app-sys" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0798b8aef6694341d40bb81edc759f8979b896b59f9f0f45d8cfa3bb7bf2e743" +dependencies = [ + "glib-sys", + "gstreamer-base-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gstreamer-base" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cbd8f59586a369c40d4b0d2f3a61cf9e9287b3cf5503cdcd8e7c5faa99265e" +dependencies = [ + "atomic_refcell", + "cfg-if", + "glib", + "gstreamer", + "gstreamer-base-sys", + "libc", +] + +[[package]] +name = "gstreamer-base-sys" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b05f77bfd76b5afee6b29c27dae19eaf5018b5cf8d0d17520f3de44c6385c32" +dependencies = [ + "glib-sys", + "gobject-sys", + "gstreamer-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gstreamer-sys" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436d9532847489a8285d57b8c3670762c12a18f777fdc2ab159b52e0e6f521b9" +dependencies = [ + "cfg-if", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "h2" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h264-reader" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036a78b2620d92f0ec57690bc792b3bb87348632ee5225302ba2e66a48021c6c" +dependencies = [ + "bitstream-io", + "hex-slice", + "log", + "memchr", + "rfc6381-codec", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "bytemuck", + "cfg-if", + "crunchy", + "num-traits", + "rand 0.9.5", + "rand_distr", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-slice" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5491a308e0214554f07a81d8944abe45f552871c12e3c3c6e7e5d354039a6c4c" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "hostname" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" +dependencies = [ + "cfg-if", + "libc", + "windows-link", +] + +[[package]] +name = "html-escape" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9356095b4b41197bba32173600e1582792cda618f65d12f68e2e77d273413c5" + +[[package]] +name = "http" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke 0.8.3", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" + +[[package]] +name = "icu_properties" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" + +[[package]] +name = "icu_provider" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke 0.8.3", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "moxcms", + "num-traits", + "png", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "indent" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f1a0777d972970f204fdf8ef319f1f4f8459131636d7e3c96c5d59570d0fa6" + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "indicatif" +version = "0.18.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" +dependencies = [ + "console 0.16.6", + "portable-atomic", + "unicode-width", + "unit-prefix", + "web-time", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "instability" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3b5acc1e2fd9375041a388da33d1eb8aed5f7a8c0dd3543e3ea2805adfbe20" +dependencies = [ + "darling 0.24.1", + "indoc", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jiff" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "jiff-tzdb-platform", + "js-sys", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "jiff-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" +dependencies = [ + "defmt", + "log", +] + +[[package]] +name = "jiff-static" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jiff-tzdb" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bd39932ad231f10513df9ab62661fead8719872150b7ad02a2df79f4e141e" + +[[package]] +name = "jiff-tzdb-platform" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" +dependencies = [ + "jiff-tzdb", +] + +[[package]] +name = "js-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" +dependencies = [ + "cfg-if", + "futures-util", + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "10.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" +dependencies = [ + "base64 0.22.1", + "getrandom 0.2.17", + "js-sys", + "serde", + "serde_json", + "signature", + "zeroize", +] + +[[package]] +name = "kasuari" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" +dependencies = [ + "hashbrown 0.16.1", + "portable-atomic", + "thiserror 2.0.21", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + +[[package]] +name = "kstring" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a09b82a7f771ed02dc0dd9b27130a0fa5499fa15ed3027116c1e5e4e591bd9e" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lab" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" + +[[package]] +name = "layout-rs" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8b38bc67665e362eb770c6b6ae88b48d040d94a0a10c4904c37bc79d263b95" + +[[package]] +name = "lazy_static" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" + +[[package]] +name = "lexical-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" +dependencies = [ + "lexical-parse-integer", + "lexical-util", +] + +[[package]] +name = "lexical-parse-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "lexical-util" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" + +[[package]] +name = "lexical-write-float" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" +dependencies = [ + "lexical-util", + "lexical-write-integer", +] + +[[package]] +name = "lexical-write-integer" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" +dependencies = [ + "lexical-util", +] + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libloading" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754ca22de805bb5744484a5b151a9e1a8e837d5dc232c2d7d8c2e3492edc8b60" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libredox" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" +dependencies = [ + "libc", +] + +[[package]] +name = "line-clipping" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e752191d037c44ad111a8caa762921926658402f01cc1253f7bef2020ece4f5e" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", + "serde", +] + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "log-once" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d8a05e3879b317b1b6dbf353e5bba7062bedcc59815267bb23eaa0c576cebf0" +dependencies = [ + "log", +] + +[[package]] +name = "lru" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef9ac18847474e638e3702b76c65d4eb93428471a74778ef0f1be711717f89b5" +dependencies = [ + "hashbrown 0.17.1", +] + +[[package]] +name = "lz4_flex" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef0d4ed8669f8f8826eb00dc878084aa8f253506c4fd5e8f58f5bce72ddb97e" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "mac_address" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b367b50a9be9a5d3b5718c1da74e5d6b9c17647f89752ee2562a470cc3c4eb1a" +dependencies = [ + "nix 0.30.1", + "windows-sys 0.61.2", +] + +[[package]] +name = "macro_rules_attribute" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3ae8f6d608c795738406608304d30a2dfbdc8e58e44f7ba43236da5208ded3c" +dependencies = [ + "macro_rules_attribute-proc_macro", + "pastey", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc04a4c58212d57930a24bf47d3fa87485264a3a054e9c10e042eb373573ad3c" + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "matrixmultiply" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f607c237553f086e7043417a51df26b2eb899d3caff94e6a67592ff992fedc7" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", + "stable_deref_trait", +] + +[[package]] +name = "memmem" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "memory-stats" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c73f5c649995a115e1a0220b35e4df0a1294500477f97a91d0660fb5abeb574a" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess2" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1706dc14a2e140dec0a7a07109d9a3d5890b81e85bd6c60b906b249a77adf0ca" +dependencies = [ + "mime", + "phf", + "phf_shared", + "unicase", +] + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "monostate" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3341a273f6c9d5bef1908f17b7267bbab0e95c9bf69a0d4dcf8e9e1b2c76ef67" +dependencies = [ + "monostate-impl", + "serde", + "serde_core", +] + +[[package]] +name = "monostate-impl" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "mp4ra-rust" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdbc3d3867085d66ac6270482e66f3dd2c5a18451a3dc9ad7269e94844a536b7" +dependencies = [ + "four-cc", +] + +[[package]] +name = "mpeg4-audio-const" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a1fe2275b68991faded2c80aa4a33dba398b77d276038b8f50701a22e55918" + +[[package]] +name = "muldiv" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0" + +[[package]] +name = "natord" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "ndarray" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841" +dependencies = [ + "matrixmultiply", + "num-complex", + "num-integer", + "num-traits", + "portable-atomic", + "portable-atomic-util", + "rawpointer", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.13.2", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nix" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +dependencies = [ + "bitflags 2.13.2", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "nix" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +dependencies = [ + "bitflags 2.13.2", + "cfg-if", + "cfg_aliases", + "libc", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[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 = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", + "serde", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "bytemuck", + "num-traits", + "serde", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[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 2.0.119", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "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", + "serde", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "objc2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +dependencies = [ + "objc2-encode", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "objc2-encode" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "object-pool" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceffa2e6ccecd71e60a0f06b655df2c66acd1c0c892dafefc96fd49d65f71d53" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "onig" +version = "6.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2" +dependencies = [ + "bitflags 2.13.2", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e68317604e77e53b85896388e1a803c1d21b74c899ec9e5e1112db90735edd7" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "opentelemetry" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0142c63252a9e054e68a4c61a5778f7b14f576274d593f8ce883d191a099682" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror 2.0.21", + "tracing", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d658ba1faf63f7b9c492cfbe6e0ec365440a16132d3270c1065f7b33f1b638" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b59f80e1ac4d5ff7a2db8fb6c80badb7f0f3f858211fba08dd9aaec750894f9" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "portable-atomic", + "rand 0.9.5", + "thiserror 2.0.21", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "option-operations" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aca39cf52b03268400c16eeb9b56382ea3c3353409309b63f5c8f0b1faf42754" +dependencies = [ + "pastey", +] + +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + +[[package]] +name = "ordered-float" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c7c9e0d9b23589f26070720bac724174bfec1083e82f7854cdd0267518343c0" +dependencies = [ + "num-traits", +] + +[[package]] +name = "page_size" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "palette" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddeed8580d347d2abf3dcf06a5f0b3dc020258338526b277847cd4248a70fc64" +dependencies = [ + "approx", + "libm", + "palette_derive", + "palette_math", +] + +[[package]] +name = "palette_derive" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88537020289b719d81be994ccf1bbf4990f477e2f69ee52fe3e45f43a02e56be" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "palette_math" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e6eb142958d64335fb0e345c5b9ead2ecd6fc438c307e9d7d3c4fd428dbaf12" +dependencies = [ + "libm", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + +[[package]] +name = "peg" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aad070be5b63aa72103f2fcdd70a83adbd5e90112ce5b574171ff1c65501773" +dependencies = [ + "peg-macros", + "peg-runtime", +] + +[[package]] +name = "peg-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd8ef6825cae95355031ae26a99b616a2a21f22ba2de0197c43dfb05acbe7ee" +dependencies = [ + "peg-runtime", + "proc-macro2", + "quote", +] + +[[package]] +name = "peg-runtime" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7011d97b484a5ebdc4b1fdb3b12d5e4bbbea56e9d22b688f2e79e04b65a7d8a6" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pest" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pest_meta" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb" +dependencies = [ + "pest", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset 0.5.7", + "hashbrown 0.15.5", + "indexmap", + "serde", + "serde_derive", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.8", +] + +[[package]] +name = "phf_macros" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.119", + "unicase", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", + "unicase", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + +[[package]] +name = "ply-rs-bw" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe55bbee2b70d1c1e58d8340eda9a80c5ce11fb9b1bc10b5fc1575c490d38fa9" +dependencies = [ + "byteorder", + "indexmap", + "peg", +] + +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.13.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + +[[package]] +name = "poll-promise" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6a58fecbf9da8965bcdb20ce4fd29788d1acee68ddbb64f0ba1b81bccdb7df" +dependencies = [ + "document-features", + "static_assertions", +] + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528ac67416ff8646872a3c02cad9cc4ee5dc9f9540c9b10771855c95cb2e5ae1" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "prost-types" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f94967dc7688f3054c7fac87473ffae4cc4c3904800e2d9f5b857246d8963b0a" +dependencies = [ + "prost", +] + +[[package]] +name = "puffin" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b514d95a258be801fde8a1ff1c974f4a4841d9750f5d1d6690fc07a5ad4049" +dependencies = [ + "anyhow", + "byteorder", + "cfg-if", + "itertools 0.14.0", + "parking_lot", +] + +[[package]] +name = "pulp" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b86df24f0a7ddd5e4b95c94fc9ed8a98f1ca94d3b01bdce2824097e7835907" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "reborrow", + "version_check", +] + +[[package]] +name = "pulp" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "paste", + "pulp-wasm-simd-flag", + "raw-cpuid", + "reborrow", + "version_check", +] + +[[package]] +name = "pulp-wasm-simd-flag" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740" + +[[package]] +name = "pxfm" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" + +[[package]] +name = "quiver" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30fc53445d63835c1580064663c42973fb3c64ea5d19ed1a666a5fac5dc191e4" +dependencies = [ + "quiver_derive", + "quiver_types", +] + +[[package]] +name = "quiver_derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11c3bc8019d249c8926310ac15808d0b1d5af20b187c24eedbc8d1116fdcd3d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "quiver_types" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28ae5ccd523981092a925ce1bf414c4f61eebd19d62881f79d2639df602b0c9" +dependencies = [ + "arrow", + "half", + "thiserror 2.0.21", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rand" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e058c7de0b26af77780c769414d6257830bb240f3c38477dbc2c16e5f54d6d4c" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.5", +] + +[[package]] +name = "ratatui" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" +dependencies = [ + "instability", + "ratatui-core", + "ratatui-crossterm", + "ratatui-macros", + "ratatui-termina", + "ratatui-termwiz", + "ratatui-widgets", + "serde", +] + +[[package]] +name = "ratatui-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" +dependencies = [ + "bitflags 2.13.2", + "compact_str 0.9.1", + "critical-section", + "hashbrown 0.17.1", + "itertools 0.14.0", + "kasuari", + "lru", + "palette", + "serde", + "strum 0.28.0", + "thiserror 2.0.21", + "unicode-segmentation", + "unicode-truncate", + "unicode-width", +] + +[[package]] +name = "ratatui-crossterm" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" +dependencies = [ + "cfg-if", + "crossterm", + "instability", + "ratatui-core", +] + +[[package]] +name = "ratatui-macros" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" +dependencies = [ + "ratatui-core", + "ratatui-widgets", +] + +[[package]] +name = "ratatui-termina" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" +dependencies = [ + "instability", + "ratatui-core", + "termina", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" +dependencies = [ + "ratatui-core", + "termwiz", +] + +[[package]] +name = "ratatui-widgets" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" +dependencies = [ + "bitflags 2.13.2", + "hashbrown 0.17.1", + "indoc", + "instability", + "itertools 0.14.0", + "line-clipping", + "ratatui-core", + "serde", + "strum 0.28.0", + "time", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-cond" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f" +dependencies = [ + "either", + "itertools 0.14.0", + "rayon", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "re_analytics" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6828ec339cf5b73028fd5d2533d0d3981ce2c0974d996cbd52ab571d9aa0ff33" +dependencies = [ + "crossbeam", + "directories", + "ehttp", + "jiff", + "re_build_info", + "re_log", + "re_quota_channel", + "serde", + "serde_json", + "sha2", + "thiserror 2.0.21", + "url", + "uuid", + "web-sys", +] + +[[package]] +name = "re_arrow_util" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a218813e41cebd320502db168f073dbef82e54f465169b9d5db5a038b59cadce" +dependencies = [ + "anyhow", + "arrow", + "comfy-table", + "half", + "itertools 0.14.0", + "re_log", + "re_tracing", + "re_tuid", + "serde_json", + "thiserror 2.0.21", +] + +[[package]] +name = "re_auth" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1046391c5b135e6b5fef074bfd8d7b6f26ac6d60378d367237ebc6ddccd19ddb" +dependencies = [ + "async-trait", + "base64 0.22.1", + "directories", + "ehttp", + "getrandom 0.2.17", + "getrandom 0.3.4", + "hmac", + "http", + "jiff", + "js-sys", + "jsonwebtoken", + "parking_lot", + "rand 0.9.5", + "re_analytics", + "re_log", + "ring", + "saturating_cast", + "serde", + "serde_json", + "sha2", + "signature", + "thiserror 2.0.21", + "tiny_http", + "tokio", + "tonic", + "tower", + "url", + "uuid", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "re_backoff" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24045f1f64f8182843196f8e93198a894d758b853b24784dc5c988a9a57b2209" +dependencies = [ + "futures", + "getrandom 0.3.4", + "js-sys", + "rand 0.9.5", + "tokio", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "re_build_info" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0193e3c3f986f0dc6cdaac20b61ac0b653c0420724e1f4f0be12a949b60363" +dependencies = [ + "re_byte_size", + "serde", +] + +[[package]] +name = "re_build_tools" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea184cece718a96eafe5c8a037f4921249eddf25a088ba76c9386a3d07afb260" +dependencies = [ + "anyhow", + "cargo_metadata", + "glob", + "jiff", + "sha2", + "unindent", + "walkdir", +] + +[[package]] +name = "re_byte_size" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7a121584eb8bd6c233074a5e6c83e3851337514327d7b081f1105ec6161c03" +dependencies = [ + "arrow", + "half", + "parking_lot", + "re_byte_size_derive", + "smallvec", + "vec1", +] + +[[package]] +name = "re_byte_size_derive" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2badb0b23f623cf11835ad6ea8c7b2c49c113a8ce20cc3bdb5999a67c999b874" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "re_capabilities" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709b7059f3001816b4df13b32085bc065fc0b6239643b031bb5b4422328992af" +dependencies = [ + "document-features", + "re_log", + "static_assertions", +] + +[[package]] +name = "re_case" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e92115a7b0b8f5ebc9a9c20fc06e5020c0968a4b0d9d671e4841e4b6ec17f948" +dependencies = [ + "convert_case 0.11.0", +] + +[[package]] +name = "re_chunk" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3aaac97919d00db037490bf11fc2837398a1bcb108b3a74d3a169af30ae7e5" +dependencies = [ + "ahash", + "anyhow", + "arrow", + "bytemuck", + "crossbeam", + "document-features", + "half", + "itertools 0.14.0", + "nohash-hasher", + "rand 0.9.5", + "re_arrow_util", + "re_byte_size", + "re_error", + "re_format", + "re_log", + "re_log_types", + "re_quota_channel", + "re_sorbet", + "re_span", + "re_tracing", + "re_types_core", + "thiserror 2.0.21", +] + +[[package]] +name = "re_chunk_store" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a554d71dfce940b4edddc533f689f2c17aa2caf8a7bde05ee309b316c2b90d24" +dependencies = [ + "ahash", + "anyhow", + "arrow", + "document-features", + "indent", + "itertools 0.14.0", + "nohash-hasher", + "parking_lot", + "re_arrow_util", + "re_byte_size", + "re_chunk", + "re_format", + "re_log", + "re_log_encoding", + "re_log_types", + "re_sdk_types", + "re_sorbet", + "re_tracing", + "re_types_core", + "saturating_cast", + "thiserror 2.0.21", + "web-time", +] + +[[package]] +name = "re_entity_db" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e57d091006172928af1a02c0ee452d1f0acee058cd16ea151a336ac214bc7a4" +dependencies = [ + "ahash", + "arrow", + "document-features", + "emath", + "indexmap", + "itertools 0.14.0", + "nohash-hasher", + "poll-promise", + "re_arrow_util", + "re_byte_size", + "re_chunk", + "re_chunk_store", + "re_format", + "re_log", + "re_log_channel", + "re_log_encoding", + "re_log_types", + "re_mutex", + "re_query", + "re_sorbet", + "re_tracing", + "re_types_core", + "re_uri", + "serde", + "static_assertions", + "tap", + "thiserror 2.0.21", + "vec1", + "web-time", +] + +[[package]] +name = "re_error" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc10202b765d5043703720eaab232fbea38437c755a649942b0bf5974e4cddfb" + +[[package]] +name = "re_format" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9793ceb32d0943ea4fdbadb99e8cc3f74366a0b0c2339e7e2a0432b502c72a" +dependencies = [ + "half", + "itertools 0.14.0", + "num-traits", + "re_log", +] + +[[package]] +name = "re_grpc_client" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa13ca0cbfb38f5fd2cfba892e67cd3aa5d19b1594189559e869e9dde79b785d" +dependencies = [ + "async-stream", + "crossbeam", + "re_chunk", + "re_error", + "re_log", + "re_log_channel", + "re_log_encoding", + "re_log_types", + "re_protos", + "re_quota_channel", + "re_sorbet", + "re_tracing", + "re_uri", + "rerun-tonic-web-wasm-client", + "thiserror 2.0.21", + "tokio", + "tokio-stream", + "tonic", + "wasm-bindgen-futures", + "web-time", +] + +[[package]] +name = "re_grpc_headers" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5e5e962f593eb017c97458ec5c7c914dedb194def5b5c349e2b17774b3c327b" +dependencies = [ + "http", + "pin-project-lite", + "tonic", + "tower", +] + +[[package]] +name = "re_grpc_server" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14f8115ff45ccfedb3b4fab578e352f0f4fa249d7fb476ef53a6652c778c777" +dependencies = [ + "anyhow", + "async-stream", + "futures", + "itertools 0.14.0", + "parking_lot", + "re_byte_size", + "re_chunk", + "re_error", + "re_format", + "re_log", + "re_log_channel", + "re_log_encoding", + "re_log_types", + "re_memory", + "re_protos", + "re_quota_channel", + "re_sdk_types", + "re_sorbet", + "re_tracing", + "re_uri", + "tokio", + "tokio-stream", + "tokio-util", + "tonic", + "tonic-web", + "tower-http", + "wildmatch", +] + +[[package]] +name = "re_lenses" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cf67a83d90fe0d78408bbd5d97b6f87ee190aaf2b066b6ba035304edab8c880" +dependencies = [ + "arrow", + "re_lenses_core", + "re_log", + "re_sdk_types", +] + +[[package]] +name = "re_lenses_core" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50ebc7aad107ffc4fb5e405951d8866bdffa3bbfcab83b96f38378c1d256bf1e" +dependencies = [ + "ahash", + "arrow", + "itertools 0.14.0", + "nohash-hasher", + "re_arrow_util", + "re_byte_size", + "re_chunk", + "re_log", + "re_log_types", + "re_sdk_types", + "thiserror 2.0.21", + "vec1", +] + +[[package]] +name = "re_log" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e82e912948056f7211c436d354de745aa4a04269ef52f5d6760a8c0a098062d" +dependencies = [ + "crossbeam", + "log", + "log-once", + "parking_lot", + "tracing", + "tracing-log", + "tracing-subscriber", + "tracing-web", +] + +[[package]] +name = "re_log_channel" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d27a5bf2579dcabc38c531ae1be7785f918c0a350a73c7e7611766fae104647" +dependencies = [ + "camino", + "crossbeam", + "futures", + "parking_lot", + "re_byte_size", + "re_log_encoding", + "re_log_types", + "re_protos", + "re_quota_channel", + "re_tracing", + "re_uri", + "serde", + "thiserror 2.0.21", +] + +[[package]] +name = "re_log_encoding" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a5df35e1e32e783014827a362bf68fb97f9b122240ad731511207fb8fceec48" +dependencies = [ + "arrow", + "bytes", + "crossbeam", + "itertools 0.14.0", + "lz4_flex", + "parking_lot", + "re_arrow_util", + "re_build_info", + "re_byte_size", + "re_chunk", + "re_log", + "re_log_types", + "re_protos", + "re_quota_channel", + "re_sorbet", + "re_span", + "re_tracing", + "re_types_core", + "sha2", + "thiserror 2.0.21", + "tokio", + "tokio-stream", + "tracing", + "xxhash-rust", +] + +[[package]] +name = "re_log_types" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f34dd4de4c0f73d7977526d052c599569baf6785cbbb4296735d9094fe8de4" +dependencies = [ + "ahash", + "arrow", + "bytemuck", + "clean-path", + "document-features", + "fixed", + "half", + "itertools 0.14.0", + "jiff", + "natord", + "nohash-hasher", + "num-derive", + "num-traits", + "parking_lot", + "quiver", + "re_arrow_util", + "re_build_info", + "re_byte_size", + "re_format", + "re_log", + "re_string_interner", + "re_tracing", + "re_tuid", + "re_types_core", + "serde", + "static_assertions", + "thiserror 2.0.21", + "typenum", + "uuid", + "web-time", + "xxhash-rust", +] + +[[package]] +name = "re_memory" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b562dc9970318507f97da5ede2a1a1109b63396efecacb6edfaf4b23a764903" +dependencies = [ + "ahash", + "backtrace", + "crossbeam", + "itertools 0.14.0", + "memory-stats", + "nohash-hasher", + "parking_lot", + "re_format", + "re_log", + "re_quota_channel", + "re_tracing", + "saturating_cast", + "serde", + "smallvec", + "sysinfo", + "wasm-bindgen", + "web-time", +] + +[[package]] +name = "re_mp4" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63d71dca1bc07c053ed67ccfd0b52df652192a6541fbdf85cc3d46142e20d709" +dependencies = [ + "byteorder", + "bytes", + "num-rational", + "serde", + "serde_json", + "thiserror 2.0.21", +] + +[[package]] +name = "re_mutex" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0ae90ae886c4d8318f75e3f4fdee4ed4aa2d58e45ac9eb891c402b264e7019" +dependencies = [ + "cfg-if", + "parking_lot", + "re_byte_size", + "re_log", +] + +[[package]] +name = "re_protos" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4b9722ba8815a81f67adbc43b099fe3d116e5e501e24a7f56754ae7a151a5e" +dependencies = [ + "arrow", + "http", + "itertools 0.14.0", + "jiff", + "lz4_flex", + "opentelemetry", + "prost", + "prost-types", + "quiver", + "re_arrow_util", + "re_build_info", + "re_byte_size", + "re_chunk", + "re_grpc_headers", + "re_log_types", + "re_sorbet", + "re_tracing", + "re_tuid", + "re_types_core", + "serde", + "thiserror 2.0.21", + "tonic", + "tonic-prost", + "tower", + "tracing", + "url", +] + +[[package]] +name = "re_query" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4d3d0e524979ff673a09a79bfcf934c030348b0c0e1db8edf7a383720358027" +dependencies = [ + "ahash", + "anyhow", + "arrow", + "indent", + "itertools 0.14.0", + "nohash-hasher", + "parking_lot", + "paste", + "re_byte_size", + "re_chunk", + "re_chunk_store", + "re_error", + "re_format", + "re_log", + "re_log_types", + "re_tracing", + "re_types_core", + "seq-macro", + "thiserror 2.0.21", +] + +[[package]] +name = "re_quota_channel" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a59a27acd017a54a99147b03545aba671ad1db28f1e17e6edf694a0f9d9b87" +dependencies = [ + "crossbeam", + "parking_lot", + "re_byte_size", + "re_format", + "re_log", + "tokio", +] + +[[package]] +name = "re_redap_client" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0fbcd37c49a0b09a5908ac0fa05c2c2bddab7aadfe88e4b141924b8a7b50ff6" +dependencies = [ + "ahash", + "arrow", + "bitflags 2.13.2", + "ehttp", + "futures", + "http", + "http-body", + "itertools 0.14.0", + "jiff", + "opentelemetry", + "opentelemetry-proto", + "quiver", + "re_arrow_util", + "re_auth", + "re_backoff", + "re_byte_size", + "re_chunk", + "re_error", + "re_format", + "re_log", + "re_log_channel", + "re_log_encoding", + "re_log_types", + "re_protos", + "re_tracing", + "re_types_core", + "re_uri", + "rerun-tonic-web-wasm-client", + "serde", + "thiserror 2.0.21", + "tokio", + "tokio-stream", + "tonic", + "tonic-prost", + "tower", + "tracing", + "url", + "web-time", +] + +[[package]] +name = "re_rvl" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e653e7b497786499d64f452e3a766426eb8a67784e85329f9026979306a77973" +dependencies = [ + "byteorder", + "thiserror 2.0.21", +] + +[[package]] +name = "re_sdk" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e426edaa5b4aae7338893282b53e671afc02770601d054f4754bc42ec43ff29" +dependencies = [ + "ahash", + "const_format", + "crossbeam", + "document-features", + "itertools 0.14.0", + "libc", + "nohash-hasher", + "parking_lot", + "percent-encoding", + "re_build_info", + "re_build_tools", + "re_byte_size", + "re_chunk", + "re_grpc_client", + "re_grpc_server", + "re_lenses", + "re_lenses_core", + "re_log", + "re_log_channel", + "re_log_encoding", + "re_log_types", + "re_memory", + "re_quota_channel", + "re_sdk_types", + "re_sorbet", + "re_tracing", + "re_uri", + "thiserror 2.0.21", + "tokio", + "uuid", +] + +[[package]] +name = "re_sdk_types" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbecb95e90d133d4721715412f24b333895f56373fe0ebce99ecdf0aa0b9bc2" +dependencies = [ + "array-init", + "arrow", + "bytemuck", + "document-features", + "emath", + "half", + "infer", + "itertools 0.14.0", + "mime_guess2", + "ndarray", + "nohash-hasher", + "ply-rs-bw", + "re_byte_size", + "re_error", + "re_format", + "re_log", + "re_log_types", + "re_rvl", + "re_sorbet", + "re_tracing", + "re_types_core", + "serde", + "smallvec", + "thiserror 2.0.21", + "uuid", +] + +[[package]] +name = "re_sorbet" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3779c99433e8c50c8a6745100a6139625c2d25500005428ab09a87de07e73e6e" +dependencies = [ + "arrow", + "itertools 0.14.0", + "nohash-hasher", + "re_arrow_util", + "re_byte_size", + "re_log", + "re_log_types", + "re_tracing", + "re_tuid", + "re_types_core", + "semver 1.0.28", + "strum 0.26.3", + "thiserror 2.0.21", + "tracing", + "web-time", +] + +[[package]] +name = "re_span" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf08cd0e8927ac0827d165d13d20b4ca185f4e1674a480add117dcd351b3c8d9" +dependencies = [ + "num-traits", +] + +[[package]] +name = "re_string_interner" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d265632b061bad0098cb06444a7724646fb1b51caadb1805b80cd74bcea950d1" +dependencies = [ + "ahash", + "nohash-hasher", + "parking_lot", + "re_byte_size", + "serde", + "static_assertions", +] + +[[package]] +name = "re_tracing" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c5dbe275a6768c4ea0707d4bdad82475827c633e8519e384ab4c48a6142f149" +dependencies = [ + "parking_lot", + "puffin", +] + +[[package]] +name = "re_tuid" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef911ec344d82f05bc48b16f12827b04f324d4f3bba8ebfbf4fe1079fe18f072" +dependencies = [ + "bytemuck", + "document-features", + "getrandom 0.3.4", + "quiver", + "re_byte_size", + "re_log", + "serde", + "web-time", +] + +[[package]] +name = "re_types_core" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8bfe18f2708871b6f62091b1789dc50f58d58db0f8671dd2cb805a7c7851cdb" +dependencies = [ + "anyhow", + "arrow", + "bitflags 2.13.2", + "bytemuck", + "document-features", + "half", + "itertools 0.14.0", + "nohash-hasher", + "quiver", + "re_arrow_util", + "re_byte_size", + "re_case", + "re_error", + "re_log", + "re_string_interner", + "re_tracing", + "re_tuid", + "serde", + "thiserror 2.0.21", +] + +[[package]] +name = "re_uri" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3051c3983d798ef7c151870efd44bd14efacb5588bf06b50b540db0dc71e90ad" +dependencies = [ + "percent-encoding", + "re_byte_size", + "re_log", + "re_log_types", + "re_tuid", + "re_types_core", + "serde", + "static_assertions", + "thiserror 2.0.21", + "url", +] + +[[package]] +name = "re_video" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579fdf925303652e1fa8019235c010519e9da35cca415e6396441033cabb3f83" +dependencies = [ + "ahash", + "bit-vec 0.9.1", + "bytemuck", + "cfg_aliases", + "cros-codecs", + "econtext", + "getrandom 0.3.4", + "h264-reader", + "image", + "itertools 0.14.0", + "js-sys", + "poll-promise", + "re_byte_size", + "re_log", + "re_mp4", + "re_mutex", + "re_quota_channel", + "re_rvl", + "re_span", + "re_tracing", + "re_tuid", + "saturating_cast", + "scuffle-av1", + "scuffle-bytes-util", + "serde", + "smallvec", + "thiserror 2.0.21", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", +] + +[[package]] +name = "reborrow" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "redox_users" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" +dependencies = [ + "libredox", + "thiserror 2.0.21", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rerun" +version = "0.34.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4d0a5aec4cac00347273e40aed333fe20459d5cacab673e7100c7c1f5d3c57" +dependencies = [ + "ahash", + "anyhow", + "arrow", + "camino", + "cfg-if", + "crossbeam", + "document-features", + "indexmap", + "indicatif", + "itertools 0.14.0", + "parking_lot", + "puffin", + "rayon", + "re_arrow_util", + "re_build_info", + "re_build_tools", + "re_byte_size", + "re_capabilities", + "re_chunk", + "re_entity_db", + "re_error", + "re_format", + "re_grpc_server", + "re_log", + "re_log_channel", + "re_log_encoding", + "re_log_types", + "re_memory", + "re_protos", + "re_quota_channel", + "re_redap_client", + "re_sdk", + "re_sdk_types", + "re_sorbet", + "re_tracing", + "re_uri", + "re_video", + "similar-asserts", + "tokio", + "walkdir", +] + +[[package]] +name = "rerun-tonic-web-wasm-client" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cf00a06feab41977adfc4f2593cb60ed937351924d5bb0edeaa3eafbc02a6a" +dependencies = [ + "base64 0.22.1", + "byteorder", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "httparse", + "js-sys", + "pin-project", + "thiserror 2.0.21", + "tonic", + "tower-service", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", +] + +[[package]] +name = "rfc6381-codec" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed54c20f5c3ec82eab6d998b313dc75ec5d5650d4f57675e61d72489040297fd" +dependencies = [ + "mp4ra-rust", + "mpeg4-audio-const", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ron" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81116b9531d61eabc41aeb228e4b6b2435bcca3233b98cf3b3077d4e6e9debb3" +dependencies = [ + "bitflags 2.13.2", + "once_cell", + "serde", + "serde_derive", + "typeid", + "unicode-ident", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74b56ffa8bb2830709a538c2cbcae9aa062db0d2a42563bfb09bdaae44020eb" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.28", +] + +[[package]] +name = "rustix" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags 2.13.2", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safetensors" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "safetensors" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b079b829cb27a1c3c374341345ed2e8b2c0c839034522cee576c140bd7f846" +dependencies = [ + "hashbrown 0.16.1", + "libc", + "serde", + "serde_json", + "tempfile", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "saturating_cast" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc4972f129a0ea378b69fa7c186d63255606e362ad00795f00b869dea5265eb" + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scuffle-av1" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028eddc8b17fe9dba817b238c56d3acf03748bdbed4c35783cfb93857ef15955" +dependencies = [ + "byteorder", + "bytes", + "scuffle-bytes-util", + "scuffle-workspace-hack", +] + +[[package]] +name = "scuffle-bytes-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0417748c2a42f4a08d4e634b68b1d64f22a8c24bef2e7ac93df33aa61202a45b" +dependencies = [ + "byteorder", + "bytes", + "bytestring", + "scuffle-workspace-hack", +] + +[[package]] +name = "scuffle-workspace-hack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8028ded836a0d9fabdfa4d713389b76a2098b5153f50a135c8faed7e3a3d5ae2" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.13.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio", + "signal-hook", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" +dependencies = [ + "bstr", + "unicode-segmentation", +] + +[[package]] +name = "similar-asserts" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b441962c817e33508847a22bd82f03a30cff43642dc2fae8b050566121eb9a" +dependencies = [ + "console 0.15.11", + "similar", +] + +[[package]] +name = "siphasher" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spin" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0134f9043ed38b087ac4f7d4af44c79e2c9e5094421fe3164f435ce585953b10" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spm_precompiled" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326" +dependencies = [ + "base64 0.13.1", + "nom 7.1.3", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strfmt" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046d549b88a663d317cd04d39696fca5f77db4db44e1db65bfb9dee7f9e680bd" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.119", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "svg" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94afda9cd163c04f6bee8b4bf2501c91548deae308373c436f36aeff3cf3c4a3" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "synstructure" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "sysctl" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc" +dependencies = [ + "bitflags 2.13.2", + "byteorder", + "enum-as-inner", + "libc", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "sysinfo" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows", +] + +[[package]] +name = "system-deps" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0dae2cbca1f0ff93795713cfe0a4c02f760e3c0b8ae2ab4ec4045808ff429f" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-lexicon" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.3", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "termina" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" +dependencies = [ + "bitflags 2.13.2", + "parking_lot", + "rustix", + "signal-hook", + "windows-sys 0.61.2", +] + +[[package]] +name = "terminfo" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" +dependencies = [ + "fnv", + "nom 7.1.3", + "phf", + "phf_codegen", +] + +[[package]] +name = "termios" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" +dependencies = [ + "libc", +] + +[[package]] +name = "termwiz" +version = "0.23.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bitflags 2.13.2", + "fancy-regex", + "filedescriptor", + "finl_unicode", + "fixedbitset 0.4.2", + "hex", + "lazy_static", + "libc", + "log", + "memmem", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float 4.6.0", + "pest", + "pest_derive", + "phf", + "sha2", + "signal-hook", + "siphasher", + "terminfo", + "termios", + "thiserror 1.0.69", + "ucd-trie", + "unicode-segmentation", + "vtparse", + "wezterm-bidi", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl 2.0.21", +] + +[[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 2.0.119", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "thread_local" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad99c4c6d32803332c548b1af0540b357b3f5fc0be8f6c6bfe8b2e6ae784070" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb87b95ec50ddfa440816d227a17b2ccbdda963a316a727fda0fc4334f7d134" +dependencies = [ + "deranged", + "libc", + "num-conv", + "num_threads", + "powerfmt", + "serde_core", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tiny_http" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" +dependencies = [ + "ascii", + "chunked_transfer", + "httpdate", + "log", +] + +[[package]] +name = "tinystr" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokenizers" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e22d44a15349529690fb07bd645cf58149a1b1e44d6cb5bd1641ff1a6223" +dependencies = [ + "ahash", + "aho-corasick", + "compact_str 0.9.1", + "dary_heap", + "derive_builder", + "esaxx-rs", + "getrandom 0.3.4", + "itertools 0.14.0", + "log", + "macro_rules_attribute", + "monostate", + "onig", + "paste", + "rand 0.9.5", + "rayon", + "rayon-cond", + "regex", + "regex-syntax", + "serde", + "serde_json", + "spm_precompiled", + "thiserror 2.0.21", + "unicode-normalization-alignments", + "unicode-segmentation", + "unicode_categories", +] + +[[package]] +name = "tokio" +version = "1.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cc2678c2cdd569ef8215e2afd7954ada2ae20b4fdd2c5fe6139a3b02d105db" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d06f0b082ba57c26b79407372e57cf2a1e28124f78e9479fe80322cf53420b" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "libc", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "1.1.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.15+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "tonic" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" +dependencies = [ + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "rustls-native-certs", + "socket2", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tonic-web" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6a1b6319ca4b61a4c0f0c94d439c8f3ed344cca56fe0df40e1fe4be11380b" +dependencies = [ + "base64 0.22.1", + "bytes", + "http", + "http-body", + "pin-project", + "tokio-stream", + "tonic", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags 2.13.2", + "bytes", + "http", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracing-web" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e6a141feebd51f8d91ebfd785af50fca223c570b86852166caa3b141defe7c" +dependencies = [ + "js-sys", + "tracing-core", + "tracing-subscriber", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tui-scrollview" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "997f1ad8c98f3c1928bdf05a288d5ea5557b4261ea7c4c86fbf273f79b584da8" +dependencies = [ + "indoc", + "ratatui-core", + "ratatui-widgets", +] + +[[package]] +name = "tui-widgets" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0e6148c74b784d4228b3f8ea23d708192b17388e6204a8131322d5f615bd9ed" +dependencies = [ + "document-features", + "ratatui-core", + "tui-scrollview", +] + +[[package]] +name = "twox-hash" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5283634e518fe9e82c7b20520bb4bc209009fd16c82077c802f8111ecbb0117a" + +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "ug" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b761acf8af3494640d826a8609e2265e19778fb43306c7f15379c78c9b05b0" +dependencies = [ + "gemm 0.18.2", + "half", + "libloading 0.8.9", + "memmap2", + "num", + "num-traits", + "num_cpus", + "rayon", + "safetensors 0.4.5", + "serde", + "thiserror 1.0.69", + "tracing", + "yoke 0.7.5", +] + +[[package]] +name = "ug-cuda" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f0a1fa748f26166778c33b8498255ebb7c6bffb472bcc0a72839e07ebb1d9b5" +dependencies = [ + "cudarc 0.17.8", + "half", + "serde", + "thiserror 1.0.69", + "ug", +] + +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "unicode-normalization-alignments" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de" +dependencies = [ + "smallvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-truncate" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" +dependencies = [ + "itertools 0.14.0", + "unicode-segmentation", + "unicode-width", +] + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "unindent" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" + +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "unty" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dbe8d477efbc6c70a1dea1f9f1e0482168983a9147dee6b3a619f666f3aeac6" + +[[package]] +name = "uom" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a739f83872836c82a4f2527d4e54b37007b3de68cafe7edde95fd695968bf4b9" +dependencies = [ + "num-bigint", + "num-complex", + "num-rational", + "num-traits", + "serde_core", + "typenum", +] + +[[package]] +name = "ureq" +version = "3.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a7ac20be9b7726e0bbdbf974c059676d9acb1cd414961f570a4e8231cacd7fc" +dependencies = [ + "base64 0.23.1", + "flate2", + "log", + "percent-encoding", + "rustls", + "rustls-pki-types", + "ureq-proto", + "utf8-zero", + "webpki-roots", +] + +[[package]] +name = "ureq-proto" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86fd172ccca569e458f61b6bdd6220965a9ef36e672a6852953b51a0e1583be" +dependencies = [ + "base64 0.23.1", + "http", + "httparse", + "log", +] + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "utf8-zero" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8c0a043c9540bae7c578c88f91dda8bd82e59ae27c21baca69c8b191aaf5a6e" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +dependencies = [ + "atomic", + "getrandom 0.4.3", + "js-sys", + "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "vec1" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab68b56840f69efb0fefbe3ab6661499217ffdc58e2eef7c3f6f69835386322" +dependencies = [ + "serde", + "smallvec", +] + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "virtue" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2063ed945650e9080bcfa2b56cbde318efe1347a3cf06882e23e2f124183e88" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "vtparse" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.4+wasi-0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbab34de2d982e9b48e18d216d04c4a6f641066ff19ffb699980f591ee3610e" +dependencies = [ + "js-sys", + "tokio", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 3.0.6", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.129" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88261b9deccee56594c11a3460c462c41f58d148598fe70ad77070126a68aba4" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "wezterm-bidi" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" +dependencies = [ + "log", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-blob-leases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +dependencies = [ + "getrandom 0.3.4", + "mac_address", + "sha2", + "thiserror 1.0.69", + "uuid", +] + +[[package]] +name = "wezterm-color-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +dependencies = [ + "csscolorparser", + "deltae", + "lazy_static", + "wezterm-dynamic", +] + +[[package]] +name = "wezterm-dynamic" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +dependencies = [ + "log", + "ordered-float 4.6.0", + "strsim", + "thiserror 1.0.69", + "wezterm-dynamic-derive", +] + +[[package]] +name = "wezterm-dynamic-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "wezterm-input-types" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +dependencies = [ + "bitflags 1.3.2", + "euclid", + "lazy_static", + "serde", + "wezterm-dynamic", +] + +[[package]] +name = "which" +version = "7.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +dependencies = [ + "either", + "env_home", + "rustix", + "winsafe", +] + +[[package]] +name = "wildmatch" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29333c3ea1ba8b17211763463ff24ee84e41c78224c16b001cd907e663a38c68" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" +dependencies = [ + "memchr", +] + +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "xxhash-rust" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "550a2b930b62486a393c52d5c3b84bff264b28aa437ed64694d31e93b1757af7" + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive 0.7.5", + "zerofrom", +] + +[[package]] +name = "yoke" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" +dependencies = [ + "stable_deref_trait", + "yoke-derive 0.8.4", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "synstructure 0.13.2", +] + +[[package]] +name = "yoke-derive" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure 0.14.0", +] + +[[package]] +name = "zerocopy" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", + "synstructure 0.14.0", +] + +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c50655cbb0fe3fc43170059e702f1ce5e19b84cec58dc87b037a09935c2f328" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "zerotrie" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" +dependencies = [ + "displaydoc", + "yoke 0.8.3", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" +dependencies = [ + "yoke 0.8.3", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "zip" +version = "8.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b" +dependencies = [ + "crc32fast", + "indexmap", + "memchr", + "typed-path", +] + +[[package]] +name = "zlib-rs" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b268e58e7c693d7c271f93ffc4ba3b380412554231c85bf61ca7af91042a4112" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" + +[[package]] +name = "zune-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/copper-rs-pose/app/Cargo.toml b/copper-rs-pose/app/Cargo.toml new file mode 100644 index 0000000..26bfb20 --- /dev/null +++ b/copper-rs-pose/app/Cargo.toml @@ -0,0 +1,35 @@ +# Based on copper-rs examples/cu_human_pose (release/1.2, Apache-2.0). +# Copper crates are pinned exactly: the SDK rust is older than the declared +# rust-version (1.95), so the build uses --ignore-rust-version and any new +# Copper release could break it. +[package] +name = "copper-rs-pose" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" +publish = false + +[features] +default = ["cpu"] +cpu = [] +cuda = ["candle-core/cuda", "candle-nn/cuda"] + +[dependencies] +cu29 = { version = "=1.2.1", features = ["log-level-debug", "textlogs"] } +cu-gstreamer = { version = "=1.2.1", features = ["gst"] } +cu-sensor-payloads = "=1.2.1" +cu-logmon = "=1.2.1" +# default-features = false drops clipboard support and stderr capture. +cu-consolemon = { version = "=1.2.1", default-features = false } + +candle-core = "0.11.0" +candle-nn = "0.11.0" +rerun = { version = "0.34", default-features = false, features = ["sdk", "server"] } +bincode = { package = "cu-bincode", version = "2.1", default-features = false, features = ["derive", "alloc"] } +serde = { version = "1.0", default-features = false, features = ["derive", "alloc"] } + +[build-dependencies] +cu29-build = "=1.2.1" + +[profile.release] +strip = true diff --git a/copper-rs-pose/app/build.rs b/copper-rs-pose/app/build.rs new file mode 100644 index 0000000..7cbac12 --- /dev/null +++ b/copper-rs-pose/app/build.rs @@ -0,0 +1,3 @@ +fn main() { + cu29_build::setup(); +} diff --git a/copper-rs-pose/app/copperconfig.ron b/copper-rs-pose/app/copperconfig.ron new file mode 100644 index 0000000..0f3d468 --- /dev/null +++ b/copper-rs-pose/app/copperconfig.ron @@ -0,0 +1,84 @@ +( + tasks: [ + ( + id: "camera", + type: "cu_gstreamer::CuDefaultGStreamer", + config: { + // /dev/copper-camera is a udev link to the USB (UVC) camera. + "pipeline": "v4l2src device=/dev/copper-camera ! videoconvert ! videoscale ! video/x-raw, format=NV12, width=640, height=360 ! appsink name=copper max-buffers=1 drop=true sync=false", + "caps": "video/x-raw, format=NV12, width=640, height=360", + "log_bus_messages": true, + "log_pad_events": true, + "log_src_pad_events": true, + "stop_timeout_ms": 2000, + }, + // Do not write raw frames to the .copper log (about 345 KB each). + logging: ( + enabled: false, + ), + ), + ( + id: "gst_to_image", + type: "tasks::GstToCuImage", + config: { + "width": 640, + "height": 360, + "fourcc": "NV12", + }, + logging: ( + enabled: false, + ), + ), + ( + id: "yolo", + type: "tasks::YoloPose", + config: { + "variant": "yolov8n-pose", + // Installed into the extension by copper-install.sh. + "model_path": "/usr/share/copper-rs-pose/yolov8n-pose.safetensors", + "conf_threshold": 0.25, + "iou_threshold": 0.7, + }, + ), + ( + id: "viz", + type: "tasks::RerunPoseViz", + ), + ], + cnx: [ + ( + src: "camera", + dst: "gst_to_image", + msg: "cu_gstreamer::CuGstBuffer", + ), + ( + src: "gst_to_image", + dst: "yolo", + msg: "cu_sensor_payloads::CuImage>", + ), + ( + src: "gst_to_image", + dst: "viz", + msg: "cu_sensor_payloads::CuImage>", + ), + ( + src: "yolo", + dst: "viz", + msg: "payloads::CuPoses", + ), + ], + logging: ( + keyframe_interval: 10000, + section_size_mib: 32, + ), + // CuConsoleMon shows its TUI only when stdin and stdout are a terminal + // (a manual run over `ssh -t`). Under systemd it does nothing. + monitors: [ + ( + type: "cu_logmon::CuLogMon", + ), + ( + type: "cu_consolemon::CuConsoleMon", + ), + ], +) diff --git a/copper-rs-pose/app/src/image.rs b/copper-rs-pose/app/src/image.rs new file mode 100644 index 0000000..0d12733 --- /dev/null +++ b/copper-rs-pose/app/src/image.rs @@ -0,0 +1,64 @@ +//! Shared image format conversion helpers. + +/// Convert YUYV (YUV 4:2:2) to RGB. +pub fn yuyv_to_rgb(data: &[u8], width: usize, height: usize) -> Vec { + let mut rgb = Vec::with_capacity(width * height * 3); + + for chunk in data.chunks(4) { + if chunk.len() < 4 { + break; + } + let y0 = chunk[0] as f32; + let u = chunk[1] as f32 - 128.0; + let y1 = chunk[2] as f32; + let v = chunk[3] as f32 - 128.0; + + let r0 = (y0 + 1.402 * v).clamp(0.0, 255.0) as u8; + let g0 = (y0 - 0.344 * u - 0.714 * v).clamp(0.0, 255.0) as u8; + let b0 = (y0 + 1.772 * u).clamp(0.0, 255.0) as u8; + rgb.extend_from_slice(&[r0, g0, b0]); + + let r1 = (y1 + 1.402 * v).clamp(0.0, 255.0) as u8; + let g1 = (y1 - 0.344 * u - 0.714 * v).clamp(0.0, 255.0) as u8; + let b1 = (y1 + 1.772 * u).clamp(0.0, 255.0) as u8; + rgb.extend_from_slice(&[r1, g1, b1]); + } + + rgb +} + +/// Convert NV12 (YUV 4:2:0) to RGB. +pub fn nv12_to_rgb(data: &[u8], width: usize, height: usize) -> Vec { + let mut rgb = Vec::with_capacity(width * height * 3); + let y_plane = &data[..width * height]; + let uv_plane = &data[width * height..]; + + for y_idx in 0..height { + for x_idx in 0..width { + let y = y_plane[y_idx * width + x_idx] as f32; + let uv_idx = (y_idx / 2) * width + (x_idx / 2) * 2; + let u = uv_plane.get(uv_idx).copied().unwrap_or(128) as f32 - 128.0; + let v = uv_plane.get(uv_idx + 1).copied().unwrap_or(128) as f32 - 128.0; + + let r = (y + 1.402 * v).clamp(0.0, 255.0) as u8; + let g = (y - 0.344 * u - 0.714 * v).clamp(0.0, 255.0) as u8; + let b = (y + 1.772 * u).clamp(0.0, 255.0) as u8; + rgb.extend_from_slice(&[r, g, b]); + } + } + + rgb +} + +/// Convert BGR to RGB. +pub fn bgr_to_rgb(data: &[u8], _width: usize, _height: usize) -> Vec { + data.chunks(3) + .flat_map(|bgr| { + if bgr.len() >= 3 { + [bgr[2], bgr[1], bgr[0]] + } else { + [0, 0, 0] + } + }) + .collect() +} diff --git a/copper-rs-pose/app/src/main.rs b/copper-rs-pose/app/src/main.rs new file mode 100644 index 0000000..9b1d39b --- /dev/null +++ b/copper-rs-pose/app/src/main.rs @@ -0,0 +1,57 @@ +//! YOLOv8 Pose Estimation Demo for Copper +//! +//! This example demonstrates real-time pose estimation using: +//! - GStreamer (V4L2) camera input +//! - YOLOv8-pose model via Candle (HuggingFace ML framework) +//! - Rerun visualization for displaying results +//! +//! Based on the copper-rs `cu_human_pose` example. See getting_started.md. + +mod image; +mod payloads; +mod tasks; +mod yolo; + +use std::fs; +use std::path::Path; +use std::process::ExitCode; + +use cu29::prelude::*; + +// Re-export for RON config visibility +pub use payloads::*; +pub use tasks::*; + +// Size of one log slab. cu29 makes a new slab file when one is full. +const SLAB_SIZE: Option = Some(256 * 1024 * 1024); // 256 MB + +#[copper_runtime(config = "copperconfig.ron")] +struct YoloPoseDemoApplication {} + +fn main() -> ExitCode { + // The root filesystem is read-only. systemd makes this directory (StateDirectory=). + let logger_path = "/var/lib/copper-rs-pose/human-pose.copper"; + if let Some(parent) = Path::new(logger_path).parent() + && !parent.exists() + { + fs::create_dir_all(parent).expect("Failed to create logs directory"); + } + + // Build the application from RON config + let application = YoloPoseDemoApplication::builder() + .with_log_path(logger_path, SLAB_SIZE) + .expect("Failed to set up Copper logging") + .build() + .expect("Failed to build application"); + + // `run` starts the tasks itself. + if let Err(e) = application.run_until_shutdown() { + error!("Error during iteration: {}", e.error.to_string()); + // In a release build, error! goes only to the .copper log. Tell systemd too. + eprintln!("copper-rs-pose: {}", e.error); + // Return (do not call process::exit) so that `e` is dropped and the + // logger closes the .copper file. + return ExitCode::FAILURE; + } + ExitCode::SUCCESS +} diff --git a/copper-rs-pose/app/src/payloads.rs b/copper-rs-pose/app/src/payloads.rs new file mode 100644 index 0000000..de6d9cc --- /dev/null +++ b/copper-rs-pose/app/src/payloads.rs @@ -0,0 +1,113 @@ +use bincode::{Decode, Encode}; +use cu29::prelude::*; +use serde::{Deserialize, Serialize}; + +/// Maximum number of poses to detect per frame +pub const MAX_POSES: usize = 32; + +/// Number of keypoints in COCO pose format (YOLOv8-pose) +pub const NUM_KEYPOINTS: usize = 17; + +// COCO keypoint indices for reference: +// 0: nose, 1: left_eye, 2: right_eye, 3: left_ear, 4: right_ear, +// 5: left_shoulder, 6: right_shoulder, 7: left_elbow, 8: right_elbow, +// 9: left_wrist, 10: right_wrist, 11: left_hip, 12: right_hip, +// 13: left_knee, 14: right_knee, 15: left_ankle, 16: right_ankle + +// Skeleton connections for visualization (pairs of keypoint indices) +pub const SKELETON_CONNECTIONS: [(usize, usize); 19] = [ + (0, 1), // nose -> left_eye + (0, 2), // nose -> right_eye + (1, 3), // left_eye -> left_ear + (2, 4), // right_eye -> right_ear + (5, 6), // left_shoulder -> right_shoulder + (5, 7), // left_shoulder -> left_elbow + (7, 9), // left_elbow -> left_wrist + (6, 8), // right_shoulder -> right_elbow + (8, 10), // right_elbow -> right_wrist + (5, 11), // left_shoulder -> left_hip + (6, 12), // right_shoulder -> right_hip + (11, 12), // left_hip -> right_hip + (11, 13), // left_hip -> left_knee + (13, 15), // left_knee -> left_ankle + (12, 14), // right_hip -> right_knee + (14, 16), // right_knee -> right_ankle + (0, 5), // nose -> left_shoulder (neck proxy) + (0, 6), // nose -> right_shoulder (neck proxy) + (5, 6), // left_shoulder -> right_shoulder (duplicate for torso) +]; + +/// A single keypoint with x, y coordinates and confidence score +#[derive(Debug, Clone, Copy, Default, Encode, Decode, Serialize, Deserialize, Reflect)] +pub struct Keypoint { + pub x: f32, + pub y: f32, + pub confidence: f32, +} + +impl Keypoint { + pub fn new(x: f32, y: f32, confidence: f32) -> Self { + Self { x, y, confidence } + } + + /// Check if keypoint is visible (confidence above threshold) + pub fn is_visible(&self, threshold: f32) -> bool { + self.confidence >= threshold + } +} + +/// A single detected pose with bounding box and keypoints +#[derive(Debug, Clone, Default, Encode, Decode, Serialize, Deserialize, Reflect)] +pub struct Pose { + /// Bounding box in format [x_center, y_center, width, height] + pub bbox: [f32; 4], + /// Detection confidence score + pub confidence: f32, + /// 17 COCO keypoints + pub keypoints: [Keypoint; NUM_KEYPOINTS], +} + +impl Pose { + /// Get bounding box corners as (x1, y1, x2, y2) + pub fn bbox_corners(&self) -> (f32, f32, f32, f32) { + let [cx, cy, w, h] = self.bbox; + let x1 = cx - w / 2.0; + let y1 = cy - h / 2.0; + let x2 = cx + w / 2.0; + let y2 = cy + h / 2.0; + (x1, y1, x2, y2) + } +} + +/// Collection of detected poses in a frame +#[derive(Debug, Clone, Default, Encode, Decode, Serialize, Deserialize, Reflect)] +pub struct CuPoses { + pub poses: Vec, +} + +impl CuPoses { + pub fn new() -> Self { + Self { poses: Vec::new() } + } + + #[allow(clippy::result_large_err)] + pub fn push(&mut self, pose: Pose) -> Result<(), Pose> { + if self.poses.len() >= MAX_POSES { + return Err(pose); + } + self.poses.push(pose); + Ok(()) + } + + pub fn len(&self) -> usize { + self.poses.len() + } + + pub fn is_empty(&self) -> bool { + self.poses.is_empty() + } + + pub fn iter(&self) -> impl Iterator { + self.poses.iter() + } +} diff --git a/copper-rs-pose/app/src/tasks/gst_to_image.rs b/copper-rs-pose/app/src/tasks/gst_to_image.rs new file mode 100644 index 0000000..91c50fb --- /dev/null +++ b/copper-rs-pose/app/src/tasks/gst_to_image.rs @@ -0,0 +1,188 @@ +//! Convert a GStreamer buffer into a CuImage for downstream tasks. + +use cu_gstreamer::CuGstBuffer; +use cu_sensor_payloads::{CuImage, CuImageBufferFormat}; +use cu29::bincode::{Decode, Encode}; +use cu29::prelude::*; +use std::ops::DerefMut; +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static GST_LOG_COUNT: AtomicUsize = AtomicUsize::new(0); + +#[derive(Reflect)] +#[reflect(from_reflect = false)] +pub struct GstToCuImage { + format: CuImageBufferFormat, + #[reflect(ignore)] + pool: Arc>>, + last_payload_ns: Option, + last_warn_ns: u64, +} + +impl Freezable for GstToCuImage { + fn freeze( + &self, + encoder: &mut E, + ) -> Result<(), cu29::bincode::error::EncodeError> { + Encode::encode(&self.last_payload_ns, encoder)?; + Encode::encode(&self.last_warn_ns, encoder)?; + Ok(()) + } + + fn thaw( + &mut self, + decoder: &mut D, + ) -> Result<(), cu29::bincode::error::DecodeError> { + self.last_payload_ns = Decode::decode(decoder)?; + self.last_warn_ns = Decode::decode(decoder)?; + Ok(()) + } +} + +impl CuTask for GstToCuImage { + type Resources<'r> = (); + type Input<'m> = input_msg!(CuGstBuffer); + type Output<'m> = output_msg!(CuImage>); + + fn new(config: Option<&ComponentConfig>, _resources: Self::Resources<'_>) -> CuResult + where + Self: Sized, + { + let config = config.ok_or_else(|| CuError::from("GstToCuImage requires configuration"))?; + + let width = config + .get::("width")? + .ok_or_else(|| CuError::from("GstToCuImage requires width"))?; + let height = config + .get::("height")? + .ok_or_else(|| CuError::from("GstToCuImage requires height"))?; + let fourcc = if let Some(fourcc) = config.get::("fourcc")? { + fourcc + } else if let Some(pixel_format) = config.get::("pixel_format")? { + pixel_format + } else { + return Err(CuError::from( + "GstToCuImage requires fourcc (or pixel_format)", + )); + }; + let pixel_format = fourcc_to_bytes(&fourcc)?; + let stride = config + .get::("stride")? + .unwrap_or_else(|| default_stride(width, pixel_format)); + let format = CuImageBufferFormat { + width, + height, + stride, + pixel_format, + }; + if !format.is_valid() { + return Err(CuError::from(format!( + "Invalid image layout for fourcc={} width={} height={} stride={}", + fourcc, width, height, stride + ))); + } + + let buffer_size = format.byte_size(); + let pool_size = config.get::("pool_size")?.unwrap_or(4) as usize; + let pool_id = config + .get::("pool_id")? + .unwrap_or_else(|| "gst_image_pool".to_string()); + + let pool = CuHostMemoryPool::new(&pool_id, pool_size, || vec![0u8; buffer_size])?; + + Ok(Self { + format, + pool, + last_payload_ns: None, + last_warn_ns: 0, + }) + } + + fn process( + &mut self, + ctx: &CuContext, + input: &Self::Input<'_>, + output: &mut Self::Output<'_>, + ) -> CuResult<()> { + let now_ns = ctx.now().as_nanos(); + let Some(buffer) = input.payload() else { + const WARN_AFTER_NS: u64 = 2_000_000_000; + const WARN_EVERY_NS: u64 = 2_000_000_000; + let last_payload_ns = self.last_payload_ns.unwrap_or(0); + if now_ns.saturating_sub(last_payload_ns) >= WARN_AFTER_NS + && now_ns.saturating_sub(self.last_warn_ns) >= WARN_EVERY_NS + { + warning!( + "gst_to_image: no frames received for {} ms", + now_ns.saturating_sub(last_payload_ns) / 1_000_000 + ); + self.last_warn_ns = now_ns; + } + output.clear_payload(); + return Ok(()); + }; + self.last_payload_ns = Some(now_ns); + + let mapped = buffer + .map_readable() + .map_err(|e| CuError::new_with_cause("Failed to map GStreamer buffer", e))?; + let src = mapped.as_slice(); + let min_len = self.format.required_bytes(); + let log_idx = GST_LOG_COUNT.fetch_add(1, Ordering::Relaxed); + if log_idx < 5 { + info!( + "gst_to_image: buf_len={} min_len={} width={} height={} stride={} fourcc={}", + src.len(), + min_len, + self.format.width, + self.format.height, + self.format.stride, + String::from_utf8_lossy(&self.format.pixel_format) + ); + } + if src.len() < min_len { + return Err(CuError::from(format!( + "GStreamer buffer too small: expected >= {}, got {} bytes", + min_len, + src.len() + ))); + } + + // Acquire a buffer from the pool instead of allocating + let handle = self + .pool + .acquire() + .ok_or_else(|| CuError::from("Failed to acquire buffer from image pool"))?; + + // Copy the source data into the pooled buffer + handle.with_inner_mut(|inner| { + let dest = inner.deref_mut(); + let copy_len = src.len().min(dest.len()); + dest[..copy_len].copy_from_slice(&src[..copy_len]); + }); + + let image = CuImage::new(self.format, handle); + output.tov = input.tov; + output.set_payload(image); + Ok(()) + } +} + +fn default_stride(width: u32, pixel_format: [u8; 4]) -> u32 { + match &pixel_format { + b"YUYV" => width * 2, + b"BGR3" | b"RGB3" | b"BGR " | b"RGB " => width * 3, + _ => width, + } +} + +fn fourcc_to_bytes(fourcc: &str) -> CuResult<[u8; 4]> { + let bytes = fourcc.as_bytes(); + if bytes.len() != 4 { + return Err(CuError::from("fourcc must be exactly 4 characters")); + } + let mut out = [0u8; 4]; + out.copy_from_slice(&bytes[0..4]); + Ok(out) +} diff --git a/copper-rs-pose/app/src/tasks/mod.rs b/copper-rs-pose/app/src/tasks/mod.rs new file mode 100644 index 0000000..34b4582 --- /dev/null +++ b/copper-rs-pose/app/src/tasks/mod.rs @@ -0,0 +1,7 @@ +mod gst_to_image; +mod rerun_viz; +mod yolo_pose; + +pub use gst_to_image::GstToCuImage; +pub use rerun_viz::RerunPoseViz; +pub use yolo_pose::YoloPose; diff --git a/copper-rs-pose/app/src/tasks/rerun_viz.rs b/copper-rs-pose/app/src/tasks/rerun_viz.rs new file mode 100644 index 0000000..03c1104 --- /dev/null +++ b/copper-rs-pose/app/src/tasks/rerun_viz.rs @@ -0,0 +1,232 @@ +//! Rerun visualization sink for pose estimation results + +use crate::image::{bgr_to_rgb, nv12_to_rgb, yuyv_to_rgb}; +use crate::payloads::{CuPoses, SKELETON_CONNECTIONS}; +use cu_sensor_payloads::CuImage; +use cu29::prelude::*; +use rerun::{ + Boxes2D, ChannelDatatype, ColorModel, Image, LineStrips2D, Points2D, RecordingStream, + RecordingStreamBuilder, Vec2D, +}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static IMAGE_LOG_COUNT: AtomicUsize = AtomicUsize::new(0); + +/// Rerun visualization sink for pose estimation +/// +/// Displays the camera image with overlaid pose skeletons, +/// keypoints, and bounding boxes. +#[derive(Reflect)] +#[reflect(from_reflect = false)] +pub struct RerunPoseViz { + #[reflect(ignore)] + rec: RecordingStream, +} + +const CAMERA_ENTITY: &str = "camera/image"; + +impl Freezable for RerunPoseViz {} + +impl CuSinkTask for RerunPoseViz { + type Resources<'r> = (); + // Two separate inputs: image from camera, poses from YOLO + // Use 'm lifetime and separate types for multiple inputs + type Input<'m> = input_msg!('m, CuImage>, CuPoses); + + fn new(_config: Option<&ComponentConfig>, _resources: Self::Resources<'_>) -> CuResult + where + Self: Sized, + { + // The device has no display. Serve the stream so a Rerun viewer on the + // laptop can connect. The history limit keeps memory use bounded when + // no viewer is connected. + let rec = RecordingStreamBuilder::new("YOLO Pose Demo") + .serve_grpc_opts( + "0.0.0.0", + rerun::DEFAULT_SERVER_PORT, + rerun::ServerOptions { + playback_behavior: rerun::PlaybackBehavior::NewestFirst, + memory_limit: rerun::MemoryLimit::from_bytes(256 * 1024 * 1024), + ..Default::default() + }, + ) + .map_err(|e| CuError::new_with_cause("Failed to start Rerun gRPC server", e))?; + eprintln!( + "copper-rs-pose: Rerun server ready. On your laptop run: rerun --connect rerun+http://:{}/proxy", + rerun::DEFAULT_SERVER_PORT + ); + + Ok(Self { rec }) + } + + fn process(&mut self, _ctx: &CuContext, input: &Self::Input<'_>) -> CuResult<()> { + // Input is a reference to a tuple of message references + let (image_msg, poses_msg) = *input; + + // Log the camera image if available + if let Some(image) = image_msg.payload() { + self.log_image(image)?; + } + + // Log pose visualizations if available + if let Some(poses) = poses_msg.payload() { + self.log_poses(poses)?; + } + + Ok(()) + } +} + +impl RerunPoseViz { + fn log_image(&self, image: &CuImage>) -> CuResult<()> { + let width = image.format.width; + let height = image.format.height; + let pixel_format = &image.format.pixel_format; + + // Convert image to RGB for visualization + let rgb_data: Vec = image.buffer_handle.with_inner(|data| { + match pixel_format { + b"YUYV" => yuyv_to_rgb(data, width as usize, height as usize), + b"NV12" => nv12_to_rgb(data, width as usize, height as usize), + b"RGB3" | b"RGB " => data.to_vec(), + b"BGR3" | b"BGR " => bgr_to_rgb(data, width as usize, height as usize), + _ => { + // Attempt to handle as RGB or grayscale + if data.len() == (width * height * 3) as usize { + data.to_vec() + } else if data.len() == (width * height) as usize { + data.iter().flat_map(|&g| [g, g, g]).collect() + } else { + vec![128u8; (width * height * 3) as usize] + } + } + } + }); + + let log_idx = IMAGE_LOG_COUNT.fetch_add(1, Ordering::Relaxed); + if log_idx < 5 { + info!( + "rerun_viz: width={} height={} pixel_format={} rgb_len={}", + width, + height, + String::from_utf8_lossy(pixel_format), + rgb_data.len() + ); + } + + let rerun_image = Image::from_color_model_and_bytes( + rgb_data, + [width, height], + ColorModel::RGB, + ChannelDatatype::U8, + ); + + self.rec + .log(CAMERA_ENTITY, &rerun_image) + .map_err(|e| CuError::new_with_cause("Failed to log image", e))?; + + Ok(()) + } + + fn log_poses(&self, poses: &CuPoses) -> CuResult<()> { + if poses.is_empty() { + // Clear previous visualizations when no poses detected + let _ = self + .rec + .log(CAMERA_ENTITY, &Points2D::new(Vec::::new())); + let _ = self + .rec + .log(CAMERA_ENTITY, &LineStrips2D::new(Vec::>::new())); + let _ = self.rec.log( + CAMERA_ENTITY, + &Boxes2D::from_centers_and_sizes(Vec::::new(), Vec::::new()), + ); + return Ok(()); + } + + // Collect all keypoints for visualization + let mut all_keypoints: Vec = Vec::new(); + let mut keypoint_colors: Vec = Vec::new(); + + // Collect skeleton lines + let mut skeleton_strips: Vec> = Vec::new(); + + // Collect bounding boxes + let mut box_centers: Vec = Vec::new(); + let mut box_sizes: Vec = Vec::new(); + + // Color palette for different poses + let pose_colors = [ + rerun::Color::from_rgb(255, 0, 0), // Red + rerun::Color::from_rgb(0, 255, 0), // Green + rerun::Color::from_rgb(0, 0, 255), // Blue + rerun::Color::from_rgb(255, 255, 0), // Yellow + rerun::Color::from_rgb(255, 0, 255), // Magenta + rerun::Color::from_rgb(0, 255, 255), // Cyan + ]; + + for (pose_idx, pose) in poses.iter().enumerate() { + let color = pose_colors[pose_idx % pose_colors.len()]; + + // Add keypoints + for kp in &pose.keypoints { + if kp.confidence > 0.5 { + all_keypoints.push(Vec2D::new(kp.x, kp.y)); + keypoint_colors.push(color); + } + } + + // Add skeleton connections + for &(i, j) in &SKELETON_CONNECTIONS { + let kp1 = &pose.keypoints[i]; + let kp2 = &pose.keypoints[j]; + + if kp1.confidence > 0.5 && kp2.confidence > 0.5 { + skeleton_strips.push(vec![Vec2D::new(kp1.x, kp1.y), Vec2D::new(kp2.x, kp2.y)]); + } + } + + // Add bounding box + box_centers.push(Vec2D::new(pose.bbox[0], pose.bbox[1])); + box_sizes.push(Vec2D::new(pose.bbox[2], pose.bbox[3])); + } + + // Log keypoints + if !all_keypoints.is_empty() { + let radii = vec![rerun::Radius::new_scene_units(5.0); all_keypoints.len()]; + self.rec + .log( + CAMERA_ENTITY, + &Points2D::new(all_keypoints) + .with_colors(keypoint_colors) + .with_radii(radii), + ) + .map_err(|e| CuError::new_with_cause("Failed to log keypoints", e))?; + } + + // Log skeleton + if !skeleton_strips.is_empty() { + let skeleton_colors = vec![rerun::Color::from_rgb(255, 255, 0); skeleton_strips.len()]; + self.rec + .log( + CAMERA_ENTITY, + &LineStrips2D::new(skeleton_strips).with_colors(skeleton_colors), + ) + .map_err(|e| CuError::new_with_cause("Failed to log skeleton", e))?; + } + + // Log bounding boxes + if !box_centers.is_empty() { + let box_colors = vec![rerun::Color::from_rgb(0, 255, 0); box_centers.len()]; + self.rec + .log( + CAMERA_ENTITY, + &Boxes2D::from_centers_and_sizes(box_centers, box_sizes) + .with_colors(box_colors), + ) + .map_err(|e| CuError::new_with_cause("Failed to log boxes", e))?; + } + + Ok(()) + } +} diff --git a/copper-rs-pose/app/src/tasks/yolo_pose.rs b/copper-rs-pose/app/src/tasks/yolo_pose.rs new file mode 100644 index 0000000..5749177 --- /dev/null +++ b/copper-rs-pose/app/src/tasks/yolo_pose.rs @@ -0,0 +1,131 @@ +//! YOLOv8 Pose estimation Copper task + +use crate::payloads::CuPoses; +use crate::yolo::{Multiples, YoloV8Pose, preprocess_image, process_predictions}; +use candle_core::{DType, Device}; +use candle_nn::{Module, VarBuilder}; +use cu_sensor_payloads::CuImage; +use cu29::prelude::*; + +/// YOLOv8 Pose estimation task +/// +/// Processes incoming camera images and outputs detected poses with keypoints. +#[derive(Reflect)] +#[reflect(from_reflect = false)] +pub struct YoloPose { + #[reflect(ignore)] + model: YoloV8Pose, + #[reflect(ignore)] + device: Device, + conf_threshold: f32, + iou_threshold: f32, +} + +impl Freezable for YoloPose {} + +impl CuTask for YoloPose { + type Resources<'r> = (); + type Input<'m> = input_msg!(CuImage>); + type Output<'m> = output_msg!(CuPoses); + + fn new(config: Option<&ComponentConfig>, _resources: Self::Resources<'_>) -> CuResult + where + Self: Sized, + { + // Parse configuration + let config = config.ok_or_else(|| CuError::from("YoloPose requires configuration"))?; + + let variant = config + .get::("variant")? + .unwrap_or_else(|| "yolov8n-pose".to_string()); + + let conf_threshold = config.get::("conf_threshold")?.unwrap_or(0.25) as f32; + let iou_threshold = config.get::("iou_threshold")?.unwrap_or(0.7) as f32; + + // Determine model size from variant + let multiples = match variant.as_str() { + "yolov8n-pose" => Multiples::n(), + "yolov8s-pose" => Multiples::s(), + "yolov8m-pose" => Multiples::m(), + "yolov8l-pose" => Multiples::l(), + "yolov8x-pose" => Multiples::x(), + _ => { + return Err(CuError::from(format!( + "Unknown variant: {}. Use yolov8[n|s|m|l|x]-pose", + variant + ))); + } + }; + + // Select device based on feature flags + #[cfg(feature = "cuda")] + let device = Device::new_cuda(0).unwrap_or(Device::Cpu); + + #[cfg(not(feature = "cuda"))] + let device = Device::Cpu; + + // The weights are installed in the extension at build time. The device + // does not download them. + let model_path = config + .get::("model_path")? + .ok_or_else(|| CuError::from("YoloPose requires model_path"))?; + + // Load the model + // SAFETY: The safetensors file is memory-mapped and only read by VarBuilder. + let vb = unsafe { + VarBuilder::from_mmaped_safetensors(&[model_path], DType::F32, &device) + .map_err(|e| CuError::new_with_cause("Failed to load model weights", e))? + }; + + let model = YoloV8Pose::load(vb, multiples, 1, (17, 3)) + .map_err(|e| CuError::new_with_cause("Failed to build YOLOv8 model", e))?; + + Ok(Self { + model, + device, + conf_threshold, + iou_threshold, + }) + } + + fn process( + &mut self, + _ctx: &CuContext, + input: &Self::Input<'_>, + output: &mut Self::Output<'_>, + ) -> CuResult<()> { + let Some(image) = input.payload() else { + // No image received; don't emit poses to avoid clearing downstream overlays. + output.clear_payload(); + return Ok(()); + }; + + // Preprocess the image + let (tensor, model_w, model_h) = preprocess_image(image, &self.device) + .map_err(|e| CuError::new_with_cause("Failed to preprocess image", e))?; + + // Run inference + let predictions = self + .model + .forward(&tensor) + .map_err(|e| CuError::new_with_cause("Model inference failed", e))? + .squeeze(0) + .map_err(|e| CuError::new_with_cause("Failed to squeeze predictions", e))?; + + // Postprocess predictions + let poses = process_predictions( + &predictions, + image.format.width, + image.format.height, + model_w, + model_h, + self.conf_threshold, + self.iou_threshold, + ); + + output.set_payload(poses); + output.tov = input.tov; + + Ok(()) + } +} diff --git a/copper-rs-pose/app/src/yolo/mod.rs b/copper-rs-pose/app/src/yolo/mod.rs new file mode 100644 index 0000000..c687f29 --- /dev/null +++ b/copper-rs-pose/app/src/yolo/mod.rs @@ -0,0 +1,7 @@ +pub mod model; +pub mod postprocess; +pub mod preprocess; + +pub use model::{Multiples, YoloV8Pose}; +pub use postprocess::process_predictions; +pub use preprocess::preprocess_image; diff --git a/copper-rs-pose/app/src/yolo/model.rs b/copper-rs-pose/app/src/yolo/model.rs new file mode 100644 index 0000000..8e9f602 --- /dev/null +++ b/copper-rs-pose/app/src/yolo/model.rs @@ -0,0 +1,683 @@ +//! YOLOv8 Pose model implementation using Candle +//! +//! Adapted from the candle-examples yolo-v8 implementation. +//! See: https://github.com/huggingface/candle/tree/main/candle-examples/examples/yolo-v8 + +use candle_core::{D, DType, IndexOp, Result, Tensor}; +use candle_nn::{Conv2d, Conv2dConfig, Module, VarBuilder, batch_norm, conv2d, conv2d_no_bias}; + +/// Model size multipliers for different YOLOv8 variants +#[derive(Clone, Copy, PartialEq, Debug)] +pub struct Multiples { + depth: f64, + width: f64, + ratio: f64, +} + +impl Multiples { + pub fn n() -> Self { + Self { + depth: 0.33, + width: 0.25, + ratio: 2.0, + } + } + + pub fn s() -> Self { + Self { + depth: 0.33, + width: 0.50, + ratio: 2.0, + } + } + + pub fn m() -> Self { + Self { + depth: 0.67, + width: 0.75, + ratio: 1.5, + } + } + + pub fn l() -> Self { + Self { + depth: 1.00, + width: 1.00, + ratio: 1.0, + } + } + + pub fn x() -> Self { + Self { + depth: 1.00, + width: 1.25, + ratio: 1.0, + } + } + + fn filters(&self) -> (usize, usize, usize) { + let f1 = (256. * self.width) as usize; + let f2 = (512. * self.width) as usize; + let f3 = (512. * self.width * self.ratio) as usize; + (f1, f2, f3) + } +} + +#[derive(Debug)] +struct Upsample { + scale_factor: usize, +} + +impl Upsample { + fn new(scale_factor: usize) -> Result { + Ok(Upsample { scale_factor }) + } +} + +impl Module for Upsample { + fn forward(&self, xs: &Tensor) -> Result { + let (_b_size, _channels, h, w) = xs.dims4()?; + xs.upsample_nearest2d(self.scale_factor * h, self.scale_factor * w) + } +} + +#[derive(Debug)] +struct ConvBlock { + conv: Conv2d, +} + +impl ConvBlock { + fn load( + vb: VarBuilder, + c1: usize, + c2: usize, + k: usize, + stride: usize, + padding: Option, + ) -> Result { + let padding = padding.unwrap_or(k / 2); + let cfg = Conv2dConfig { + padding, + stride, + groups: 1, + dilation: 1, + cudnn_fwd_algo: None, + }; + let bn = batch_norm(c2, 1e-3, vb.pp("bn"))?; + let conv = conv2d_no_bias(c1, c2, k, cfg, vb.pp("conv"))?.absorb_bn(&bn)?; + Ok(Self { conv }) + } +} + +impl Module for ConvBlock { + fn forward(&self, xs: &Tensor) -> Result { + let xs = self.conv.forward(xs)?; + candle_nn::ops::silu(&xs) + } +} + +#[derive(Debug)] +struct Bottleneck { + cv1: ConvBlock, + cv2: ConvBlock, + residual: bool, +} + +impl Bottleneck { + fn load(vb: VarBuilder, c1: usize, c2: usize, shortcut: bool) -> Result { + let channel_factor = 1.; + let c_ = (c2 as f64 * channel_factor) as usize; + let cv1 = ConvBlock::load(vb.pp("cv1"), c1, c_, 3, 1, None)?; + let cv2 = ConvBlock::load(vb.pp("cv2"), c_, c2, 3, 1, None)?; + let residual = c1 == c2 && shortcut; + Ok(Self { cv1, cv2, residual }) + } +} + +impl Module for Bottleneck { + fn forward(&self, xs: &Tensor) -> Result { + let ys = self.cv2.forward(&self.cv1.forward(xs)?)?; + if self.residual { xs + ys } else { Ok(ys) } + } +} + +#[derive(Debug)] +struct C2f { + cv1: ConvBlock, + cv2: ConvBlock, + bottleneck: Vec, +} + +impl C2f { + fn load(vb: VarBuilder, c1: usize, c2: usize, n: usize, shortcut: bool) -> Result { + let c = (c2 as f64 * 0.5) as usize; + let cv1 = ConvBlock::load(vb.pp("cv1"), c1, 2 * c, 1, 1, None)?; + let cv2 = ConvBlock::load(vb.pp("cv2"), (2 + n) * c, c2, 1, 1, None)?; + let mut bottleneck = Vec::with_capacity(n); + for idx in 0..n { + let b = Bottleneck::load(vb.pp(format!("bottleneck.{idx}")), c, c, shortcut)?; + bottleneck.push(b) + } + Ok(Self { + cv1, + cv2, + bottleneck, + }) + } +} + +impl Module for C2f { + fn forward(&self, xs: &Tensor) -> Result { + let ys = self.cv1.forward(xs)?; + let mut ys = ys.chunk(2, 1)?; + for m in self.bottleneck.iter() { + ys.push(m.forward(ys.last().unwrap())?) + } + let zs = Tensor::cat(ys.as_slice(), 1)?; + self.cv2.forward(&zs) + } +} + +#[derive(Debug)] +struct Sppf { + cv1: ConvBlock, + cv2: ConvBlock, + k: usize, +} + +impl Sppf { + fn load(vb: VarBuilder, c1: usize, c2: usize, k: usize) -> Result { + let c_ = c1 / 2; + let cv1 = ConvBlock::load(vb.pp("cv1"), c1, c_, 1, 1, None)?; + let cv2 = ConvBlock::load(vb.pp("cv2"), c_ * 4, c2, 1, 1, None)?; + Ok(Self { cv1, cv2, k }) + } +} + +impl Module for Sppf { + fn forward(&self, xs: &Tensor) -> Result { + let xs = self.cv1.forward(xs)?; + let xs2 = xs + .pad_with_zeros(2, self.k / 2, self.k / 2)? + .pad_with_zeros(3, self.k / 2, self.k / 2)? + .max_pool2d_with_stride(self.k, 1)?; + let xs3 = xs2 + .pad_with_zeros(2, self.k / 2, self.k / 2)? + .pad_with_zeros(3, self.k / 2, self.k / 2)? + .max_pool2d_with_stride(self.k, 1)?; + let xs4 = xs3 + .pad_with_zeros(2, self.k / 2, self.k / 2)? + .pad_with_zeros(3, self.k / 2, self.k / 2)? + .max_pool2d_with_stride(self.k, 1)?; + self.cv2.forward(&Tensor::cat(&[&xs, &xs2, &xs3, &xs4], 1)?) + } +} + +#[derive(Debug)] +struct Dfl { + conv: Conv2d, + num_classes: usize, +} + +impl Dfl { + fn load(vb: VarBuilder, num_classes: usize) -> Result { + let conv = conv2d_no_bias(num_classes, 1, 1, Default::default(), vb.pp("conv"))?; + Ok(Self { conv, num_classes }) + } +} + +impl Module for Dfl { + fn forward(&self, xs: &Tensor) -> Result { + let (b_sz, _channels, anchors) = xs.dims3()?; + let xs = xs + .reshape((b_sz, 4, self.num_classes, anchors))? + .transpose(2, 1)?; + let xs = candle_nn::ops::softmax(&xs, 1)?; + self.conv.forward(&xs)?.reshape((b_sz, 4, anchors)) + } +} + +#[derive(Debug)] +struct DarkNet { + b1_0: ConvBlock, + b1_1: ConvBlock, + b2_0: C2f, + b2_1: ConvBlock, + b2_2: C2f, + b3_0: ConvBlock, + b3_1: C2f, + b4_0: ConvBlock, + b4_1: C2f, + b5: Sppf, +} + +impl DarkNet { + fn load(vb: VarBuilder, m: Multiples) -> Result { + let (w, r, d) = (m.width, m.ratio, m.depth); + let b1_0 = ConvBlock::load(vb.pp("b1.0"), 3, (64. * w) as usize, 3, 2, Some(1))?; + let b1_1 = ConvBlock::load( + vb.pp("b1.1"), + (64. * w) as usize, + (128. * w) as usize, + 3, + 2, + Some(1), + )?; + let b2_0 = C2f::load( + vb.pp("b2.0"), + (128. * w) as usize, + (128. * w) as usize, + (3. * d).round() as usize, + true, + )?; + let b2_1 = ConvBlock::load( + vb.pp("b2.1"), + (128. * w) as usize, + (256. * w) as usize, + 3, + 2, + Some(1), + )?; + let b2_2 = C2f::load( + vb.pp("b2.2"), + (256. * w) as usize, + (256. * w) as usize, + (6. * d).round() as usize, + true, + )?; + let b3_0 = ConvBlock::load( + vb.pp("b3.0"), + (256. * w) as usize, + (512. * w) as usize, + 3, + 2, + Some(1), + )?; + let b3_1 = C2f::load( + vb.pp("b3.1"), + (512. * w) as usize, + (512. * w) as usize, + (6. * d).round() as usize, + true, + )?; + let b4_0 = ConvBlock::load( + vb.pp("b4.0"), + (512. * w) as usize, + (512. * w * r) as usize, + 3, + 2, + Some(1), + )?; + let b4_1 = C2f::load( + vb.pp("b4.1"), + (512. * w * r) as usize, + (512. * w * r) as usize, + (3. * d).round() as usize, + true, + )?; + let b5 = Sppf::load( + vb.pp("b5.0"), + (512. * w * r) as usize, + (512. * w * r) as usize, + 5, + )?; + Ok(Self { + b1_0, + b1_1, + b2_0, + b2_1, + b2_2, + b3_0, + b3_1, + b4_0, + b4_1, + b5, + }) + } + + fn forward(&self, xs: &Tensor) -> Result<(Tensor, Tensor, Tensor)> { + let x1 = self.b1_1.forward(&self.b1_0.forward(xs)?)?; + let x2 = self + .b2_2 + .forward(&self.b2_1.forward(&self.b2_0.forward(&x1)?)?)?; + let x3 = self.b3_1.forward(&self.b3_0.forward(&x2)?)?; + let x4 = self.b4_1.forward(&self.b4_0.forward(&x3)?)?; + let x5 = self.b5.forward(&x4)?; + Ok((x2, x3, x5)) + } +} + +#[derive(Debug)] +struct YoloV8Neck { + up: Upsample, + n1: C2f, + n2: C2f, + n3: ConvBlock, + n4: C2f, + n5: ConvBlock, + n6: C2f, +} + +impl YoloV8Neck { + fn load(vb: VarBuilder, m: Multiples) -> Result { + let up = Upsample::new(2)?; + let (w, r, d) = (m.width, m.ratio, m.depth); + let n = (3. * d).round() as usize; + let n1 = C2f::load( + vb.pp("n1"), + (512. * w * (1. + r)) as usize, + (512. * w) as usize, + n, + false, + )?; + let n2 = C2f::load( + vb.pp("n2"), + (768. * w) as usize, + (256. * w) as usize, + n, + false, + )?; + let n3 = ConvBlock::load( + vb.pp("n3"), + (256. * w) as usize, + (256. * w) as usize, + 3, + 2, + Some(1), + )?; + let n4 = C2f::load( + vb.pp("n4"), + (768. * w) as usize, + (512. * w) as usize, + n, + false, + )?; + let n5 = ConvBlock::load( + vb.pp("n5"), + (512. * w) as usize, + (512. * w) as usize, + 3, + 2, + Some(1), + )?; + let n6 = C2f::load( + vb.pp("n6"), + (512. * w * (1. + r)) as usize, + (512. * w * r) as usize, + n, + false, + )?; + Ok(Self { + up, + n1, + n2, + n3, + n4, + n5, + n6, + }) + } + + fn forward(&self, p3: &Tensor, p4: &Tensor, p5: &Tensor) -> Result<(Tensor, Tensor, Tensor)> { + let x = self + .n1 + .forward(&Tensor::cat(&[&self.up.forward(p5)?, p4], 1)?)?; + let head_1 = self + .n2 + .forward(&Tensor::cat(&[&self.up.forward(&x)?, p3], 1)?)?; + let head_2 = self + .n4 + .forward(&Tensor::cat(&[&self.n3.forward(&head_1)?, &x], 1)?)?; + let head_3 = self + .n6 + .forward(&Tensor::cat(&[&self.n5.forward(&head_2)?, p5], 1)?)?; + Ok((head_1, head_2, head_3)) + } +} + +struct DetectionHeadOut { + pred: Tensor, + anchors: Tensor, + strides: Tensor, +} + +#[derive(Debug)] +struct DetectionHead { + dfl: Dfl, + cv2: [(ConvBlock, ConvBlock, Conv2d); 3], + cv3: [(ConvBlock, ConvBlock, Conv2d); 3], + ch: usize, + no: usize, +} + +impl DetectionHead { + fn load(vb: VarBuilder, nc: usize, filters: (usize, usize, usize)) -> Result { + let ch = 16; + let dfl = Dfl::load(vb.pp("dfl"), ch)?; + let c1 = usize::max(filters.0, nc); + let c2 = usize::max(filters.0 / 4, ch * 4); + let cv3 = [ + Self::load_cv3(vb.pp("cv3.0"), c1, nc, filters.0)?, + Self::load_cv3(vb.pp("cv3.1"), c1, nc, filters.1)?, + Self::load_cv3(vb.pp("cv3.2"), c1, nc, filters.2)?, + ]; + let cv2 = [ + Self::load_cv2(vb.pp("cv2.0"), c2, ch, filters.0)?, + Self::load_cv2(vb.pp("cv2.1"), c2, ch, filters.1)?, + Self::load_cv2(vb.pp("cv2.2"), c2, ch, filters.2)?, + ]; + let no = nc + ch * 4; + Ok(Self { + dfl, + cv2, + cv3, + ch, + no, + }) + } + + fn load_cv3( + vb: VarBuilder, + c1: usize, + nc: usize, + filter: usize, + ) -> Result<(ConvBlock, ConvBlock, Conv2d)> { + let block0 = ConvBlock::load(vb.pp("0"), filter, c1, 3, 1, None)?; + let block1 = ConvBlock::load(vb.pp("1"), c1, c1, 3, 1, None)?; + let conv = conv2d(c1, nc, 1, Default::default(), vb.pp("2"))?; + Ok((block0, block1, conv)) + } + + fn load_cv2( + vb: VarBuilder, + c2: usize, + ch: usize, + filter: usize, + ) -> Result<(ConvBlock, ConvBlock, Conv2d)> { + let block0 = ConvBlock::load(vb.pp("0"), filter, c2, 3, 1, None)?; + let block1 = ConvBlock::load(vb.pp("1"), c2, c2, 3, 1, None)?; + let conv = conv2d(c2, 4 * ch, 1, Default::default(), vb.pp("2"))?; + Ok((block0, block1, conv)) + } + + fn forward(&self, xs0: &Tensor, xs1: &Tensor, xs2: &Tensor) -> Result { + let forward_cv = |xs: &Tensor, i: usize| { + let xs_2 = self.cv2[i].0.forward(xs)?; + let xs_2 = self.cv2[i].1.forward(&xs_2)?; + let xs_2 = self.cv2[i].2.forward(&xs_2)?; + + let xs_3 = self.cv3[i].0.forward(xs)?; + let xs_3 = self.cv3[i].1.forward(&xs_3)?; + let xs_3 = self.cv3[i].2.forward(&xs_3)?; + Tensor::cat(&[&xs_2, &xs_3], 1) + }; + let xs0 = forward_cv(xs0, 0)?; + let xs1 = forward_cv(xs1, 1)?; + let xs2 = forward_cv(xs2, 2)?; + + let (anchors, strides) = make_anchors(&xs0, &xs1, &xs2, (8, 16, 32), 0.5)?; + let anchors = anchors.transpose(0, 1)?.unsqueeze(0)?; + let strides = strides.transpose(0, 1)?; + + let reshape = |xs: &Tensor| { + let d = xs.dim(0)?; + let el = xs.elem_count(); + xs.reshape((d, self.no, el / (d * self.no))) + }; + let ys0 = reshape(&xs0)?; + let ys1 = reshape(&xs1)?; + let ys2 = reshape(&xs2)?; + + let x_cat = Tensor::cat(&[ys0, ys1, ys2], 2)?; + let box_ = x_cat.i((.., ..self.ch * 4))?; + let cls = x_cat.i((.., self.ch * 4..))?; + + let dbox = dist2bbox(&self.dfl.forward(&box_)?, &anchors)?; + let dbox = dbox.broadcast_mul(&strides)?; + let pred = Tensor::cat(&[dbox, candle_nn::ops::sigmoid(&cls)?], 1)?; + Ok(DetectionHeadOut { + pred, + anchors, + strides, + }) + } +} + +#[derive(Debug)] +struct PoseHead { + detect: DetectionHead, + cv4: [(ConvBlock, ConvBlock, Conv2d); 3], + kpt: (usize, usize), +} + +impl PoseHead { + fn load( + vb: VarBuilder, + nc: usize, + kpt: (usize, usize), + filters: (usize, usize, usize), + ) -> Result { + let detect = DetectionHead::load(vb.clone(), nc, filters)?; + let nk = kpt.0 * kpt.1; + let c4 = usize::max(filters.0 / 4, nk); + let cv4 = [ + Self::load_cv4(vb.pp("cv4.0"), c4, nk, filters.0)?, + Self::load_cv4(vb.pp("cv4.1"), c4, nk, filters.1)?, + Self::load_cv4(vb.pp("cv4.2"), c4, nk, filters.2)?, + ]; + Ok(Self { detect, cv4, kpt }) + } + + fn load_cv4( + vb: VarBuilder, + c1: usize, + nc: usize, + filter: usize, + ) -> Result<(ConvBlock, ConvBlock, Conv2d)> { + let block0 = ConvBlock::load(vb.pp("0"), filter, c1, 3, 1, None)?; + let block1 = ConvBlock::load(vb.pp("1"), c1, c1, 3, 1, None)?; + let conv = conv2d(c1, nc, 1, Default::default(), vb.pp("2"))?; + Ok((block0, block1, conv)) + } + + fn forward(&self, xs0: &Tensor, xs1: &Tensor, xs2: &Tensor) -> Result { + let d = self.detect.forward(xs0, xs1, xs2)?; + let forward_cv = |xs: &Tensor, i: usize| { + let (b_sz, _, h, w) = xs.dims4()?; + let xs = self.cv4[i].0.forward(xs)?; + let xs = self.cv4[i].1.forward(&xs)?; + let xs = self.cv4[i].2.forward(&xs)?; + xs.reshape((b_sz, self.kpt.0 * self.kpt.1, h * w)) + }; + let xs0 = forward_cv(xs0, 0)?; + let xs1 = forward_cv(xs1, 1)?; + let xs2 = forward_cv(xs2, 2)?; + let xs = Tensor::cat(&[xs0, xs1, xs2], D::Minus1)?; + let (b_sz, _nk, hw) = xs.dims3()?; + let xs = xs.reshape((b_sz, self.kpt.0, self.kpt.1, hw))?; + + let ys01 = ((xs.i((.., .., 0..2))? * 2.)?.broadcast_add(&d.anchors)? - 0.5)? + .broadcast_mul(&d.strides)?; + let ys2 = candle_nn::ops::sigmoid(&xs.i((.., .., 2..3))?)?; + let ys = Tensor::cat(&[ys01, ys2], 2)?.flatten(1, 2)?; + Tensor::cat(&[d.pred, ys], 1) + } +} + +fn make_anchors( + xs0: &Tensor, + xs1: &Tensor, + xs2: &Tensor, + (s0, s1, s2): (usize, usize, usize), + grid_cell_offset: f64, +) -> Result<(Tensor, Tensor)> { + let dev = xs0.device(); + let mut anchor_points = vec![]; + let mut stride_tensor = vec![]; + for (xs, stride) in [(xs0, s0), (xs1, s1), (xs2, s2)] { + let (_, _, h, w) = xs.dims4()?; + let sx = (Tensor::arange(0, w as u32, dev)?.to_dtype(DType::F32)? + grid_cell_offset)?; + let sy = (Tensor::arange(0, h as u32, dev)?.to_dtype(DType::F32)? + grid_cell_offset)?; + let sx = sx + .reshape((1, sx.elem_count()))? + .repeat((h, 1))? + .flatten_all()?; + let sy = sy + .reshape((sy.elem_count(), 1))? + .repeat((1, w))? + .flatten_all()?; + anchor_points.push(Tensor::stack(&[&sx, &sy], D::Minus1)?); + stride_tensor.push((Tensor::ones(h * w, DType::F32, dev)? * stride as f64)?); + } + let anchor_points = Tensor::cat(anchor_points.as_slice(), 0)?; + let stride_tensor = Tensor::cat(stride_tensor.as_slice(), 0)?.unsqueeze(1)?; + Ok((anchor_points, stride_tensor)) +} + +fn dist2bbox(distance: &Tensor, anchor_points: &Tensor) -> Result { + let chunks = distance.chunk(2, 1)?; + let lt = &chunks[0]; + let rb = &chunks[1]; + let x1y1 = anchor_points.sub(lt)?; + let x2y2 = anchor_points.add(rb)?; + let c_xy = ((&x1y1 + &x2y2)? * 0.5)?; + let wh = (&x2y2 - &x1y1)?; + Tensor::cat(&[c_xy, wh], 1) +} + +/// YOLOv8 Pose estimation model +#[derive(Debug)] +pub struct YoloV8Pose { + net: DarkNet, + fpn: YoloV8Neck, + head: PoseHead, +} + +impl YoloV8Pose { + /// Load model weights from a VarBuilder + /// + /// # Arguments + /// * `vb` - Variable builder with loaded weights + /// * `m` - Model size multipliers + /// * `num_classes` - Number of object classes (1 for pose) + /// * `kpt` - Keypoint configuration (num_keypoints, values_per_keypoint) + pub fn load( + vb: VarBuilder, + m: Multiples, + num_classes: usize, + kpt: (usize, usize), + ) -> Result { + let net = DarkNet::load(vb.pp("net"), m)?; + let fpn = YoloV8Neck::load(vb.pp("fpn"), m)?; + let head = PoseHead::load(vb.pp("head"), num_classes, kpt, m.filters())?; + Ok(Self { net, fpn, head }) + } +} + +impl Module for YoloV8Pose { + fn forward(&self, xs: &Tensor) -> Result { + let (xs1, xs2, xs3) = self.net.forward(xs)?; + let (xs1, xs2, xs3) = self.fpn.forward(&xs1, &xs2, &xs3)?; + self.head.forward(&xs1, &xs2, &xs3) + } +} diff --git a/copper-rs-pose/app/src/yolo/postprocess.rs b/copper-rs-pose/app/src/yolo/postprocess.rs new file mode 100644 index 0000000..249d016 --- /dev/null +++ b/copper-rs-pose/app/src/yolo/postprocess.rs @@ -0,0 +1,220 @@ +//! Postprocessing for YOLOv8 pose predictions +//! +//! Handles decoding model output, non-maximum suppression, and +//! conversion to CuPoses payload format. + +use crate::payloads::{CuPoses, Keypoint, NUM_KEYPOINTS, Pose}; +use candle_core::{Device, IndexOp, Tensor}; + +/// Process raw model predictions into structured pose data +/// +/// # Arguments +/// * `predictions` - Raw model output tensor of shape (pred_size, num_predictions) +/// * `img_width` - Original image width (for coordinate scaling) +/// * `img_height` - Original image height (for coordinate scaling) +/// * `model_width` - Model input width used during preprocessing +/// * `model_height` - Model input height used during preprocessing +/// * `conf_threshold` - Minimum confidence to keep a detection +/// * `iou_threshold` - IoU threshold for NMS +pub fn process_predictions( + predictions: &Tensor, + img_width: u32, + img_height: u32, + model_width: usize, + model_height: usize, + conf_threshold: f32, + iou_threshold: f32, +) -> CuPoses { + let mut poses = CuPoses::new(); + + // Move to CPU for processing + let Ok(predictions) = predictions.to_device(&Device::Cpu) else { + return poses; + }; + + // Expected shape: (56, num_preds) where 56 = 4 (bbox) + 1 (conf) + 51 (17*3 keypoints) + let Ok((pred_size, num_preds)) = predictions.dims2() else { + return poses; + }; + + // Validate prediction size: 4 + 1 + 17*3 = 56 + if pred_size != 4 + 1 + NUM_KEYPOINTS * 3 { + return poses; + } + + let w_ratio = img_width as f32 / model_width as f32; + let h_ratio = img_height as f32 / model_height as f32; + + // Collect candidate detections + let mut candidates: Vec = Vec::new(); + + for idx in 0..num_preds { + let Ok(pred) = predictions.i((.., idx)) else { + continue; + }; + + let Ok(pred_vec) = pred.to_vec1() else { + continue; + }; + + let confidence = pred_vec[4]; + if confidence < conf_threshold { + continue; + } + + // Extract bbox (center x, center y, width, height) + let cx = pred_vec[0]; + let cy = pred_vec[1]; + let w = pred_vec[2]; + let h = pred_vec[3]; + + // Convert to corner format for NMS + let x1 = cx - w / 2.0; + let y1 = cy - h / 2.0; + let x2 = cx + w / 2.0; + let y2 = cy + h / 2.0; + + // Extract keypoints (17 keypoints, each with x, y, confidence) + let mut keypoints = [Keypoint::default(); NUM_KEYPOINTS]; + for (i, kp) in keypoints.iter_mut().enumerate().take(NUM_KEYPOINTS) { + let base = 5 + i * 3; + *kp = Keypoint::new(pred_vec[base], pred_vec[base + 1], pred_vec[base + 2]); + } + + candidates.push(PoseCandidate { + x1, + y1, + x2, + y2, + confidence, + keypoints, + }); + } + + // Sort by confidence descending + candidates.sort_by(|a, b| { + b.confidence + .partial_cmp(&a.confidence) + .unwrap_or(std::cmp::Ordering::Equal) + }); + + // Apply NMS + let mut keep = vec![true; candidates.len()]; + for i in 0..candidates.len() { + if !keep[i] { + continue; + } + for j in (i + 1)..candidates.len() { + if !keep[j] { + continue; + } + let iou = compute_iou(&candidates[i], &candidates[j]); + if iou > iou_threshold { + keep[j] = false; + } + } + } + + // Convert to CuPoses with coordinate scaling + for (i, candidate) in candidates.into_iter().enumerate() { + if !keep[i] { + continue; + } + + // Scale bbox back to original image coordinates + let bbox = [ + (candidate.x1 + candidate.x2) / 2.0 * w_ratio, // cx + (candidate.y1 + candidate.y2) / 2.0 * h_ratio, // cy + (candidate.x2 - candidate.x1) * w_ratio, // w + (candidate.y2 - candidate.y1) * h_ratio, // h + ]; + + // Scale keypoints back to original image coordinates + let mut scaled_keypoints = [Keypoint::default(); NUM_KEYPOINTS]; + for (j, kp) in candidate.keypoints.iter().enumerate() { + scaled_keypoints[j] = Keypoint::new(kp.x * w_ratio, kp.y * h_ratio, kp.confidence); + } + + let pose = Pose { + bbox, + confidence: candidate.confidence, + keypoints: scaled_keypoints, + }; + + if poses.push(pose).is_err() { + // Reached maximum poses capacity + break; + } + } + + poses +} + +/// Internal struct for NMS processing +struct PoseCandidate { + x1: f32, + y1: f32, + x2: f32, + y2: f32, + confidence: f32, + keypoints: [Keypoint; NUM_KEYPOINTS], +} + +/// Compute Intersection over Union between two bounding boxes +fn compute_iou(a: &PoseCandidate, b: &PoseCandidate) -> f32 { + let x1 = a.x1.max(b.x1); + let y1 = a.y1.max(b.y1); + let x2 = a.x2.min(b.x2); + let y2 = a.y2.min(b.y2); + + let intersection = (x2 - x1).max(0.0) * (y2 - y1).max(0.0); + + let area_a = (a.x2 - a.x1) * (a.y2 - a.y1); + let area_b = (b.x2 - b.x1) * (b.y2 - b.y1); + let union = area_a + area_b - intersection; + + if union > 0.0 { + intersection / union + } else { + 0.0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_iou_same_box() { + let a = PoseCandidate { + x1: 0.0, + y1: 0.0, + x2: 10.0, + y2: 10.0, + confidence: 0.9, + keypoints: [Keypoint::default(); NUM_KEYPOINTS], + }; + assert!((compute_iou(&a, &a) - 1.0).abs() < 1e-6); + } + + #[test] + fn test_iou_no_overlap() { + let a = PoseCandidate { + x1: 0.0, + y1: 0.0, + x2: 10.0, + y2: 10.0, + confidence: 0.9, + keypoints: [Keypoint::default(); NUM_KEYPOINTS], + }; + let b = PoseCandidate { + x1: 20.0, + y1: 20.0, + x2: 30.0, + y2: 30.0, + confidence: 0.8, + keypoints: [Keypoint::default(); NUM_KEYPOINTS], + }; + assert!((compute_iou(&a, &b)).abs() < 1e-6); + } +} diff --git a/copper-rs-pose/app/src/yolo/preprocess.rs b/copper-rs-pose/app/src/yolo/preprocess.rs new file mode 100644 index 0000000..2c32211 --- /dev/null +++ b/copper-rs-pose/app/src/yolo/preprocess.rs @@ -0,0 +1,143 @@ +//! Image preprocessing for YOLOv8 inference +//! +//! Handles conversion from V4L camera formats (YUYV, NV12, etc.) to +//! the RGB tensor format expected by the model. + +use crate::image::{bgr_to_rgb, nv12_to_rgb, yuyv_to_rgb}; +use candle_core::{DType, Device, Result, Tensor}; +use cu_sensor_payloads::CuImage; + +/// Target input size for the model (width and height) +pub const MODEL_INPUT_SIZE: usize = 640; + +/// Preprocess a CuImage for YOLO inference +/// +/// Steps: +/// 1. Convert from camera format (YUYV/NV12) to RGB +/// 2. Resize to model input size with letterboxing +/// 3. Normalize to [0, 1] range +/// 4. Convert to tensor with shape (1, 3, H, W) +/// +/// Returns the tensor and the actual (width, height) used after scaling +pub fn preprocess_image( + image: &CuImage>, + device: &Device, +) -> Result<(Tensor, usize, usize)> { + let width = image.format.width as usize; + let height = image.format.height as usize; + let pixel_format = &image.format.pixel_format; + + // Convert to RGB based on pixel format + let rgb_data = image.buffer_handle.with_inner(|data| { + match pixel_format { + b"YUYV" => yuyv_to_rgb(data, width, height), + b"NV12" => nv12_to_rgb(data, width, height), + b"RGB3" | b"RGB " => data.to_vec(), // Already RGB + b"BGR3" | b"BGR " => bgr_to_rgb(data, width, height), + _ => { + // Fallback: assume grayscale or try to interpret as RGB + if data.len() == width * height * 3 { + data.to_vec() + } else if data.len() == width * height { + // Grayscale to RGB + data.iter().flat_map(|&g| [g, g, g]).collect() + } else { + // Unknown format, return zeros + vec![0u8; width * height * 3] + } + } + } + }); + + // Calculate resize dimensions maintaining aspect ratio + let (target_w, target_h) = calculate_resize_dims(width, height, MODEL_INPUT_SIZE); + + // Resize the image + let resized = resize_rgb(&rgb_data, width, height, target_w, target_h); + + // Create tensor: (H, W, 3) -> (3, H, W) -> (1, 3, H, W) + let tensor = Tensor::from_vec(resized, (target_h, target_w, 3), device)? + .permute((2, 0, 1))? + .unsqueeze(0)? + .to_dtype(DType::F32)?; + + // Normalize to [0, 1] + let tensor = (tensor * (1.0 / 255.0))?; + + Ok((tensor, target_w, target_h)) +} + +/// Calculate resize dimensions to fit within target size while maintaining aspect ratio +/// Dimensions are rounded down to multiples of 32 for YOLO compatibility +fn calculate_resize_dims(width: usize, height: usize, target: usize) -> (usize, usize) { + if width > height { + let new_h = (height * target) / width; + (target, (new_h / 32) * 32) + } else { + let new_w = (width * target) / height; + ((new_w / 32) * 32, target) + } +} + +/// Simple bilinear resize for RGB images +fn resize_rgb(data: &[u8], src_w: usize, src_h: usize, dst_w: usize, dst_h: usize) -> Vec { + let mut result = Vec::with_capacity(dst_w * dst_h * 3); + + let x_ratio = src_w as f32 / dst_w as f32; + let y_ratio = src_h as f32 / dst_h as f32; + + for y in 0..dst_h { + for x in 0..dst_w { + let src_x = x as f32 * x_ratio; + let src_y = y as f32 * y_ratio; + + let x0 = src_x.floor() as usize; + let y0 = src_y.floor() as usize; + let x1 = (x0 + 1).min(src_w - 1); + let y1 = (y0 + 1).min(src_h - 1); + + let x_frac = src_x - x0 as f32; + let y_frac = src_y - y0 as f32; + + for c in 0..3 { + let p00 = data[(y0 * src_w + x0) * 3 + c] as f32; + let p01 = data[(y0 * src_w + x1) * 3 + c] as f32; + let p10 = data[(y1 * src_w + x0) * 3 + c] as f32; + let p11 = data[(y1 * src_w + x1) * 3 + c] as f32; + + let top = p00 * (1.0 - x_frac) + p01 * x_frac; + let bottom = p10 * (1.0 - x_frac) + p11 * x_frac; + let value = top * (1.0 - y_frac) + bottom * y_frac; + + result.push(value.clamp(0.0, 255.0) as u8); + } + } + } + + result +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_resize_dims() { + // Landscape image + let (w, h) = calculate_resize_dims(1920, 1080, 640); + assert_eq!(w, 640); + assert!(h <= 640); + assert_eq!(h % 32, 0); + + // Portrait image + let (w, h) = calculate_resize_dims(1080, 1920, 640); + assert!(w <= 640); + assert_eq!(h, 640); + assert_eq!(w % 32, 0); + + // Square image + let (w, h) = calculate_resize_dims(640, 640, 640); + assert_eq!(w, 640); + assert_eq!(h, 640); + } +} diff --git a/copper-rs-pose/avocado.yaml b/copper-rs-pose/avocado.yaml new file mode 100644 index 0000000..2ddb3d9 --- /dev/null +++ b/copper-rs-pose/avocado.yaml @@ -0,0 +1,117 @@ +cli_requirement: ">=0.41.0" + +default_target: "raspberrypi5" + +supported_targets: + - raspberrypi5 + - imx8mp-evk + - jetson-orin-nano + +distro: + release: 2026 + channel: next + +runtimes: + dev: + packages: + avocado-runtime: '*' + extensions: + - copper-rs-pose + - avocado-ext-dev + - avocado-ext-sshd-dev + - avocado-bsp-{{ avocado.target }} + +extensions: + avocado-ext-dev: + source: + type: package + version: '*' + + avocado-ext-sshd-dev: + source: + type: package + version: '*' + + avocado-bsp-{{ avocado.target }}: + source: + type: package + version: '*' + + copper-rs-pose: + version: 0.1.0 + + overlay: overlay + + enable_services: + - copper-rs-pose.service + + on_merge: + # Load the /dev/copper-camera rule from the overlay. + - udevadm control --reload + - udevadm trigger --subsystem-match=video4linux --action=add + - systemctl restart --no-block copper-rs-pose.service + + on_unmerge: + - systemctl stop copper-rs-pose.service + + packages: + copper-rs-pose-app: + compile: copper-rs-pose-app + install: copper-install.sh + + # GStreamer: v4l2src -> videoconvert -> videoscale -> appsink + gstreamer1.0: '*' + gstreamer1.0-plugins-base-videoconvertscale: '*' + gstreamer1.0-plugins-base-app: '*' + gstreamer1.0-plugins-good-video4linux2: '*' + kernel-module-uvcvideo: '*' + v4l-utils: '*' + + sdk: + packages: + nativesdk-binutils: '*' + nativesdk-cargo: '*' + nativesdk-gcc: '*' + nativesdk-glibc-dev: '*' + nativesdk-libgcc-dev: '*' + nativesdk-rust: '*' + nativesdk-pkgconfig: '*' + packagegroup-rust-cross-canadian-avocado-{{ avocado.target }}: '*' + +rootfs: + permissions: dev + +initramfs: + permissions: dev + +# NOT FOR PRODUCTION: the `dev` profile sets an empty root password and is +# referenced by rootfs/initramfs above. Define additional profiles with real +# users, groups, and hashed passwords, then point rootfs/initramfs at them via +# `permissions: `. +permissions: + dev: + users: + root: + password: "" + +sdk: + image: "docker.io/avocadolinux/sdk:{{ config.distro.release }}" + + container_args: + - --network=host + - --privileged + - -v /dev:/dev + - -v /sys:/sys + + compile: + copper-rs-pose-app: + compile: copper-compile.sh + packages: + libstd-rs: '*' + libstd-rs-dev: '*' + # Headers and .pc files for gstreamer-sys / gstreamer-app-sys + gstreamer1.0-dev: '*' + gstreamer1.0-plugins-base-dev: '*' + + packages: + avocado-sdk-toolchain: '*' diff --git a/copper-rs-pose/copper-compile.sh b/copper-rs-pose/copper-compile.sh new file mode 100755 index 0000000..ef8c3f8 --- /dev/null +++ b/copper-rs-pose/copper-compile.sh @@ -0,0 +1,65 @@ +#!/bin/bash +set -e + +# Find the Rust target from RUST_TARGET_PATH +for json_file in "$RUST_TARGET_PATH"/*.json; do + if [ -f "$json_file" ]; then + json_name=$(basename "$json_file" .json) + if [[ "$json_name" == "${OECORE_TARGET_ARCH}-"* ]]; then + RUST_TARGET="$json_name" + break + fi + fi +done + +if [ -z "$RUST_TARGET" ]; then + echo "Error: Could not find Rust target for $OECORE_TARGET_ARCH" + exit 1 +fi + +echo "Compiling copper-rs-pose for target: $RUST_TARGET" + +# Keep the crate cache and the build output in the SDK volume +# ($AVOCADO_BUILD_DIR). The project directory is a host file share, and +# a cargo build of this size on it is very slow. +export CARGO_HOME="$AVOCADO_BUILD_DIR/cargo-home" +export CARGO_TARGET_DIR="$AVOCADO_BUILD_DIR/target" + +# YOLOv8n-pose weights (Ultralytics, AGPL-3.0), converted for Candle. +# Pinned to one commit and examined with sha256. Downloaded once. +MODEL="$AVOCADO_BUILD_DIR/yolov8n-pose.safetensors" +MODEL_URL="https://huggingface.co/lmz/candle-yolo-v8/resolve/be388c6fab95ae3035a039070e1b883b9c5a1325/yolov8n-pose.safetensors" +MODEL_SHA256="08c76047b41744c027c8150e81d1dbbd94f996656cf5be266491367ae7fad072" +if ! echo "$MODEL_SHA256 $MODEL" | sha256sum -c --status 2>/dev/null; then + echo "Downloading model: $MODEL_URL" + curl -fL --retry 3 -o "$MODEL.part" "$MODEL_URL" + echo "$MODEL_SHA256 $MODEL.part" | sha256sum -c - + mv "$MODEL.part" "$MODEL" +fi + +cd app + +# Clear any rustflags that might cause conflicts with our .cargo/config.toml +unset RUSTFLAGS +unset CARGO_BUILD_RUSTFLAGS +# Clear target-specific rustflags for all possible targets +for var in $(env | grep -o 'CARGO_TARGET_[A-Z0-9_]*_RUSTFLAGS'); do + unset "$var" +done + +# Remove any existing config that might conflict +rm -rf .cargo + +# Create config.toml with cross-compilation settings +mkdir -p .cargo +cat > .cargo/config.toml << EOF +[target.$RUST_TARGET] +rustflags = ["--sysroot=$SDKTARGETSYSROOT/usr", "-C", "link-arg=--sysroot=$SDKTARGETSYSROOT"] +EOF + +# gstreamer-sys finds the target gstreamer through pkg-config in the SDK sysroot. +export PKG_CONFIG_ALLOW_CROSS=1 + +# Copper declares rust-version 1.95. The SDK rust is older, and the code builds +# with it. The exact pins in Cargo.toml keep this bypass stable. +cargo build --release --locked --ignore-rust-version --target "$RUST_TARGET" diff --git a/copper-rs-pose/copper-install.sh b/copper-rs-pose/copper-install.sh new file mode 100755 index 0000000..561ee8b --- /dev/null +++ b/copper-rs-pose/copper-install.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -e + +# Find the Rust target from RUST_TARGET_PATH +for json_file in "$RUST_TARGET_PATH"/*.json; do + if [ -f "$json_file" ]; then + json_name=$(basename "$json_file" .json) + if [[ "$json_name" == "${OECORE_TARGET_ARCH}-"* ]]; then + RUST_TARGET="$json_name" + break + fi + fi +done + +BINARY_PATH="$AVOCADO_BUILD_DIR/target/$RUST_TARGET/release/copper-rs-pose" + +if [ ! -f "$BINARY_PATH" ]; then + echo "Error: Binary not found at $BINARY_PATH" + exit 1 +fi + +echo "Installing copper-rs-pose into extension" +install -D -m 755 "$BINARY_PATH" "$AVOCADO_BUILD_EXT_SYSROOT/usr/bin/copper-rs-pose" +echo "Installed: $(file "$AVOCADO_BUILD_EXT_SYSROOT/usr/bin/copper-rs-pose")" + +install -D -m 644 "$AVOCADO_BUILD_DIR/yolov8n-pose.safetensors" \ + "$AVOCADO_BUILD_EXT_SYSROOT/usr/share/copper-rs-pose/yolov8n-pose.safetensors" + +# The binary links to gstreamer and glibc. The extension must supply these libraries. +"${READELF:-readelf}" -d "$BINARY_PATH" | grep NEEDED || true diff --git a/copper-rs-pose/getting_started.md b/copper-rs-pose/getting_started.md new file mode 100644 index 0000000..dfd7fa6 --- /dev/null +++ b/copper-rs-pose/getting_started.md @@ -0,0 +1,220 @@ +# Getting Started with Copper Human Pose + +This guide shows how to build the Copper human pose reference, put it on a device, and watch the poses on your laptop. The app is one Rust binary. It reads a USB camera, finds poses with YOLOv8n-pose on the CPU, and serves the results over Rerun on port 9876. + +## Prerequisites + +- macOS or Linux. On macOS, the Avocado CLI starts its own helper VM (avocado-vm) for the SDK. On Linux, Docker must be installed and running. +- The latest version of the [Avocado CLI](https://docs.peridio.com/guides/avocado-cli/overview) +- One of the supported devices: `raspberrypi5`, `imx8mp-evk` or `jetson-orin-nano` +- The media and cables to provision your device (SD card, USB cable, serial console adapter). See the [Support Matrix](https://docs.peridio.com/hardware/support-matrix). +- A USB (UVC) webcam. Most webcams that give YUYV video work. +- A network connection between the device and your laptop. Ethernet is better than Wi-Fi, because the device sends raw camera frames to the viewer. +- The Rerun viewer, version 0.34.1, on your laptop. Install it with one of these commands: + + ```bash + pip install rerun-sdk==0.34.1 + cargo install rerun-cli@0.34.1 --locked + ``` + + The viewer version must be the same as the version in the app. A different version does not connect. + +## Initialize + +Initialize a new project from the reference: + +```bash +avocado init --reference copper-rs-pose copper-pose +cd copper-pose +``` + +To use a target other than the default (`raspberrypi5`), add `--target`: + +```bash +avocado init --reference copper-rs-pose --target imx8mp-evk copper-pose +cd copper-pose +``` + +## Install + +Install the Rust toolchain and the packages for the device: + +```bash +avocado install -f +``` + +## Build + +Compile the app and build the runtime image: + +```bash +avocado build +``` + +The first build compiles about 700 Rust crates and takes some minutes. Later builds take less than 1 minute. For the details, see [How the build works](#how-the-build-works). + +## Deploy + +### Raspberry Pi 5 and NXP i.MX 8MP EVK + +Insert your SD card and provision: + +```bash +avocado provision -r dev --profile sd +``` + +Put the SD card into the device, connect the webcam and the network, and apply power. + +### NVIDIA Jetson Orin Nano + +```bash +avocado provision -r dev --profile tegraflash +``` + +Obey the USB disconnect and reconnect prompts during the flash process. Then connect the webcam and the network. + +### Update a device that you provisioned before + +When you change the code, you do not have to provision again. Build, then deploy to the running device: + +```bash +avocado build +avocado deploy -r dev -d +``` + +## Verify + +Log in as `root` with an empty password. The service starts automatically at boot. + +1. Make sure that the device found the webcam: + + ```bash + ls -l /dev/copper-camera + ``` + + This is a link to the video node of the USB camera, for example `/dev/copper-camera -> video1`. Connect only one USB camera. With two cameras, the link can go to either one. If the link is not there, see [Troubleshooting](#troubleshooting). + +2. Make sure that the service runs: + + ```bash + systemctl status copper-rs-pose + journalctl -u copper-rs-pose + ``` + + The status is `active (running)`. The journal has this line, which shows that the Rerun server is ready. You use this command in step 5. + + ``` + copper-rs-pose: Rerun server ready. On your laptop run: rerun --connect rerun+http://:9876/proxy + ``` + +3. Make sure that the Copper log is written: + + ```bash + ls -lh /var/lib/copper-rs-pose/ + ``` + + The directory has `human-pose_0.copper`. When a log file is full (256 MB), Copper starts `human-pose_1.copper`, then `human-pose_2.copper`, and more. Copper does not delete old files. Delete them when you need disk space. + +4. Get the IP address of the device: + + ```bash + ip a + ``` + +5. On your laptop, connect the viewer. Use the IP address from step 4: + + ```bash + rerun --version + rerun --connect rerun+http://:9876/proxy + ``` + + `rerun --version` must show 0.34.1. The viewer shows the `camera/image` view with the live camera image. When a person is in the camera image, the viewer shows a box, the keypoints and the skeleton lines on the person. + +Inference runs on the CPU. The frame rate is low, and it is lowest on the i.MX 8MP, which has Cortex-A53 cores. + +### See the Copper TUI + +The Copper console monitor shows the task graph and the timing of each task. It starts only when you run the app in a terminal. The service uses the camera and port 9876, so the command stops the service first. On your laptop, run: + +```bash +ssh -t root@ 'systemctl stop copper-rs-pose; copper-rs-pose' +``` + +Push `q` to stop the app. The app prints `copper-rs-pose: Exiting...` when it stops. Then start the service again: + +```bash +ssh root@ systemctl start copper-rs-pose +``` + +## Customize + +All app files are in `app/`. After a change, build and deploy again (see [Update a device that you provisioned before](#update-a-device-that-you-provisioned-before)). + +### Change the detection sensitivity + +In `app/copperconfig.ron`, change the `yolo` task: + +- `conf_threshold`: the minimum score for a person. Make it lower to find more people. +- `iou_threshold`: the overlap limit when two boxes are on the same person. + +### Change the camera resolution + +The width and height are in three places in `app/copperconfig.ron`. The three values must be the same: + +- The `pipeline` string of the `camera` task +- The `caps` string of the `camera` task +- The `width` and `height` of the `gst_to_image` task + +### Use a different camera + +The udev rule `overlay/usr/lib/udev/rules.d/70-copper-camera.rules` makes `/dev/copper-camera` for a USB camera. To use a different camera, change the rule, or change `device=` in the `pipeline` string. + +### Add a task to the graph + +A Copper app is a graph of tasks. Each task is a Rust type, and `copperconfig.ron` connects the tasks. To add a task: + +1. Write the task in `app/src/tasks/`, and export it from `app/src/tasks/mod.rs`. Use `rerun_viz.rs` as an example of a sink task. +2. Add the task to `tasks` in `app/copperconfig.ron`. +3. Add a line to `cnx` for each message that the task receives. + +For example, write a sink `PoseCounter` in `app/src/tasks/pose_counter.rs` with `type Input<'m> = input_msg!(CuPoses);`, and export it from `mod.rs`. Then add the task and its connection: + +```ron +(id: "counter", type: "tasks::PoseCounter"), +``` + +```ron +(src: "yolo", dst: "counter", msg: "payloads::CuPoses"), +``` + +The build examines the graph. If a message type does not agree with a task, the build fails. + +## How the build works + +The Install step installs the Rust cross-compilation toolchain (`nativesdk-rust`, `nativesdk-cargo`, `packagegroup-rust-cross-canadian-avocado-`). It also installs the GStreamer headers that the app links against (`gstreamer1.0-dev`, `gstreamer1.0-plugins-base-dev`) and the GStreamer plugins for the device. + +The build runs `copper-compile.sh` in the SDK container. The script does these steps: + +1. Finds the Rust target from `RUST_TARGET_PATH`. +2. Puts the cargo cache and the build output in `$AVOCADO_BUILD_DIR`. This directory is in the SDK volume, which is much faster than the project directory. +3. Downloads the YOLOv8n-pose weights (6.6 MB) from Hugging Face, pinned to one commit, and examines the sha256. If the file is already there, it does not download it again. +4. Writes `app/.cargo/config.toml` with the sysroot flags. +5. Runs `cargo build --release --locked --ignore-rust-version`. + +Copper declares Rust 1.95, and the SDK has Rust 1.94.1. The code builds with 1.94.1, so the script uses `--ignore-rust-version`. `Cargo.toml` pins the Copper crates to `=1.2.1`, and `Cargo.lock` pins all other crates. + +At build time, `build.rs` and the `#[copper_runtime]` macro read `app/copperconfig.ron` and make the task graph into Rust code. Thus a change to `copperconfig.ron` needs a new build. + +Then `copper-install.sh` copies the binary to `/usr/bin/copper-rs-pose` and the weights to `/usr/share/copper-rs-pose/` in the extension. + +## Troubleshooting + +- **The service restarts every 5 seconds.** The app cannot open the camera. Make sure that `/dev/copper-camera` is there. If a camera is connected later, the service starts it automatically. +- **`/dev/copper-camera` is not there.** Find your camera with `v4l2-ctl --list-devices`. If it is not a USB (UVC) camera, change `device=` in the `pipeline` string. +- **No image in the viewer.** Make sure that `rerun --version` on the laptop shows 0.34.1, and that the laptop can connect to port 9876 on the device. +- **No skeletons.** Stand back so that the camera sees all of your body, or make `conf_threshold` lower. +- **The camera is disconnected while the app runs.** The app does not find this, and it stops sending frames. Restart the service. + +## Security + +The Rerun server has no authentication. All computers on the same network can connect to port 9876 and see the camera image. Use this reference only on a network that you trust. diff --git a/copper-rs-pose/icon.png b/copper-rs-pose/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..229ffa8fdf4ff60cf0d034d1a003f33b6e37ea8f GIT binary patch literal 30685 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 the capture node of a USB (UVC) camera. Connect only one. +# The SoC camera blocks on some boards also make /dev/video* nodes, so +# /dev/video0 is not always the USB camera. +SUBSYSTEM=="video4linux", KERNEL=="video*", DRIVERS=="uvcvideo", ATTR{index}=="0", SYMLINK+="copper-camera" From 4bbd454232d53ca80e523cc18f06ed72ff9157a6 Mon Sep 17 00:00:00 2001 From: nicksinas Date: Fri, 2 Oct 2026 18:58:39 -0500 Subject: [PATCH 2/3] copper-rs-pose: call the framework copper-rs in docs and comments Copper Robotics is the company and copper-rs is the product. Upstream source text is not changed. --- copper-rs-pose/README.md | 10 +++++----- copper-rs-pose/app/Cargo.toml | 4 ++-- copper-rs-pose/copper-compile.sh | 2 +- copper-rs-pose/getting_started.md | 16 ++++++++-------- .../lib/systemd/system/copper-rs-pose.service | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/copper-rs-pose/README.md b/copper-rs-pose/README.md index a670649..41ca38d 100644 --- a/copper-rs-pose/README.md +++ b/copper-rs-pose/README.md @@ -15,14 +15,14 @@ topics: icon: icon.png --- -# Copper Human Pose +# copper-rs Human Pose -A [Copper](https://github.com/copper-project/copper-rs) robotics task graph in Rust that reads a USB camera, finds human poses with YOLOv8n-pose on the CPU, and serves the results to a [Rerun](https://rerun.io) viewer on your laptop. It is based on the upstream `cu_human_pose` example. +A [copper-rs](https://github.com/copper-project/copper-rs) task graph in Rust that reads a USB camera, finds human poses with YOLOv8n-pose on the CPU, and serves the results to a [Rerun](https://rerun.io) viewer on your laptop. It is based on the upstream `cu_human_pose` example. -- Cross-compile a Copper app (a task graph in `copperconfig.ron`, made into code at build time) into one binary +- Cross-compile a copper-rs app (a task graph in `copperconfig.ron`, made into code at build time) into one binary - Camera input through GStreamer, inference with Candle, no Python and no GPU - Watch the live camera image and the skeletons from your laptop with `rerun --connect` -- Write the Copper log to `/var/lib` on a read-only root filesystem -- See the live task graph in the Copper TUI over SSH +- Write the copper-rs log to `/var/lib` on a read-only root filesystem +- See the live task graph in the copper-rs TUI over SSH The YOLOv8 pose weights are from Ultralytics and use the AGPL-3.0 license. The build downloads them, and they are not in this repository. For a product, get a license from Ultralytics or use your own model. diff --git a/copper-rs-pose/app/Cargo.toml b/copper-rs-pose/app/Cargo.toml index 26bfb20..72b8c3f 100644 --- a/copper-rs-pose/app/Cargo.toml +++ b/copper-rs-pose/app/Cargo.toml @@ -1,7 +1,7 @@ # Based on copper-rs examples/cu_human_pose (release/1.2, Apache-2.0). -# Copper crates are pinned exactly: the SDK rust is older than the declared +# copper-rs crates are pinned exactly: the SDK rust is older than the declared # rust-version (1.95), so the build uses --ignore-rust-version and any new -# Copper release could break it. +# copper-rs release could break it. [package] name = "copper-rs-pose" version = "0.1.0" diff --git a/copper-rs-pose/copper-compile.sh b/copper-rs-pose/copper-compile.sh index ef8c3f8..887595b 100755 --- a/copper-rs-pose/copper-compile.sh +++ b/copper-rs-pose/copper-compile.sh @@ -60,6 +60,6 @@ EOF # gstreamer-sys finds the target gstreamer through pkg-config in the SDK sysroot. export PKG_CONFIG_ALLOW_CROSS=1 -# Copper declares rust-version 1.95. The SDK rust is older, and the code builds +# copper-rs declares rust-version 1.95. The SDK rust is older, and the code builds # with it. The exact pins in Cargo.toml keep this bypass stable. cargo build --release --locked --ignore-rust-version --target "$RUST_TARGET" diff --git a/copper-rs-pose/getting_started.md b/copper-rs-pose/getting_started.md index dfd7fa6..3c676df 100644 --- a/copper-rs-pose/getting_started.md +++ b/copper-rs-pose/getting_started.md @@ -1,6 +1,6 @@ -# Getting Started with Copper Human Pose +# Getting Started with copper-rs Human Pose -This guide shows how to build the Copper human pose reference, put it on a device, and watch the poses on your laptop. The app is one Rust binary. It reads a USB camera, finds poses with YOLOv8n-pose on the CPU, and serves the results over Rerun on port 9876. +This guide shows how to build the copper-rs human pose reference, put it on a device, and watch the poses on your laptop. The app is one Rust binary. It reads a USB camera, finds poses with YOLOv8n-pose on the CPU, and serves the results over Rerun on port 9876. ## Prerequisites @@ -107,13 +107,13 @@ Log in as `root` with an empty password. The service starts automatically at boo copper-rs-pose: Rerun server ready. On your laptop run: rerun --connect rerun+http://:9876/proxy ``` -3. Make sure that the Copper log is written: +3. Make sure that the copper-rs log is written: ```bash ls -lh /var/lib/copper-rs-pose/ ``` - The directory has `human-pose_0.copper`. When a log file is full (256 MB), Copper starts `human-pose_1.copper`, then `human-pose_2.copper`, and more. Copper does not delete old files. Delete them when you need disk space. + The directory has `human-pose_0.copper`. When a log file is full (256 MB), copper-rs starts `human-pose_1.copper`, then `human-pose_2.copper`, and more. copper-rs does not delete old files. Delete them when you need disk space. 4. Get the IP address of the device: @@ -132,9 +132,9 @@ Log in as `root` with an empty password. The service starts automatically at boo Inference runs on the CPU. The frame rate is low, and it is lowest on the i.MX 8MP, which has Cortex-A53 cores. -### See the Copper TUI +### See the copper-rs TUI -The Copper console monitor shows the task graph and the timing of each task. It starts only when you run the app in a terminal. The service uses the camera and port 9876, so the command stops the service first. On your laptop, run: +The copper-rs console monitor shows the task graph and the timing of each task. It starts only when you run the app in a terminal. The service uses the camera and port 9876, so the command stops the service first. On your laptop, run: ```bash ssh -t root@ 'systemctl stop copper-rs-pose; copper-rs-pose' @@ -171,7 +171,7 @@ The udev rule `overlay/usr/lib/udev/rules.d/70-copper-camera.rules` makes `/dev/ ### Add a task to the graph -A Copper app is a graph of tasks. Each task is a Rust type, and `copperconfig.ron` connects the tasks. To add a task: +A copper-rs app is a graph of tasks. Each task is a Rust type, and `copperconfig.ron` connects the tasks. To add a task: 1. Write the task in `app/src/tasks/`, and export it from `app/src/tasks/mod.rs`. Use `rerun_viz.rs` as an example of a sink task. 2. Add the task to `tasks` in `app/copperconfig.ron`. @@ -201,7 +201,7 @@ The build runs `copper-compile.sh` in the SDK container. The script does these s 4. Writes `app/.cargo/config.toml` with the sysroot flags. 5. Runs `cargo build --release --locked --ignore-rust-version`. -Copper declares Rust 1.95, and the SDK has Rust 1.94.1. The code builds with 1.94.1, so the script uses `--ignore-rust-version`. `Cargo.toml` pins the Copper crates to `=1.2.1`, and `Cargo.lock` pins all other crates. +copper-rs declares Rust 1.95, and the SDK has Rust 1.94.1. The code builds with 1.94.1, so the script uses `--ignore-rust-version`. `Cargo.toml` pins the copper-rs crates to `=1.2.1`, and `Cargo.lock` pins all other crates. At build time, `build.rs` and the `#[copper_runtime]` macro read `app/copperconfig.ron` and make the task graph into Rust code. Thus a change to `copperconfig.ron` needs a new build. diff --git a/copper-rs-pose/overlay/usr/lib/systemd/system/copper-rs-pose.service b/copper-rs-pose/overlay/usr/lib/systemd/system/copper-rs-pose.service index 31193d2..76ee308 100644 --- a/copper-rs-pose/overlay/usr/lib/systemd/system/copper-rs-pose.service +++ b/copper-rs-pose/overlay/usr/lib/systemd/system/copper-rs-pose.service @@ -1,5 +1,5 @@ [Unit] -Description=Copper human pose (YOLOv8n-pose, Rerun server on port 9876) +Description=copper-rs human pose (YOLOv8n-pose, Rerun server on port 9876) After=network.target Wants=network.target From 9fb9741c5dafcc263088bc9e6f6a697076590d05 Mon Sep 17 00:00:00 2001 From: nicksinas Date: Fri, 16 Oct 2026 12:23:10 -0500 Subject: [PATCH 3/3] copper-rs-pose: support all 2026/next boards; address review comments - supported_targets and README targets: every 2026/next board except QEMU and jetson-orin-nx (11 targets). The Deploy section gives the provisioning profile per board family (sd, tegraflash, ufs). - rerun_viz: log keypoints, skeleton and boxes every frame. An empty set clears the overlay from the frame before, so stale overlays no longer stay when a person has no confident keypoints. - yolo SPPF: pad the max-pool with -inf, as PyTorch MaxPool2d does. Zero padding changed border values, because SiLU can be negative. - getting_started: use a width and height that are multiples of 16, because the app reads frames as rows with no padding. --- copper-rs-pose/README.md | 10 +++- copper-rs-pose/app/src/tasks/rerun_viz.rs | 70 +++++++++-------------- copper-rs-pose/app/src/yolo/model.rs | 29 ++++++---- copper-rs-pose/avocado.yaml | 10 +++- copper-rs-pose/getting_started.md | 24 ++++++-- 5 files changed, 80 insertions(+), 63 deletions(-) diff --git a/copper-rs-pose/README.md b/copper-rs-pose/README.md index 41ca38d..21a3c92 100644 --- a/copper-rs-pose/README.md +++ b/copper-rs-pose/README.md @@ -1,9 +1,17 @@ --- language: Rust targets: - - raspberrypi5 - imx8mp-evk + - imx91-frdm + - imx93-evk + - imx93-frdm + - jetson-agx-orin + - jetson-agx-thor - jetson-orin-nano + - raspberrypi4 + - raspberrypi5 + - rb3gen2 + - rubikpi3 topics: - robotics - vision diff --git a/copper-rs-pose/app/src/tasks/rerun_viz.rs b/copper-rs-pose/app/src/tasks/rerun_viz.rs index 03c1104..9c95e05 100644 --- a/copper-rs-pose/app/src/tasks/rerun_viz.rs +++ b/copper-rs-pose/app/src/tasks/rerun_viz.rs @@ -129,20 +129,8 @@ impl RerunPoseViz { } fn log_poses(&self, poses: &CuPoses) -> CuResult<()> { - if poses.is_empty() { - // Clear previous visualizations when no poses detected - let _ = self - .rec - .log(CAMERA_ENTITY, &Points2D::new(Vec::::new())); - let _ = self - .rec - .log(CAMERA_ENTITY, &LineStrips2D::new(Vec::>::new())); - let _ = self.rec.log( - CAMERA_ENTITY, - &Boxes2D::from_centers_and_sizes(Vec::::new(), Vec::::new()), - ); - return Ok(()); - } + // Log all three collections every frame, also when they are empty. An + // empty collection clears the overlay from the frame before. // Collect all keypoints for visualization let mut all_keypoints: Vec = Vec::new(); @@ -192,40 +180,34 @@ impl RerunPoseViz { } // Log keypoints - if !all_keypoints.is_empty() { - let radii = vec![rerun::Radius::new_scene_units(5.0); all_keypoints.len()]; - self.rec - .log( - CAMERA_ENTITY, - &Points2D::new(all_keypoints) - .with_colors(keypoint_colors) - .with_radii(radii), - ) - .map_err(|e| CuError::new_with_cause("Failed to log keypoints", e))?; - } + let radii = vec![rerun::Radius::new_scene_units(5.0); all_keypoints.len()]; + self.rec + .log( + CAMERA_ENTITY, + &Points2D::new(all_keypoints) + .with_colors(keypoint_colors) + .with_radii(radii), + ) + .map_err(|e| CuError::new_with_cause("Failed to log keypoints", e))?; // Log skeleton - if !skeleton_strips.is_empty() { - let skeleton_colors = vec![rerun::Color::from_rgb(255, 255, 0); skeleton_strips.len()]; - self.rec - .log( - CAMERA_ENTITY, - &LineStrips2D::new(skeleton_strips).with_colors(skeleton_colors), - ) - .map_err(|e| CuError::new_with_cause("Failed to log skeleton", e))?; - } + let skeleton_colors = vec![rerun::Color::from_rgb(255, 255, 0); skeleton_strips.len()]; + self.rec + .log( + CAMERA_ENTITY, + &LineStrips2D::new(skeleton_strips).with_colors(skeleton_colors), + ) + .map_err(|e| CuError::new_with_cause("Failed to log skeleton", e))?; // Log bounding boxes - if !box_centers.is_empty() { - let box_colors = vec![rerun::Color::from_rgb(0, 255, 0); box_centers.len()]; - self.rec - .log( - CAMERA_ENTITY, - &Boxes2D::from_centers_and_sizes(box_centers, box_sizes) - .with_colors(box_colors), - ) - .map_err(|e| CuError::new_with_cause("Failed to log boxes", e))?; - } + let box_colors = vec![rerun::Color::from_rgb(0, 255, 0); box_centers.len()]; + self.rec + .log( + CAMERA_ENTITY, + &Boxes2D::from_centers_and_sizes(box_centers, box_sizes) + .with_colors(box_colors), + ) + .map_err(|e| CuError::new_with_cause("Failed to log boxes", e))?; Ok(()) } diff --git a/copper-rs-pose/app/src/yolo/model.rs b/copper-rs-pose/app/src/yolo/model.rs index 8e9f602..d4a737c 100644 --- a/copper-rs-pose/app/src/yolo/model.rs +++ b/copper-rs-pose/app/src/yolo/model.rs @@ -197,22 +197,27 @@ impl Sppf { impl Module for Sppf { fn forward(&self, xs: &Tensor) -> Result { let xs = self.cv1.forward(xs)?; - let xs2 = xs - .pad_with_zeros(2, self.k / 2, self.k / 2)? - .pad_with_zeros(3, self.k / 2, self.k / 2)? - .max_pool2d_with_stride(self.k, 1)?; - let xs3 = xs2 - .pad_with_zeros(2, self.k / 2, self.k / 2)? - .pad_with_zeros(3, self.k / 2, self.k / 2)? - .max_pool2d_with_stride(self.k, 1)?; - let xs4 = xs3 - .pad_with_zeros(2, self.k / 2, self.k / 2)? - .pad_with_zeros(3, self.k / 2, self.k / 2)? - .max_pool2d_with_stride(self.k, 1)?; + let xs2 = pad_neg_inf(&xs, self.k / 2)?.max_pool2d_with_stride(self.k, 1)?; + let xs3 = pad_neg_inf(&xs2, self.k / 2)?.max_pool2d_with_stride(self.k, 1)?; + let xs4 = pad_neg_inf(&xs3, self.k / 2)?.max_pool2d_with_stride(self.k, 1)?; self.cv2.forward(&Tensor::cat(&[&xs, &xs2, &xs3, &xs4], 1)?) } } +/// Pads the height and width of an NCHW tensor with -inf, like the padding of +/// PyTorch MaxPool2d. Zero padding changes the result at the borders, because +/// the SiLU output before the pool can be negative. +fn pad_neg_inf(xs: &Tensor, pad: usize) -> Result { + let (b, c, h, w) = xs.dims4()?; + let fill = |h: usize, w: usize| { + Tensor::full(f32::NEG_INFINITY, (b, c, h, w), xs.device())?.to_dtype(xs.dtype()) + }; + let rows = fill(pad, w)?; + let xs = Tensor::cat(&[&rows, xs, &rows], 2)?; + let cols = fill(h + 2 * pad, pad)?; + Tensor::cat(&[&cols, &xs, &cols], 3) +} + #[derive(Debug)] struct Dfl { conv: Conv2d, diff --git a/copper-rs-pose/avocado.yaml b/copper-rs-pose/avocado.yaml index 2ddb3d9..e93ef4b 100644 --- a/copper-rs-pose/avocado.yaml +++ b/copper-rs-pose/avocado.yaml @@ -3,9 +3,17 @@ cli_requirement: ">=0.41.0" default_target: "raspberrypi5" supported_targets: - - raspberrypi5 - imx8mp-evk + - imx91-frdm + - imx93-evk + - imx93-frdm + - jetson-agx-orin + - jetson-agx-thor - jetson-orin-nano + - raspberrypi4 + - raspberrypi5 + - rb3gen2 + - rubikpi3 distro: release: 2026 diff --git a/copper-rs-pose/getting_started.md b/copper-rs-pose/getting_started.md index 3c676df..9ac0279 100644 --- a/copper-rs-pose/getting_started.md +++ b/copper-rs-pose/getting_started.md @@ -6,7 +6,7 @@ This guide shows how to build the copper-rs human pose reference, put it on a de - macOS or Linux. On macOS, the Avocado CLI starts its own helper VM (avocado-vm) for the SDK. On Linux, Docker must be installed and running. - The latest version of the [Avocado CLI](https://docs.peridio.com/guides/avocado-cli/overview) -- One of the supported devices: `raspberrypi5`, `imx8mp-evk` or `jetson-orin-nano` +- One of the supported devices. See `supported_targets` in `avocado.yaml` for the list. - The media and cables to provision your device (SD card, USB cable, serial console adapter). See the [Support Matrix](https://docs.peridio.com/hardware/support-matrix). - A USB (UVC) webcam. Most webcams that give YUYV video work. - A network connection between the device and your laptop. Ethernet is better than Wi-Fi, because the device sends raw camera frames to the viewer. @@ -55,9 +55,9 @@ The first build compiles about 700 Rust crates and takes some minutes. Later bui ## Deploy -### Raspberry Pi 5 and NXP i.MX 8MP EVK +### Raspberry Pi and NXP boards -Insert your SD card and provision: +For `raspberrypi4`, `raspberrypi5`, `imx8mp-evk`, `imx91-frdm`, `imx93-evk` and `imx93-frdm`, insert your SD card and provision: ```bash avocado provision -r dev --profile sd @@ -65,7 +65,9 @@ avocado provision -r dev --profile sd Put the SD card into the device, connect the webcam and the network, and apply power. -### NVIDIA Jetson Orin Nano +### NVIDIA Jetson + +For `jetson-orin-nano`, `jetson-agx-orin` and `jetson-agx-thor`, put the device in recovery mode, connect it to your computer with USB, and provision: ```bash avocado provision -r dev --profile tegraflash @@ -73,6 +75,16 @@ avocado provision -r dev --profile tegraflash Obey the USB disconnect and reconnect prompts during the flash process. Then connect the webcam and the network. +### Qualcomm boards + +For `rb3gen2` and `rubikpi3`, put the board in EDL mode and connect it to your computer with USB. Then provision to the onboard UFS storage: + +```bash +avocado provision -r dev --profile ufs +``` + +Connect the webcam and the network. + ### Update a device that you provisioned before When you change the code, you do not have to provision again. Build, then deploy to the running device: @@ -130,7 +142,7 @@ Log in as `root` with an empty password. The service starts automatically at boo `rerun --version` must show 0.34.1. The viewer shows the `camera/image` view with the live camera image. When a person is in the camera image, the viewer shows a box, the keypoints and the skeleton lines on the person. -Inference runs on the CPU. The frame rate is low, and it is lowest on the i.MX 8MP, which has Cortex-A53 cores. +Inference runs on the CPU, so the frame rate depends on the board. It is highest on the Jetson boards and lowest on the i.MX 91 and i.MX 93, which have small Cortex-A55 cores. ### See the copper-rs TUI @@ -165,6 +177,8 @@ The width and height are in three places in `app/copperconfig.ron`. The three va - The `caps` string of the `camera` task - The `width` and `height` of the `gst_to_image` task +Use a width and a height that are multiples of 16, for example 640x352 or 1280x720. With other values, GStreamer can add padding bytes to each row. The app reads the frame as rows with no padding, so the image and the poses are not correct. + ### Use a different camera The udev rule `overlay/usr/lib/udev/rules.d/70-copper-camera.rules` makes `/dev/copper-camera` for a USB camera. To use a different camera, change the rule, or change `device=` in the `pipeline` string.