use crate::{
Result,
colour::Rgb,
error::MouseError,
keyboard::{KeyboardDevice, packet::KeyboardPacket},
};
pub const COLOUR_PACKET_HEADER: [u8; 3] = [0x00, 0x21, 0xff];
#[derive(Debug, Clone)]
pub struct ColourPacket {
colours: Vec<Rgb>,
zones: usize,
}
impl KeyboardPacket for ColourPacket {
fn serialize(&self) -> Result<Vec<u8>> {
let mut buffer = Vec::with_capacity(4 + (self.zones * 3));
buffer.extend_from_slice(&COLOUR_PACKET_HEADER);
for zone in self.colours.iter().take(self.zones) {
buffer.push(zone.r);
buffer.push(zone.g);
buffer.push(zone.b);
}
Ok(buffer)
}
}
impl ColourPacket {
pub fn new(device_type: KeyboardDevice) -> Self {
Self {
zones: device_type.get_zones(),
colours: vec![Rgb::new(255, 255, 255); device_type.get_zones()],
}
}
pub fn with_colours(device_type: KeyboardDevice, colours: Vec<Rgb>) -> Self {
let zones = match device_type {
KeyboardDevice::None => 0,
KeyboardDevice::Apex3TKL => 8,
};
let mut colours_safe = colours;
colours_safe.resize(zones, Rgb::new(255, 255, 255));
Self {
zones,
colours: colours_safe,
}
}
pub fn get_colours(&self) -> Vec<Rgb> {
self.colours.clone()
}
pub fn get_zone(&self, index: usize) -> Result<Rgb> {
if index >= self.zones {
return Err(MouseError::ZoneOutOfRange.into());
}
self.colours
.get(index)
.cloned()
.ok_or_else(|| MouseError::ZoneOutOfRange.into())
}
pub fn change_zone(&mut self, index: usize, colour: Rgb) -> Result<()> {
if index >= self.zones {
return Err(MouseError::ZoneOutOfRange.into());
}
if let Some(value) = self.colours.get_mut(index) {
*value = colour;
Ok(())
} else {
Err(MouseError::ZoneOutOfRange.into())
}
}
}