respeaker 0.3.0

USB control library for Seeed ReSpeaker Mic Array v2.0 and XVF3800 (LEDs + DSP tuning), with reSpeaker Lite identification
Documentation
use crate::error::{Error, Result};

/// RGB color (0–255 per channel).
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct Rgb {
    pub r: u8,
    pub g: u8,
    pub b: u8,
}

impl Rgb {
    pub const BLACK: Self = Self { r: 0, g: 0, b: 0 };
    pub const RED: Self = Self { r: 255, g: 0, b: 0 };
    pub const GREEN: Self = Self { r: 0, g: 255, b: 0 };
    pub const BLUE: Self = Self { r: 0, g: 0, b: 255 };
    pub const WHITE: Self = Self {
        r: 255,
        g: 255,
        b: 255,
    };

    pub const fn new(r: u8, g: u8, b: u8) -> Self {
        Self { r, g, b }
    }

    /// Parse `RRGGBB` or `0xRRGGBB` hex.
    pub fn from_hex(s: &str) -> Result<Self> {
        let s = s.trim().trim_start_matches("0x").trim_start_matches("0X");
        if s.len() != 6 {
            return Err(Error::InvalidValue(format!(
                "expected RRGGBB hex color, got `{s}`"
            )));
        }
        let v = u32::from_str_radix(s, 16)
            .map_err(|e| Error::InvalidValue(format!("invalid hex color `{s}`: {e}")))?;
        Ok(Self::from_u32(v))
    }

    /// Pack as `0xRRGGBB` (XVF3800 LED_COLOR format).
    pub const fn to_u32(self) -> u32 {
        ((self.r as u32) << 16) | ((self.g as u32) << 8) | (self.b as u32)
    }

    pub const fn from_u32(v: u32) -> Self {
        Self {
            r: ((v >> 16) & 0xff) as u8,
            g: ((v >> 8) & 0xff) as u8,
            b: (v & 0xff) as u8,
        }
    }

    pub(crate) fn mono_payload(self) -> [u8; 4] {
        [self.r, self.g, self.b, 0]
    }
}