zendo-protocol 0.1.2

Wire-protocol constants and binary frame decoders for the Zendo motion-tracking WebSocket stream.
Documentation
//! Wire-protocol definitions for the Zendo motion-tracking WebSocket stream.
//!
//! This crate is the single source of truth for the binary protocol that the
//! Zendo desktop app emits and that [`zendo-sdk`](https://crates.io/crates/zendo-sdk)
//! consumes. It owns the port range, the message-type tags, the joint and
//! landmark vocabularies, and the pure decode/encode routines.
//!
//! It has no dependencies, performs no I/O, never allocates, and is `no_std`
//! by default-disabling the `std` feature.
//!
//! # Frame layout
//!
//! Every frame is one binary WebSocket message: byte 0 is the type tag, the
//! rest is the payload. All numeric values are little-endian `f64`.
//!
//! | Message | Tag | Payload |
//! |---|---|---|
//! | Hello            | `0x01` | protocol version (`u16` LE) |
//! | Body quaternions | `0x02` | 13 joints x (w, x, y, z) |
//! | Body landmarks   | `0x03` | 19 landmarks x (x, y, z, confidence) |
//! | Hand quaternions | `0x04` | 1 side byte + 16 joints x (w, x, y, z) |
//! | Hand landmarks   | `0x05` | 1 side byte + 21 landmarks x (x, y, z, confidence) |
//!
//! The server sends the hello frame first on every connection so clients can
//! detect a [`PROTOCOL_VERSION`] mismatch before decoding data frames.
//!
//! # Example
//!
//! ```
//! use zendo_protocol::{decode, Message};
//!
//! # let frame: &[u8] = &{
//! #     let mut f = [0u8; 1 + 13 * 4 * 8];
//! #     f[0] = zendo_protocol::MSG_BODY_QUATERNION;
//! #     f
//! # };
//! match decode(frame) {
//!     Ok(Message::BodyQuaternions(q)) => println!("hips: {:?}", q.hips),
//!     Ok(other) => println!("other message: {other:?}"),
//!     Err(e) => eprintln!("bad frame: {e}"),
//! }
//! ```

#![cfg_attr(not(feature = "std"), no_std)]

mod constants;
mod decode;
mod encode;
mod error;
mod frames;
mod types;

pub use constants::{
    BODY_JOINT_COUNT, BODY_LANDMARK_COUNT, HAND_JOINT_COUNT, HAND_LANDMARK_COUNT, HAND_SIDE_LEFT,
    HAND_SIDE_RIGHT, MSG_BODY_LANDMARK, MSG_BODY_QUATERNION, MSG_HAND_LANDMARK,
    MSG_HAND_QUATERNION, MSG_HELLO, PROTOCOL_VERSION, WEBSOCKET_PORT_END, WEBSOCKET_PORT_START,
};
pub use decode::{decode, decode_hello, Message};
pub use encode::{
    encode_body_landmarks, encode_body_quaternions, encode_hand_landmarks, encode_hand_quaternions,
    encode_hello, ENCODED_BODY_LANDMARK_LEN, ENCODED_BODY_QUATERNION_LEN,
    ENCODED_HAND_LANDMARK_LEN, ENCODED_HAND_QUATERNION_LEN, ENCODED_HELLO_LEN,
};
pub use error::ProtocolError;
pub use frames::{BodyLandmarkFrame, BodyQuaternionFrame, HandLandmarkFrame, HandQuaternionFrame};
pub use types::{HandJoint, HandLandmarkName, HandSide, Joint, Landmark, LandmarkName, Quaternion};