This commit is contained in:
parent
c39b9b96b7
commit
a834539a0b
11 changed files with 126 additions and 29 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ pub enum CommandCode {
|
|||
Utf8Data = 0x0020,
|
||||
#[cfg(feature = "compression_zstd")]
|
||||
BitmapLinearWinZstd = 0x001A,
|
||||
//Multi = 0x0100,
|
||||
Multi = 0x0100,
|
||||
}
|
||||
|
||||
impl From<CommandCode> for u16 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
85
src/commands/multi.rs
Normal 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 {}
|
||||
}
|
||||
|
|
@ -90,6 +90,7 @@ impl LoadableFromPacket for TypedCommand {
|
|||
CommandCode::BitmapLinearWinZstd => {
|
||||
load_as_typed::<BitmapCommand>(header, payload)
|
||||
}
|
||||
CommandCode::Multi => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue