minidsp-protocol 0.1.4

A control interface for some MiniDSP products
Documentation
use bytes::Buf;
use thiserror::Error;

macro_rules! try_def {
    ($meth:ident, $ty:ty) => {
        fn $meth(&mut self) -> Result<$ty, TryBufError>;
    };
}

macro_rules! try_impl {
    ($meth:ident, $inner:ident, $ty:ty, $len:literal) => {
        fn $meth(&mut self) -> Result<$ty, TryBufError> {
            if self.remaining() < $len {
                Err(TryBufError::InvalidLength {
                    remaining: self.remaining(),
                    required: $len,
                })
            } else {
                Ok(self.$inner())
            }
        }
    };
}

#[cfg_attr(feature = "debug", derive(Debug, Error))]
#[derive(Clone)]
pub enum TryBufError {
    #[cfg_attr(
        feature = "debug",
        error("invalid read length, remaining: {remaining}, required: {required}")
    )]
    InvalidLength { remaining: usize, required: usize },
}

pub trait TryBuf {
    try_def!(try_get_u8, u8);
    try_def!(try_get_i8, i8);

    try_def!(try_get_u16, u16);
    try_def!(try_get_u16_le, u16);
    try_def!(try_get_i16, i16);
    try_def!(try_get_i16_le, i16);

    try_def!(try_get_u32, u32);
    try_def!(try_get_u32_le, u32);
    try_def!(try_get_i32, i32);
    try_def!(try_get_i32_le, i32);

    try_def!(try_get_u64, u64);
    try_def!(try_get_u64_le, u64);
    try_def!(try_get_i64, i64);
    try_def!(try_get_i64_le, i64);

    try_def!(try_get_f32, f32);
    try_def!(try_get_f32_le, f32);

    try_def!(try_get_f64, f64);
    try_def!(try_get_f64_le, f64);
}

impl<T> TryBuf for T
where
    T: Buf,
{
    try_impl!(try_get_u8, get_u8, u8, 1);
    try_impl!(try_get_i8, get_i8, i8, 1);

    try_impl!(try_get_u16, get_u16, u16, 2);
    try_impl!(try_get_u16_le, get_u16_le, u16, 2);
    try_impl!(try_get_i16, get_i16, i16, 2);
    try_impl!(try_get_i16_le, get_i16_le, i16, 2);

    try_impl!(try_get_u32, get_u32, u32, 4);
    try_impl!(try_get_u32_le, get_u32_le, u32, 4);
    try_impl!(try_get_i32, get_i32, i32, 4);
    try_impl!(try_get_i32_le, get_i32_le, i32, 4);

    try_impl!(try_get_u64, get_u64, u64, 8);
    try_impl!(try_get_u64_le, get_u64_le, u64, 8);
    try_impl!(try_get_i64, get_i64, i64, 8);
    try_impl!(try_get_i64_le, get_i64_le, i64, 8);

    try_impl!(try_get_f32, get_f32, f32, 4);
    try_impl!(try_get_f32_le, get_f32_le, f32, 4);

    try_impl!(try_get_f64, get_f64, f64, 8);
    try_impl!(try_get_f64_le, get_f64_le, f64, 8);
}