zendo-protocol 0.2.0

Wire-protocol constants and binary frame decoders for the Zendo motion-tracking WebSocket stream.
Documentation
//! The protocol decoding error type.

use core::fmt;

/// Why a binary frame could not be decoded.
///
/// This is a small, copyable enum so downstream crates can match on the exact
/// failure without string parsing.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ProtocolError {
    /// The frame had no bytes, so it carried no type tag.
    EmptyFrame,
    /// The type tag did not correspond to any known message.
    UnknownMessageType(u8),
    /// The payload length did not match what the message type requires.
    InvalidLength {
        message_type: u8,
        expected: usize,
        actual: usize,
    },
    /// A hand frame carried a side byte that was neither right (0) nor left (1).
    InvalidHandSide(u8),
}

impl fmt::Display for ProtocolError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::EmptyFrame => f.write_str("received an empty WebSocket frame"),
            Self::UnknownMessageType(tag) => {
                write!(f, "unknown message type byte 0x{tag:02x}")
            }
            Self::InvalidLength {
                message_type,
                expected,
                actual,
            } => write!(
                f,
                "message type 0x{message_type:02x}: expected {expected} payload bytes, got {actual}"
            ),
            Self::InvalidHandSide(byte) => {
                write!(f, "invalid hand-side byte {byte} (expected 0 or 1)")
            }
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ProtocolError {}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn display_is_human_readable() {
        // Arrange / Act / Assert
        assert_eq!(
            ProtocolError::EmptyFrame.to_string(),
            "received an empty WebSocket frame"
        );
        assert_eq!(
            ProtocolError::UnknownMessageType(0xAB).to_string(),
            "unknown message type byte 0xab"
        );
        assert_eq!(
            ProtocolError::InvalidHandSide(7).to_string(),
            "invalid hand-side byte 7 (expected 0 or 1)"
        );
    }
}