wip multi
Some checks failed
Rust / build (pull_request) Failing after 1m5s

This commit is contained in:
Vinzenz Schroeter 2025-07-19 20:17:53 +02:00
parent c39b9b96b7
commit a834539a0b
11 changed files with 126 additions and 29 deletions

View file

@ -95,7 +95,7 @@ impl LoadableFromPacket for BitmapCommand {
let expected_bytes = tile_w * pixel_h;
let (payload, read_payload_bytes) =
decompress(compression, &payload, expected_bytes)
decompress(compression, payload, expected_bytes)
.map_err(|_| TryFromPacketError::DecompressionFailed)?;
if expected_bytes < payload.len() {
return Err(TryFromPacketError::UnexpectedPayloadSize {

View file

@ -112,7 +112,7 @@ impl LoadableFromPacket for BitVecCommand {
let compression = CompressionCode::try_from(sub)?;
let (payload, read_payload_bytes) =
decompress(compression, &payload, expected_len)
decompress(compression, payload, expected_len)
.map_err(|_| TryFromPacketError::DecompressionFailed)?;
if payload.len() < expected_len {
return Err(TryFromPacketError::UnexpectedPayloadSize {

View file

@ -67,7 +67,7 @@ impl LoadableFromPacket for BrightnessGridCommand {
actual: payload.len(),
expected: expected_size,
});
};
}
let (payload, remaining) = payload.split_at(expected_size);
let grid = ByteGrid::from_raw_parts_unchecked(

View file

@ -25,7 +25,7 @@ pub enum CommandCode {
Utf8Data = 0x0020,
#[cfg(feature = "compression_zstd")]
BitmapLinearWinZstd = 0x001A,
//Multi = 0x0100,
Multi = 0x0100,
}
impl From<CommandCode> for u16 {

View file

@ -59,7 +59,7 @@ impl LoadableFromPacket for GlobalBrightnessCommand {
return Err(TryFromPacketError::ExtraneousHeaderValues);
}
let brightness = *payload.get(0).ok_or(
let brightness = *payload.first().ok_or(
TryFromPacketError::UnexpectedPayloadSize {
expected: 1,
actual: 0,

View file

@ -10,7 +10,7 @@ mod errors;
mod fade_out;
mod global_brightness;
mod hard_reset;
//mod multi;
mod multi;
mod typed;
use crate::{Header, Packet};
@ -26,6 +26,7 @@ pub use errors::*;
pub use fade_out::*;
pub use global_brightness::*;
pub use hard_reset::*;
pub use multi::*;
use std::{fmt::Debug, hash::Hash};
pub use typed::*;
@ -112,9 +113,7 @@ pub trait LoadableFromPacket: Sized {
/// Load the specified bytes.
///
/// In case of success, returns a tuple of Self and the remaining payload.
fn from_bytes<'t>(
buf: &'t [u8],
) -> Result<(Self, &'t [u8]), TryFromPacketError> {
fn from_bytes(buf: &[u8]) -> Result<(Self, &[u8]), TryFromPacketError> {
let (header, bytes_header) =
Header::read_from(buf).ok_or(TryFromPacketError::TooSmall)?;
let (result, remaining) = Self::load(&header, &buf[bytes_header..])?;
@ -160,6 +159,7 @@ derive_try_from_packet!(FadeOutCommand);
derive_try_from_packet!(GlobalBrightnessCommand);
derive_try_from_packet!(HardResetCommand);
derive_try_from_packet!(TypedCommand);
derive_try_from_packet!(MultiCommand);
fn check_command_code_only(
header: &Header,
@ -209,7 +209,8 @@ mod tests {
$(#[$meta])*
#[test]
fn $fn_name() {
let original = $crate::TypedCommand::from($command);
let original = std::hint::black_box($command);
let original = $crate::TypedCommand::from(original);
let packet1 = Packet::try_from(&original).unwrap();
let packet2 = Packet::try_from(original.clone()).unwrap();

85
src/commands/multi.rs Normal file
View file

@ -0,0 +1,85 @@
use crate::{
commands::check_command_code, CommandCode, Header, LoadableFromPacket,
Packet, TryFromPacketError, TryIntoPacketError, TypedCommand,
};
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
pub struct MultiCommand {
commands: [Option<TypedCommand>; 4],
}
impl MultiCommand {
pub fn add(&mut self, command: TypedCommand) -> Result<(), TypedCommand> {
for item in &mut self.commands {
if item.is_none() {
*item = Some(command);
return Ok(());
}
}
Err(command)
}
}
impl TryInto<Packet> for MultiCommand {
type Error = TryIntoPacketError;
fn try_into(self) -> Result<Packet, Self::Error> {
let mut payload = Vec::new();
for command in self.commands.into_iter().flatten() {
let packet = Packet::try_from(command)?;
payload.extend_from_slice(&Vec::from(packet));
}
Ok(Packet {
header: Header {
command_code: CommandCode::Multi.into(),
..Default::default()
},
payload: Some(payload),
})
}
}
impl LoadableFromPacket for MultiCommand {
fn load<'t>(
header: &Header,
payload: &'t [u8],
) -> Result<(Self, &'t [u8]), TryFromPacketError> {
check_command_code(header.command_code, CommandCode::Multi)?;
let mut result = Self {
commands: Default::default(),
};
let mut remaining_payload = payload;
for i in 0..5 {
if remaining_payload.len() < 2 {
break;
}
result.commands[i] =
match TypedCommand::from_bytes(remaining_payload) {
Ok((command, remaining)) => {
remaining_payload = remaining;
Some(command)
}
Err(TryFromPacketError::TooSmall) => break,
Err(e) => Err(e)?,
};
}
if result.commands[0].is_none() {
return Err(TryFromPacketError::TooSmall);
}
Ok((result, remaining_payload))
}
}
#[cfg(test)]
mod tests {
use crate::commands::{multi::MultiCommand, tests::TestImplementsCommand};
use crate::{Command, Header, LoadableFromPacket, TryFromPacketError};
impl TestImplementsCommand for MultiCommand {}
}

View file

@ -90,6 +90,7 @@ impl LoadableFromPacket for TypedCommand {
CommandCode::BitmapLinearWinZstd => {
load_as_typed::<BitmapCommand>(header, payload)
}
CommandCode::Multi => todo!(),
}
}
}

View file

@ -55,27 +55,37 @@ impl<R: Read> Counted<R> {
impl<R: Read> Read for Counted<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.inner.read(buf).inspect(|count| self.count += *count)
// rust 1.76: update to inspect
self.inner.read(buf).map(|count| {
self.count += count;
count
})
}
fn read_vectored(
&mut self,
bufs: &mut [IoSliceMut<'_>],
) -> std::io::Result<usize> {
self.inner
.read_vectored(bufs)
.inspect(|count| self.count += *count)
// rust 1.76: update to inspect
self.inner.read_vectored(bufs).map(|count| {
self.count += count;
count
})
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
self.inner
.read_to_end(buf)
.inspect(|count| self.count += *count)
// rust 1.76: update to inspect
self.inner.read_to_end(buf).map(|count| {
self.count += count;
count
})
}
fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
self.inner
.read_to_string(buf)
.inspect(|count| self.count += *count)
// rust 1.76: update to inspect
self.inner.read_to_string(buf).map(|count| {
self.count += count;
count
})
}
}

View file

@ -26,17 +26,17 @@ pub(crate) enum CompressionError {
pub(crate) trait CompressionAlgo {
const CODE: CompressionCode;
fn compress(payload: &[u8]) -> Result<Vec<u8>, CompressionError>;
fn decompress<'t>(
payload: &'t [u8],
fn decompress(
payload: &[u8],
expected_size_hint: usize,
) -> Result<(Vec<u8>, &'t [u8]), CompressionError>;
) -> Result<(Vec<u8>, &[u8]), CompressionError>;
}
pub(crate) fn decompress<'t>(
pub(crate) fn decompress(
kind: CompressionCode,
#[allow(unused, reason = "depends on features")] payload: &'t [u8],
#[allow(unused, reason = "depends on features")] payload: &[u8],
expected_size_hint: usize,
) -> Result<(Vec<u8>, &'t [u8]), CompressionError> {
) -> Result<(Vec<u8>, &[u8]), CompressionError> {
match kind {
CompressionCode::Uncompressed => {
uncompressed::Uncompressed::decompress(payload, expected_size_hint)

View file

@ -12,10 +12,10 @@ impl CompressionAlgo for Uncompressed {
Ok(payload.to_vec())
}
fn decompress<'t>(
payload: &'t [u8],
fn decompress(
payload: &[u8],
expected_size_hint: usize,
) -> Result<(Vec<u8>, &'t [u8]), CompressionError> {
) -> Result<(Vec<u8>, &[u8]), CompressionError> {
let index = expected_size_hint.min(payload.len());
let (payload, remaining) = payload.split_at(index);
Ok((payload.to_vec(), remaining))