use array2d::Array2D;
use async_trait::async_trait;
use crate::data::{OpenRGBReadable, ZoneType};
use crate::OpenRGBError;
use crate::protocol::OpenRGBReadableStream;
#[derive(Debug, Eq, PartialEq)]
pub struct Zone {
pub name: String,
pub r#type: ZoneType,
pub leds_min: u32,
pub leds_max: u32,
pub leds_count: u32,
pub matrix: Option<Array2D<u32>>,
}
#[async_trait]
impl OpenRGBReadable for Zone {
async fn read(stream: &mut impl OpenRGBReadableStream, protocol: u32) -> Result<Self, OpenRGBError> {
let name = stream.read_value(protocol).await?;
let r#type = stream.read_value(protocol).await?;
let leds_min = stream.read_value(protocol).await?;
let leds_max = stream.read_value(protocol).await?;
let leds_count = stream.read_value(protocol).await?;
let matrix_len = stream.read_value::<u16>(protocol).await? as usize;
let matrix = match matrix_len {
0 => None,
_ => Some({
let matrix_height = stream.read_value::<u32>(protocol).await? as usize;
let matrix_width = stream.read_value::<u32>(protocol).await? as usize;
let matrix_size = matrix_height * matrix_width;
let mut matrix_data = Vec::with_capacity(matrix_size);
for _ in 0..matrix_size {
matrix_data.push(stream.read_value(protocol).await?);
}
Array2D::from_row_major(&matrix_data, matrix_height, matrix_width)
})
};
Ok(Zone {
name,
r#type,
leds_min,
leds_max,
leds_count,
matrix,
})
}
}
#[cfg(test)]
mod tests {
use std::error::Error;
use array2d::Array2D;
use tokio_test::io::Builder;
use crate::data::{Zone, ZoneType};
use crate::DEFAULT_PROTOCOL;
use crate::protocol::OpenRGBReadableStream;
use crate::tests::setup;
#[tokio::test]
async fn test_read_001() -> Result<(), Box<dyn Error>> {
setup()?;
let mut stream = Builder::new()
.read(&5_u16.to_le_bytes()) .read(b"test\0") .read(&1_u32.to_le_bytes()) .read(&3_u32.to_le_bytes()) .read(&18_u32.to_le_bytes()) .read(&15_u32.to_le_bytes()) .read(&0_u16.to_le_bytes()) .build();
assert_eq!(stream.read_value::<Zone>(DEFAULT_PROTOCOL).await?, Zone {
name: "test".to_string(),
r#type: ZoneType::Linear,
leds_min: 3,
leds_max: 18,
leds_count: 15,
matrix: None,
});
Ok(())
}
#[tokio::test]
async fn test_read_002() -> Result<(), Box<dyn Error>> {
setup()?;
let mut stream = Builder::new()
.read(&5_u16.to_le_bytes()) .read(b"test\0") .read(&1_u32.to_le_bytes()) .read(&3_u32.to_le_bytes()) .read(&18_u32.to_le_bytes()) .read(&15_u32.to_le_bytes()) .read(&32_u16.to_le_bytes()) .read(&2_u32.to_le_bytes()) .read(&3_u32.to_le_bytes()) .read(&0_u32.to_le_bytes()) .read(&1_u32.to_le_bytes()) .read(&2_u32.to_le_bytes()) .read(&3_u32.to_le_bytes()) .read(&4_u32.to_le_bytes()) .read(&5_u32.to_le_bytes()) .build();
assert_eq!(stream.read_value::<Zone>(DEFAULT_PROTOCOL).await?, Zone {
name: "test".to_string(),
r#type: ZoneType::Linear,
leds_min: 3,
leds_max: 18,
leds_count: 15,
matrix: Some(Array2D::from_rows(&[vec![0, 1, 2], vec![3, 4, 5]])),
});
Ok(())
}
}