use array2d::Array2D;
use flagset::{FlagSet, flags};
use crate::protocol::data::ProtocolOption;
use crate::protocol::{DeserFromBuf, ReceivedMessage};
use crate::{OpenRgbResult, impl_enum_discriminant};
use super::SegmentData;
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
pub enum ZoneType {
Single = 0,
Linear = 1,
Matrix = 2,
}
impl_enum_discriminant!(ZoneType, Single: 0, Linear: 1, Matrix: 2);
flags! {
pub enum ZoneFlags: u32 {
ResizableForEffectsOnly = 1 << 0,
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub(crate) struct ZoneData {
pub id: usize,
pub name: String,
pub zone_type: ZoneType,
pub leds_min: u32,
pub leds_max: u32,
pub leds_count: u32,
pub segments: ProtocolOption<4, Vec<SegmentData>>,
pub flags: ProtocolOption<5, FlagSet<ZoneFlags>>,
pub matrix: Option<Array2D<u32>>,
}
impl ZoneData {
pub fn id(&self) -> usize {
self.id
}
pub fn name(&self) -> &str {
&self.name
}
pub fn zone_type(&self) -> ZoneType {
self.zone_type
}
pub fn leds_min(&self) -> usize {
self.leds_min as usize
}
pub fn leds_max(&self) -> usize {
self.leds_max as usize
}
pub fn leds_count(&self) -> usize {
self.leds_count as usize
}
pub fn segments(&self) -> Option<&[SegmentData]> {
self.segments.value().map(|s| s.as_slice())
}
pub fn matrix(&self) -> Option<&Array2D<u32>> {
self.matrix.as_ref()
}
}
impl DeserFromBuf for ZoneData {
fn deserialize(buf: &mut ReceivedMessage<'_>) -> OpenRgbResult<Self> {
let name = buf.read_value()?;
let zone_type = buf.read_value()?;
let leds_min = buf.read_value()?;
let leds_max = buf.read_value()?;
let leds_count = buf.read_value()?;
let matrix_len = buf.read_u16()? as usize;
let matrix = match matrix_len {
0 => None,
_ => Some({
let matrix_height = buf.read_value::<u32>()? as usize;
let matrix_width = buf.read_value::<u32>()? as usize;
let matrix_size = matrix_height * matrix_width;
let matrix_data = buf.read_n_values::<u32>(matrix_size)?;
Array2D::from_row_major(&matrix_data, matrix_height, matrix_width).unwrap()
}),
};
let mut segments: ProtocolOption<4, Vec<SegmentData>> = buf.read_value()?;
if let Some(seg) = segments.value_mut() {
for (i, s) in seg.iter_mut().enumerate() {
s.set_id(i);
}
}
let flags = buf.read_value()?;
Ok(Self {
id: usize::MAX,
name,
zone_type,
leds_min,
leds_max,
leds_count,
matrix,
segments,
flags,
})
}
}
#[cfg(test)]
mod tests {
use std::error::Error;
use crate::{WriteMessage, data::ZoneType};
#[tokio::test]
async fn test_read_001() -> Result<(), Box<dyn Error>> {
let mut buf = WriteMessage::new(crate::DEFAULT_PROTOCOL);
let mut msg = buf.push_value(&1_u32)?.to_received_msg();
assert_eq!(msg.read_value::<ZoneType>()?, ZoneType::Linear);
Ok(())
}
#[tokio::test]
async fn test_write_001() -> Result<(), Box<dyn Error>> {
let mut buf = WriteMessage::new(crate::DEFAULT_PROTOCOL);
let mut msg = buf.push_value(&ZoneType::Linear)?.to_received_msg();
assert_eq!(msg.read_value::<u32>()?, 1);
Ok(())
}
}