zmk-studio-api 0.3.1

Rust + Python client for the ZMK Studio RPC API (Serial + BLE)
Documentation
use prost::Message;

use crate::framing::{FrameDecoder, FramingError, encode_frame};
use crate::proto::zmk::studio::{Request, Response};

#[derive(Debug)]
pub enum ProtocolError {
    Framing(FramingError),
    Decode(prost::DecodeError),
}

impl core::fmt::Display for ProtocolError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            Self::Framing(err) => write!(f, "Framing error: {err}"),
            Self::Decode(err) => write!(f, "Decode error: {err}"),
        }
    }
}

impl std::error::Error for ProtocolError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Framing(err) => Some(err),
            Self::Decode(err) => Some(err),
        }
    }
}

impl From<FramingError> for ProtocolError {
    fn from(value: FramingError) -> Self {
        Self::Framing(value)
    }
}

impl From<prost::DecodeError> for ProtocolError {
    fn from(value: prost::DecodeError) -> Self {
        Self::Decode(value)
    }
}

pub fn encode_request(request: &Request) -> Vec<u8> {
    encode_frame(&request.encode_to_vec())
}

pub fn decode_responses(
    decoder: &mut FrameDecoder,
    chunk: &[u8],
) -> Result<Vec<Response>, ProtocolError> {
    decoder
        .push(chunk)?
        .into_iter()
        .map(|frame| Response::decode(frame.as_slice()).map_err(ProtocolError::from))
        .collect()
}