add LoadableFromPacket trait
two tests are failing
This commit is contained in:
parent
e2d6529e06
commit
9ac5ff7186
21 changed files with 414 additions and 410 deletions
|
|
@ -2,8 +2,8 @@ use crate::{
|
|||
command_code::{CommandCode, InvalidCommandCodeError},
|
||||
commands::errors::{TryFromPacketError, TryIntoPacketError},
|
||||
compression::{compress, decompress},
|
||||
Bitmap, CompressionCode, DataRef, Grid, Header, Origin, Packet, Pixels,
|
||||
TypedCommand, TILE_SIZE,
|
||||
Bitmap, CompressionCode, DataRef, Grid, Header, LoadableFromPacket, Origin,
|
||||
Packet, Pixels, TypedCommand, TILE_SIZE,
|
||||
};
|
||||
|
||||
/// Overwrites a rectangular region of pixels.
|
||||
|
|
@ -49,10 +49,7 @@ impl TryFrom<&BitmapCommand> for Packet {
|
|||
let command =
|
||||
BitmapCommand::command_code_for_compression(value.compression);
|
||||
let data_ref = value.bitmap.data_ref();
|
||||
let payload = match compress(value.compression, data_ref) {
|
||||
Ok(payload) => payload,
|
||||
Err(_) => return Err(TryIntoPacketError::CompressionFailed),
|
||||
};
|
||||
let payload = compress(value.compression, data_ref)?;
|
||||
|
||||
Ok(Packet {
|
||||
header: Header {
|
||||
|
|
@ -75,50 +72,52 @@ impl TryFrom<BitmapCommand> for Packet {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for BitmapCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let code = CommandCode::try_from(packet.header.command_code)?;
|
||||
impl LoadableFromPacket for BitmapCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let code = CommandCode::try_from(header.command_code)?;
|
||||
let compression = BitmapCommand::compression_for_command_code(code)
|
||||
.ok_or(InvalidCommandCodeError(packet.header.command_code))?;
|
||||
.ok_or(InvalidCommandCodeError(header.command_code))?;
|
||||
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code: _,
|
||||
a: tiles_x,
|
||||
b: pixels_y,
|
||||
c: tile_w,
|
||||
d: pixel_h,
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
let Header {
|
||||
command_code: _,
|
||||
a: tiles_x,
|
||||
b: pixels_y,
|
||||
c: tile_w,
|
||||
d: pixel_h,
|
||||
} = *header;
|
||||
let tile_w = tile_w as usize;
|
||||
let pixel_h = pixel_h as usize;
|
||||
let tiles_x = tiles_x as usize;
|
||||
let pixels_y = pixels_y as usize;
|
||||
|
||||
let expected = tile_w as usize * pixel_h as usize;
|
||||
let payload =
|
||||
payload.ok_or(TryFromPacketError::UnexpectedPayloadSize {
|
||||
actual: 0,
|
||||
expected,
|
||||
})?;
|
||||
let expected_bytes = tile_w * pixel_h;
|
||||
let (payload, read_payload_bytes) =
|
||||
match decompress(compression, &payload, expected) {
|
||||
Ok(payload) => payload,
|
||||
Err(_) => return Err(TryFromPacketError::DecompressionFailed),
|
||||
};
|
||||
decompress(compression, &payload, expected_bytes)
|
||||
.map_err(|_| TryFromPacketError::DecompressionFailed)?;
|
||||
if expected_bytes < payload.len() {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: expected_bytes,
|
||||
actual: payload.len(),
|
||||
});
|
||||
}
|
||||
let bitmap = Bitmap::load(
|
||||
tile_w as usize * TILE_SIZE,
|
||||
pixel_h as usize,
|
||||
&payload,
|
||||
tile_w * TILE_SIZE,
|
||||
pixel_h,
|
||||
&payload[..expected_bytes],
|
||||
)?;
|
||||
let origin =
|
||||
Origin::new(tiles_x as usize * TILE_SIZE, pixels_y as usize);
|
||||
let origin = Origin::new(tiles_x * TILE_SIZE, pixels_y);
|
||||
|
||||
Ok(Self {
|
||||
bitmap,
|
||||
origin,
|
||||
compression,
|
||||
})
|
||||
Ok((
|
||||
Self {
|
||||
bitmap,
|
||||
origin,
|
||||
compression,
|
||||
},
|
||||
read_payload_bytes,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,11 +202,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn error_decompression_failed_win() {
|
||||
for compression in CompressionCode::ALL {
|
||||
for compression in CompressionCode::ALL.to_owned() {
|
||||
let p: Packet = BitmapCommand {
|
||||
origin: Origin::new(16, 8),
|
||||
bitmap: Bitmap::new(8, 8).unwrap(),
|
||||
compression: *compression,
|
||||
compression: compression,
|
||||
}
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
|
@ -225,7 +224,7 @@ mod tests {
|
|||
payload: Some(payload),
|
||||
};
|
||||
let result = TypedCommand::try_from(p);
|
||||
if *compression != CompressionCode::Uncompressed {
|
||||
if compression != CompressionCode::Uncompressed {
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(TryFromPacketError::DecompressionFailed)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#![allow(deprecated, reason = "this implements the deprecated functionality")]
|
||||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code_only,
|
||||
commands::errors::TryFromPacketError, Packet, TypedCommand,
|
||||
commands::errors::TryFromPacketError, Header, LoadableFromPacket, Packet,
|
||||
TypedCommand,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
|
@ -21,17 +22,13 @@ use std::fmt::Debug;
|
|||
#[deprecated]
|
||||
pub struct BitmapLegacyCommand;
|
||||
|
||||
impl TryFrom<Packet> for BitmapLegacyCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
||||
if let Some(e) =
|
||||
check_command_code_only(value, CommandCode::BitmapLegacy)
|
||||
{
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(Self)
|
||||
}
|
||||
impl LoadableFromPacket for BitmapLegacyCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
_: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
check_command_code_only(header, CommandCode::BitmapLegacy)?;
|
||||
Ok((Self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ use crate::{
|
|||
command_code::{CommandCode, InvalidCommandCodeError},
|
||||
commands::errors::TryFromPacketError,
|
||||
compression::{compress, decompress},
|
||||
CompressionCode, DisplayBitVec, Header, Offset, Packet, TryIntoPacketError,
|
||||
TypedCommand,
|
||||
CompressionCode, DisplayBitVec, Header, LoadableFromPacket, Offset, Packet,
|
||||
TryIntoPacketError, TypedCommand,
|
||||
};
|
||||
|
||||
/// Binary operations for use with the [`BitVecCommand`] command.
|
||||
|
|
@ -66,10 +66,7 @@ impl TryFrom<&BitVecCommand> for Packet {
|
|||
|
||||
let data_ref = value.bitvec.as_raw_slice();
|
||||
let length = data_ref.len().try_into()?;
|
||||
let payload = match compress(value.compression, data_ref) {
|
||||
Ok(payload) => payload,
|
||||
Err(_) => return Err(TryIntoPacketError::CompressionFailed),
|
||||
};
|
||||
let payload = compress(value.compression, data_ref)?;
|
||||
Ok(Packet {
|
||||
header: Header {
|
||||
command_code: command_code.into(),
|
||||
|
|
@ -83,22 +80,20 @@ impl TryFrom<&BitVecCommand> for Packet {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for BitVecCommand {
|
||||
type Error = TryFromPacketError;
|
||||
impl LoadableFromPacket for BitVecCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let Header {
|
||||
command_code,
|
||||
a: offset,
|
||||
b: expected_len,
|
||||
c: sub,
|
||||
d: reserved,
|
||||
..
|
||||
} = *header;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code,
|
||||
a: offset,
|
||||
b: expected_len,
|
||||
c: sub,
|
||||
d: reserved,
|
||||
..
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
let expected_len = expected_len as usize;
|
||||
let command_code = CommandCode::try_from(command_code)?;
|
||||
let operation = match command_code {
|
||||
|
|
@ -114,29 +109,26 @@ impl TryFrom<Packet> for BitVecCommand {
|
|||
if reserved != 0 {
|
||||
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
||||
}
|
||||
|
||||
let compression = CompressionCode::try_from(sub)?;
|
||||
let payload =
|
||||
payload.ok_or(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: expected_len,
|
||||
actual: 0,
|
||||
})?;
|
||||
let (payload, read_payload_bytes) =
|
||||
match decompress(compression, &payload, expected_len) {
|
||||
Ok(payload) => payload,
|
||||
Err(_) => return Err(TryFromPacketError::DecompressionFailed),
|
||||
};
|
||||
if payload.len() != expected_len {
|
||||
decompress(compression, &payload, expected_len)
|
||||
.map_err(|_| TryFromPacketError::DecompressionFailed)?;
|
||||
if payload.len() < expected_len {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: expected_len,
|
||||
actual: payload.len(),
|
||||
});
|
||||
}
|
||||
Ok(Self {
|
||||
offset: offset as Offset,
|
||||
bitvec: DisplayBitVec::from_vec(payload),
|
||||
compression,
|
||||
operation,
|
||||
})
|
||||
Ok((
|
||||
Self {
|
||||
offset: offset as Offset,
|
||||
bitvec: DisplayBitVec::from_slice(&payload[..expected_len]),
|
||||
compression,
|
||||
operation,
|
||||
},
|
||||
read_payload_bytes,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code,
|
||||
commands::errors::TryFromPacketError, BrightnessGrid, ByteGrid, Header,
|
||||
Origin, Packet, Tiles, TryIntoPacketError, TypedCommand,
|
||||
LoadableFromPacket, Origin, Packet, Tiles, TryIntoPacketError,
|
||||
TypedCommand,
|
||||
};
|
||||
|
||||
/// Set the brightness of individual tiles in a rectangular area of the display.
|
||||
|
|
@ -46,55 +47,46 @@ impl From<BrightnessGrid> for BrightnessGridCommand {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for BrightnessGridCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code,
|
||||
a: x,
|
||||
b: y,
|
||||
c: width,
|
||||
d: height,
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
impl LoadableFromPacket for BrightnessGridCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let Header {
|
||||
command_code,
|
||||
a: x,
|
||||
b: y,
|
||||
c: width,
|
||||
d: height,
|
||||
} = *header;
|
||||
|
||||
check_command_code(command_code, CommandCode::CharBrightness)?;
|
||||
|
||||
let expected_size = width as usize * height as usize;
|
||||
let payload = match payload {
|
||||
None => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
actual: 0,
|
||||
expected: expected_size,
|
||||
})
|
||||
}
|
||||
Some(payload) if payload.len() != expected_size => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
actual: payload.len(),
|
||||
expected: expected_size,
|
||||
})
|
||||
}
|
||||
Some(payload) => payload,
|
||||
if payload.len() < expected_size {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
actual: payload.len(),
|
||||
expected: expected_size,
|
||||
});
|
||||
};
|
||||
|
||||
let grid = ByteGrid::from_raw_parts_unchecked(
|
||||
width as usize,
|
||||
height as usize,
|
||||
payload,
|
||||
payload[..expected_size].to_vec(),
|
||||
);
|
||||
let grid = match BrightnessGrid::try_from(grid) {
|
||||
Ok(grid) => grid,
|
||||
Err(val) => return Err(TryFromPacketError::InvalidBrightness(val)),
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
grid,
|
||||
origin: Origin::new(x as usize, y as usize),
|
||||
})
|
||||
Ok((
|
||||
Self {
|
||||
grid,
|
||||
origin: Origin::new(x as usize, y as usize),
|
||||
},
|
||||
expected_size,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code,
|
||||
commands::errors::TryFromPacketError, CharGrid, Header, Origin, Packet,
|
||||
Tiles, TryIntoPacketError, TypedCommand,
|
||||
commands::errors::TryFromPacketError, CharGrid, Header, LoadableFromPacket,
|
||||
Origin, Packet, Tiles, TryIntoPacketError, TypedCommand,
|
||||
};
|
||||
|
||||
/// Show text on the screen.
|
||||
|
|
@ -48,51 +48,44 @@ impl TryFrom<&CharGridCommand> for Packet {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for CharGridCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code,
|
||||
a: origin_x,
|
||||
b: origin_y,
|
||||
c: width,
|
||||
d: height,
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
impl LoadableFromPacket for CharGridCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let Header {
|
||||
command_code,
|
||||
a: origin_x,
|
||||
b: origin_y,
|
||||
c: width,
|
||||
d: height,
|
||||
} = *header;
|
||||
|
||||
check_command_code(command_code, CommandCode::Utf8Data)?;
|
||||
|
||||
let expected = width as usize * height as usize;
|
||||
let payload = match payload {
|
||||
None => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected,
|
||||
actual: 0,
|
||||
})
|
||||
}
|
||||
Some(payload) if payload.len() != expected => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected,
|
||||
actual: payload.len(),
|
||||
})
|
||||
}
|
||||
Some(payload) => {
|
||||
String::from_utf8(payload.clone())?.chars().collect()
|
||||
}
|
||||
};
|
||||
if payload.len() < expected {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected,
|
||||
actual: payload.len(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
origin: Origin::new(origin_x as usize, origin_y as usize),
|
||||
grid: CharGrid::from_raw_parts_unchecked(
|
||||
width as usize,
|
||||
height as usize,
|
||||
payload,
|
||||
),
|
||||
})
|
||||
// TODO this does not work as char != byte
|
||||
let payload = String::from_utf8(payload[..expected].to_vec())?
|
||||
.chars()
|
||||
.collect();
|
||||
Ok((
|
||||
Self {
|
||||
origin: Origin::new(origin_x as usize, origin_y as usize),
|
||||
grid: CharGrid::from_raw_parts_unchecked(
|
||||
width as usize,
|
||||
height as usize,
|
||||
payload,
|
||||
),
|
||||
},
|
||||
expected,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
command_code::CommandCode,
|
||||
commands::{check_command_code_only, errors::TryFromPacketError},
|
||||
Packet, TypedCommand,
|
||||
Header, LoadableFromPacket, Packet, TypedCommand,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
|
@ -17,15 +17,13 @@ use std::fmt::Debug;
|
|||
/// ```
|
||||
pub struct ClearCommand;
|
||||
|
||||
impl TryFrom<Packet> for ClearCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
||||
if let Some(e) = check_command_code_only(value, CommandCode::Clear) {
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(Self)
|
||||
}
|
||||
impl LoadableFromPacket for ClearCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
_: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
check_command_code_only(header, CommandCode::Clear)?;
|
||||
Ok((Self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,9 +48,10 @@ impl From<ClearCommand> for TypedCommand {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::command_code::InvalidCommandCodeError;
|
||||
use crate::commands::tests::TestImplementsCommand;
|
||||
use crate::Header;
|
||||
use crate::{
|
||||
command_code::InvalidCommandCodeError,
|
||||
commands::tests::TestImplementsCommand, Header,
|
||||
};
|
||||
|
||||
impl TestImplementsCommand for ClearCommand {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code,
|
||||
commands::errors::TryFromPacketError, Cp437Grid, Header, Origin, Packet,
|
||||
Tiles, TryIntoPacketError, TypedCommand,
|
||||
commands::errors::TryFromPacketError, Cp437Grid, Header,
|
||||
LoadableFromPacket, Origin, Packet, Tiles, TryIntoPacketError,
|
||||
TypedCommand,
|
||||
};
|
||||
|
||||
/// Show text on the screen.
|
||||
|
|
@ -61,49 +62,39 @@ impl TryFrom<&Cp437GridCommand> for Packet {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for Cp437GridCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code,
|
||||
a: origin_x,
|
||||
b: origin_y,
|
||||
c: width,
|
||||
d: height,
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
|
||||
impl LoadableFromPacket for Cp437GridCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let Header {
|
||||
command_code,
|
||||
a: origin_x,
|
||||
b: origin_y,
|
||||
c: width,
|
||||
d: height,
|
||||
} = *header;
|
||||
check_command_code(command_code, CommandCode::Cp437Data)?;
|
||||
|
||||
let expected = width as usize * height as usize;
|
||||
let payload = match payload {
|
||||
None => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected,
|
||||
actual: 0,
|
||||
})
|
||||
}
|
||||
Some(payload) if payload.len() != expected => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected,
|
||||
actual: payload.len(),
|
||||
})
|
||||
}
|
||||
Some(payload) => payload,
|
||||
};
|
||||
if payload.len() < expected {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected,
|
||||
actual: payload.len(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
origin: Origin::new(origin_x as usize, origin_y as usize),
|
||||
grid: Cp437Grid::from_raw_parts_unchecked(
|
||||
width as usize,
|
||||
height as usize,
|
||||
payload,
|
||||
),
|
||||
})
|
||||
Ok((
|
||||
Self {
|
||||
origin: Origin::new(origin_x as usize, origin_y as usize),
|
||||
grid: Cp437Grid::from_raw_parts_unchecked(
|
||||
width as usize,
|
||||
height as usize,
|
||||
Vec::from(&payload[..expected]),
|
||||
),
|
||||
},
|
||||
expected,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::compression::CompressionError;
|
||||
use crate::{
|
||||
command_code::InvalidCommandCodeError, InvalidCompressionCodeError,
|
||||
LoadBitmapError,
|
||||
|
|
@ -40,6 +41,8 @@ pub enum TryFromPacketError {
|
|||
/// The bitmap contained in the payload could not be loaded
|
||||
#[error(transparent)]
|
||||
LoadBitmapFailed(#[from] LoadBitmapError),
|
||||
#[error("The provided packet was too small to be loadable.")]
|
||||
TooSmall,
|
||||
}
|
||||
|
||||
/// An error that can occur when parsing a raw packet as a command
|
||||
|
|
@ -47,7 +50,7 @@ pub enum TryFromPacketError {
|
|||
pub enum TryIntoPacketError {
|
||||
/// Compression of the payload failed.
|
||||
#[error("The compression of the payload failed")]
|
||||
CompressionFailed,
|
||||
CompressionFailed(#[from] CompressionError),
|
||||
/// Conversion (probably to u16) failed
|
||||
#[error(transparent)]
|
||||
ConversionError(#[from] TryFromIntError),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code_only,
|
||||
commands::errors::TryFromPacketError, Packet, TypedCommand,
|
||||
commands::errors::TryFromPacketError, Header, LoadableFromPacket, Packet,
|
||||
TypedCommand,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
|
@ -18,15 +19,13 @@ use std::fmt::Debug;
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FadeOutCommand;
|
||||
|
||||
impl TryFrom<Packet> for FadeOutCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
||||
if let Some(e) = check_command_code_only(value, CommandCode::FadeOut) {
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(Self)
|
||||
}
|
||||
impl LoadableFromPacket for FadeOutCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
_: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
check_command_code_only(header, CommandCode::FadeOut)?;
|
||||
Ok((Self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,12 +99,12 @@ mod tests {
|
|||
payload: Some(vec![5, 7]),
|
||||
};
|
||||
let result = TypedCommand::try_from(p);
|
||||
assert!(matches!(
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: 0,
|
||||
actual: 2
|
||||
})
|
||||
));
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code,
|
||||
commands::errors::TryFromPacketError, Brightness, Header, Packet,
|
||||
TypedCommand,
|
||||
commands::errors::TryFromPacketError, Brightness, Header,
|
||||
LoadableFromPacket, Packet, TypedCommand,
|
||||
};
|
||||
|
||||
/// Set the brightness of all tiles to the same value.
|
||||
|
|
@ -41,21 +41,18 @@ impl From<&GlobalBrightnessCommand> for Packet {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for GlobalBrightnessCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
impl LoadableFromPacket for GlobalBrightnessCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let Header {
|
||||
command_code,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
} = *header;
|
||||
|
||||
check_command_code(command_code, CommandCode::Brightness)?;
|
||||
|
||||
|
|
@ -63,26 +60,16 @@ impl TryFrom<Packet> for GlobalBrightnessCommand {
|
|||
return Err(TryFromPacketError::ExtraneousHeaderValues);
|
||||
}
|
||||
|
||||
let brightness = match payload {
|
||||
None => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: 1,
|
||||
actual: 0,
|
||||
})
|
||||
}
|
||||
Some(payload) if payload.len() == 1 => payload[0],
|
||||
Some(payload) => {
|
||||
return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: 1,
|
||||
actual: payload.len(),
|
||||
});
|
||||
}
|
||||
};
|
||||
let brightness = *payload.get(0).ok_or(
|
||||
TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: 1,
|
||||
actual: 0,
|
||||
},
|
||||
)?;
|
||||
|
||||
match Brightness::try_from(brightness) {
|
||||
Ok(brightness) => Ok(Self { brightness }),
|
||||
Err(_) => Err(TryFromPacketError::InvalidBrightness(brightness)),
|
||||
}
|
||||
let brightness = Brightness::try_from(brightness)
|
||||
.map_err(|_| TryFromPacketError::InvalidBrightness(brightness))?;
|
||||
Ok((Self { brightness }, 1))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,24 +145,27 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn unexpected_payload_size_brightness() {
|
||||
fn unexpected_payload_size() {
|
||||
let mut packet = Packet {
|
||||
header: Header {
|
||||
command_code: CommandCode::Brightness.into(),
|
||||
a: 0,
|
||||
b: 0,
|
||||
c: 0,
|
||||
d: 0,
|
||||
},
|
||||
payload: None,
|
||||
};
|
||||
assert_eq!(
|
||||
TypedCommand::try_from(Packet {
|
||||
header: Header {
|
||||
command_code: CommandCode::Brightness.into(),
|
||||
a: 0,
|
||||
b: 0,
|
||||
c: 0,
|
||||
d: 0,
|
||||
},
|
||||
payload: None
|
||||
}),
|
||||
TypedCommand::try_from(packet.clone()),
|
||||
Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: 1,
|
||||
actual: 0
|
||||
})
|
||||
);
|
||||
|
||||
packet.payload = Some(vec![0; 2]);
|
||||
|
||||
assert_eq!(
|
||||
TypedCommand::try_from(Packet {
|
||||
header: Header {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::check_command_code_only,
|
||||
commands::errors::TryFromPacketError, Packet, TypedCommand,
|
||||
commands::errors::TryFromPacketError, Header, LoadableFromPacket, Packet,
|
||||
TypedCommand,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
|
@ -18,16 +19,13 @@ use std::fmt::Debug;
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct HardResetCommand;
|
||||
|
||||
impl TryFrom<Packet> for HardResetCommand {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
||||
if let Some(e) = check_command_code_only(value, CommandCode::HardReset)
|
||||
{
|
||||
Err(e)
|
||||
} else {
|
||||
Ok(Self)
|
||||
}
|
||||
impl LoadableFromPacket for HardResetCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
_: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
check_command_code_only(header, CommandCode::HardReset)?;
|
||||
Ok((Self, 0))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,8 +50,7 @@ impl From<HardResetCommand> for TypedCommand {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::commands::tests::TestImplementsCommand;
|
||||
use crate::Header;
|
||||
use crate::{commands::tests::TestImplementsCommand, Header};
|
||||
|
||||
impl TestImplementsCommand for HardResetCommand {}
|
||||
|
||||
|
|
|
|||
|
|
@ -77,41 +77,103 @@ pub use typed::*;
|
|||
/// connection.send_command(command).unwrap();
|
||||
/// ```
|
||||
pub trait Command:
|
||||
Debug + Clone + Eq + TryInto<Packet> + TryFrom<Packet> + Hash
|
||||
Debug
|
||||
+ Clone
|
||||
+ Eq
|
||||
+ TryInto<Packet>
|
||||
+ LoadableFromPacket
|
||||
+ TryFrom<Packet>
|
||||
+ Hash
|
||||
{
|
||||
}
|
||||
|
||||
impl<T: Debug + Clone + Eq + TryInto<Packet> + TryFrom<Packet> + Hash> Command
|
||||
for T
|
||||
impl<
|
||||
T: Debug
|
||||
+ Clone
|
||||
+ Eq
|
||||
+ TryInto<Packet>
|
||||
+ LoadableFromPacket
|
||||
+ TryFrom<Packet>
|
||||
+ Hash,
|
||||
> Command for T
|
||||
{
|
||||
}
|
||||
|
||||
pub trait LoadableFromPacket: Sized {
|
||||
/// Load the specified header and payload.
|
||||
///
|
||||
/// In case of success, returns a tuple of Self and the number of bytes read from payload.
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError>;
|
||||
|
||||
/// Load the specified bytes.
|
||||
///
|
||||
/// In case of success, returns a tuple of Self and the number of bytes read from the buffer.
|
||||
fn from_bytes(buf: &[u8]) -> Result<(Self, usize), TryFromPacketError> {
|
||||
let (header, bytes_header) =
|
||||
Header::read_from(buf).ok_or(TryFromPacketError::TooSmall)?;
|
||||
let (result, bytes_payload) =
|
||||
Self::load(&header, &buf[bytes_header..])?;
|
||||
Ok((result, bytes_header + bytes_payload))
|
||||
}
|
||||
}
|
||||
|
||||
// Because of the orphan rule, the following is not possible:
|
||||
// impl<T: LoadableCommand> TryFrom<Packet> for T { .. }
|
||||
//
|
||||
// This macro is used instead to provide the implementation.
|
||||
macro_rules! derive_try_from_packet {
|
||||
($T:ty) => {
|
||||
#[allow(unused, reason = "Macro is used with a deprecated type")]
|
||||
impl TryFrom<Packet> for $T {
|
||||
type Error = TryFromPacketError;
|
||||
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
let payload = packet.payload.as_deref().unwrap_or(&[]);
|
||||
let (result, read_bytes) = Self::load(&packet.header, payload)?;
|
||||
//if payload.len() != read_bytes {
|
||||
// return Err(TryFromPacketError::UnexpectedPayloadSize {
|
||||
// actual: payload.len(),
|
||||
// expected: read_bytes,
|
||||
// });
|
||||
//}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
derive_try_from_packet!(BitmapCommand);
|
||||
derive_try_from_packet!(BitmapLegacyCommand);
|
||||
derive_try_from_packet!(BitVecCommand);
|
||||
derive_try_from_packet!(BrightnessGridCommand);
|
||||
derive_try_from_packet!(CharGridCommand);
|
||||
derive_try_from_packet!(ClearCommand);
|
||||
derive_try_from_packet!(Cp437GridCommand);
|
||||
derive_try_from_packet!(FadeOutCommand);
|
||||
derive_try_from_packet!(GlobalBrightnessCommand);
|
||||
derive_try_from_packet!(HardResetCommand);
|
||||
derive_try_from_packet!(TypedCommand);
|
||||
|
||||
fn check_command_code_only(
|
||||
packet: Packet,
|
||||
header: &Header,
|
||||
code: CommandCode,
|
||||
) -> Option<TryFromPacketError> {
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code: _,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
},
|
||||
payload,
|
||||
} = packet;
|
||||
if packet.header.command_code != u16::from(code) {
|
||||
Some(InvalidCommandCodeError(packet.header.command_code).into())
|
||||
} else if let Some(payload) = payload {
|
||||
Some(TryFromPacketError::UnexpectedPayloadSize {
|
||||
expected: 0,
|
||||
actual: payload.len(),
|
||||
})
|
||||
} else if a != 0 || b != 0 || c != 0 || d != 0 {
|
||||
Some(TryFromPacketError::ExtraneousHeaderValues)
|
||||
} else {
|
||||
None
|
||||
) -> Result<(), TryFromPacketError> {
|
||||
let code = u16::from(code);
|
||||
match header {
|
||||
Header { command_code, .. } if *command_code != code => {
|
||||
Err(InvalidCommandCodeError(*command_code).into())
|
||||
}
|
||||
Header {
|
||||
command_code: _,
|
||||
a: 0,
|
||||
b: 0,
|
||||
c: 0,
|
||||
d: 0,
|
||||
} => Ok(()),
|
||||
_ => Err(TryFromPacketError::ExtraneousHeaderValues),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -138,19 +200,13 @@ mod tests {
|
|||
|
||||
pub(crate) fn round_trip(original: TypedCommand) {
|
||||
let packet: Packet = original.clone().try_into().unwrap();
|
||||
let copy: TypedCommand = match TypedCommand::try_from(packet) {
|
||||
Ok(command) => command,
|
||||
Err(err) => panic!("could not reload {original:?}: {err:?}"),
|
||||
};
|
||||
let copy: TypedCommand = TypedCommand::try_from(packet).unwrap();
|
||||
assert_eq!(copy, original);
|
||||
}
|
||||
|
||||
pub(crate) fn round_trip_ref(original: &TypedCommand) {
|
||||
let packet: Packet = original.try_into().unwrap();
|
||||
let copy: TypedCommand = match TypedCommand::try_from(packet) {
|
||||
Ok(command) => command,
|
||||
Err(err) => panic!("could not reload {original:?}: {err:?}"),
|
||||
};
|
||||
let copy: TypedCommand = TypedCommand::try_from(packet).unwrap();
|
||||
assert_eq!(©, original);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use crate::{
|
||||
command_code::CommandCode, commands::errors::TryFromPacketError,
|
||||
BitVecCommand, BitmapCommand, BrightnessGridCommand, CharGridCommand,
|
||||
ClearCommand, Cp437GridCommand, FadeOutCommand, GlobalBrightnessCommand,
|
||||
HardResetCommand, Packet, TryIntoPacketError,
|
||||
BitVecCommand, BitmapCommand, BitmapLegacyCommand, BrightnessGridCommand,
|
||||
CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand,
|
||||
GlobalBrightnessCommand, HardResetCommand, Header, LoadableFromPacket,
|
||||
Packet, TryIntoPacketError,
|
||||
};
|
||||
|
||||
/// This enum contains all commands provided by the library.
|
||||
|
|
@ -26,63 +27,71 @@ pub enum TypedCommand {
|
|||
BitmapLegacy(crate::BitmapLegacyCommand),
|
||||
}
|
||||
|
||||
impl TryFrom<Packet> for TypedCommand {
|
||||
type Error = TryFromPacketError;
|
||||
impl LoadableFromPacket for TypedCommand {
|
||||
fn load(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(Self, usize), TryFromPacketError> {
|
||||
fn load_as_typed<T: LoadableFromPacket + Into<TypedCommand>>(
|
||||
header: &Header,
|
||||
payload: &[u8],
|
||||
) -> Result<(TypedCommand, usize), TryFromPacketError> {
|
||||
let (cmd, read) = T::load(header, payload)?;
|
||||
Ok((cmd.into(), read))
|
||||
}
|
||||
|
||||
/// Try to interpret the [Packet] as one containing a [`TypedCommand`]
|
||||
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
|
||||
Ok(match CommandCode::try_from(packet.header.command_code)? {
|
||||
match CommandCode::try_from(header.command_code)? {
|
||||
CommandCode::Clear => {
|
||||
TypedCommand::Clear(crate::ClearCommand::try_from(packet)?)
|
||||
load_as_typed::<ClearCommand>(header, payload)
|
||||
}
|
||||
CommandCode::Brightness => {
|
||||
load_as_typed::<GlobalBrightnessCommand>(header, payload)
|
||||
}
|
||||
CommandCode::HardReset => {
|
||||
load_as_typed::<HardResetCommand>(header, payload)
|
||||
}
|
||||
CommandCode::Brightness => TypedCommand::Brightness(
|
||||
crate::GlobalBrightnessCommand::try_from(packet)?,
|
||||
),
|
||||
CommandCode::HardReset => TypedCommand::HardReset(
|
||||
crate::HardResetCommand::try_from(packet)?,
|
||||
),
|
||||
CommandCode::FadeOut => {
|
||||
TypedCommand::FadeOut(crate::FadeOutCommand::try_from(packet)?)
|
||||
load_as_typed::<FadeOutCommand>(header, payload)
|
||||
}
|
||||
CommandCode::Cp437Data => {
|
||||
load_as_typed::<Cp437GridCommand>(header, payload)
|
||||
}
|
||||
CommandCode::CharBrightness => {
|
||||
load_as_typed::<BrightnessGridCommand>(header, payload)
|
||||
}
|
||||
CommandCode::Utf8Data => {
|
||||
load_as_typed::<CharGridCommand>(header, payload)
|
||||
}
|
||||
CommandCode::Cp437Data => TypedCommand::Cp437Grid(
|
||||
crate::Cp437GridCommand::try_from(packet)?,
|
||||
),
|
||||
CommandCode::CharBrightness => TypedCommand::BrightnessGrid(
|
||||
crate::BrightnessGridCommand::try_from(packet)?,
|
||||
),
|
||||
CommandCode::Utf8Data => TypedCommand::CharGrid(
|
||||
crate::CharGridCommand::try_from(packet)?,
|
||||
),
|
||||
#[allow(deprecated)]
|
||||
CommandCode::BitmapLegacy => TypedCommand::BitmapLegacy(
|
||||
crate::BitmapLegacyCommand::try_from(packet)?,
|
||||
),
|
||||
CommandCode::BitmapLegacy => {
|
||||
load_as_typed::<BitmapLegacyCommand>(header, payload)
|
||||
}
|
||||
CommandCode::BitmapLinear
|
||||
| CommandCode::BitmapLinearOr
|
||||
| CommandCode::BitmapLinearAnd
|
||||
| CommandCode::BitmapLinearXor => {
|
||||
TypedCommand::BitVec(crate::BitVecCommand::try_from(packet)?)
|
||||
load_as_typed::<BitVecCommand>(header, payload)
|
||||
}
|
||||
CommandCode::BitmapLinearWinUncompressed => {
|
||||
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
|
||||
load_as_typed::<BitmapCommand>(header, payload)
|
||||
}
|
||||
#[cfg(feature = "compression_zlib")]
|
||||
CommandCode::BitmapLinearWinZlib => {
|
||||
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
|
||||
load_as_typed::<BitmapCommand>(header, payload)
|
||||
}
|
||||
#[cfg(feature = "compression_bzip2")]
|
||||
CommandCode::BitmapLinearWinBzip2 => {
|
||||
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
|
||||
load_as_typed::<BitmapCommand>(header, payload)
|
||||
}
|
||||
#[cfg(feature = "compression_lzma")]
|
||||
CommandCode::BitmapLinearWinLzma => {
|
||||
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
|
||||
load_as_typed::<BitmapCommand>(header, payload)
|
||||
}
|
||||
#[cfg(feature = "compression_zstd")]
|
||||
CommandCode::BitmapLinearWinZstd => {
|
||||
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
|
||||
load_as_typed::<BitmapCommand>(header, payload)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,19 +99,7 @@ impl TryFrom<TypedCommand> for Packet {
|
|||
type Error = TryIntoPacketError;
|
||||
|
||||
fn try_from(value: TypedCommand) -> Result<Self, Self::Error> {
|
||||
Ok(match value {
|
||||
TypedCommand::Clear(c) => c.into(),
|
||||
TypedCommand::CharGrid(c) => c.try_into()?,
|
||||
TypedCommand::Cp437Grid(c) => c.try_into()?,
|
||||
TypedCommand::Bitmap(c) => c.try_into()?,
|
||||
TypedCommand::Brightness(c) => c.into(),
|
||||
TypedCommand::BrightnessGrid(c) => c.try_into()?,
|
||||
TypedCommand::BitVec(c) => c.try_into()?,
|
||||
TypedCommand::HardReset(c) => c.into(),
|
||||
TypedCommand::FadeOut(c) => c.into(),
|
||||
#[allow(deprecated)]
|
||||
TypedCommand::BitmapLegacy(c) => c.into(),
|
||||
})
|
||||
Packet::try_from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use bzip2::{
|
|||
use log::error;
|
||||
use std::io::Read;
|
||||
|
||||
pub struct Bzip2;
|
||||
pub(crate) struct Bzip2;
|
||||
|
||||
impl CompressionAlgo for Bzip2 {
|
||||
const CODE: CompressionCode = CompressionCode::Bzip2;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,19 @@ pub struct Lzma;
|
|||
|
||||
impl CompressionAlgo for Lzma {
|
||||
const CODE: CompressionCode = CompressionCode::Lzma;
|
||||
|
||||
fn compress(payload: &[u8]) -> Result<Payload, CompressionError> {
|
||||
lzma::compress(payload, 6).map_err(|e| {
|
||||
error!("failed to compress data: {e}");
|
||||
CompressionError::CompressionFailed
|
||||
})
|
||||
}
|
||||
|
||||
fn decompress(
|
||||
payload: &[u8],
|
||||
_: usize,
|
||||
expected_size_hint: usize,
|
||||
) -> Result<(Vec<u8>, usize), CompressionError> {
|
||||
let mut output: Vec<u8> = Vec::new();
|
||||
let mut output: Vec<u8> = Vec::with_capacity(expected_size_hint);
|
||||
let mut reader = LzmaReader::new_decompressor(payload)
|
||||
.map_err(|_| CompressionError::LibraryError)?;
|
||||
let read = reader
|
||||
|
|
@ -22,10 +30,4 @@ impl CompressionAlgo for Lzma {
|
|||
.map_err(|_| CompressionError::CompressionFailed)?;
|
||||
Ok((output, read))
|
||||
}
|
||||
fn compress(payload: &[u8]) -> Result<Payload, CompressionError> {
|
||||
lzma::compress(payload, 6).map_err(|e| {
|
||||
error!("failed to compress data: {e}");
|
||||
CompressionError::CompressionFailed
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
CompressionCode,
|
||||
};
|
||||
|
||||
pub struct Uncompressed;
|
||||
pub(crate) struct Uncompressed;
|
||||
|
||||
impl CompressionAlgo for Uncompressed {
|
||||
const CODE: CompressionCode = CompressionCode::Uncompressed;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
use flate2::{FlushCompress, FlushDecompress, Status};
|
||||
use log::error;
|
||||
|
||||
pub struct Zlib;
|
||||
pub(crate) struct Zlib;
|
||||
|
||||
impl CompressionAlgo for Zlib {
|
||||
const CODE: CompressionCode = CompressionCode::Zlib;
|
||||
|
|
|
|||
|
|
@ -6,10 +6,11 @@ use log::error;
|
|||
use std::io::{Read, Write};
|
||||
use zstd::{Decoder, Encoder, DEFAULT_COMPRESSION_LEVEL};
|
||||
|
||||
pub struct Zstd;
|
||||
pub(crate) struct Zstd;
|
||||
|
||||
impl CompressionAlgo for Zstd {
|
||||
const CODE: CompressionCode = CompressionCode::Zstd;
|
||||
|
||||
fn compress(payload: &[u8]) -> Result<Payload, CompressionError> {
|
||||
let buf = Vec::with_capacity(payload.len());
|
||||
let mut encoder = Encoder::new(buf, DEFAULT_COMPRESSION_LEVEL)
|
||||
|
|
@ -28,6 +29,7 @@ impl CompressionAlgo for Zstd {
|
|||
CompressionError::CompressionFailed
|
||||
})
|
||||
}
|
||||
|
||||
fn decompress(
|
||||
payload: &[u8],
|
||||
expected_size_hint: usize,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ pub trait Grid<T> {
|
|||
|
||||
/// Checks whether the specified signed position is in grid bounds
|
||||
#[must_use]
|
||||
#[inline]
|
||||
fn is_in_bounds(&self, x: usize, y: usize) -> bool {
|
||||
x < self.width() && y < self.height()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,4 +45,12 @@ impl Header {
|
|||
|
||||
Some((header, read_size))
|
||||
}
|
||||
|
||||
pub(crate) fn write_to(&self, slice: &mut [u8]) {
|
||||
slice[0..=1].copy_from_slice(&u16::to_be_bytes(self.command_code));
|
||||
slice[2..=3].copy_from_slice(&u16::to_be_bytes(self.a));
|
||||
slice[4..=5].copy_from_slice(&u16::to_be_bytes(self.b));
|
||||
slice[6..=7].copy_from_slice(&u16::to_be_bytes(self.c));
|
||||
slice[8..=9].copy_from_slice(&u16::to_be_bytes(self.d));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,23 +74,9 @@ impl Packet {
|
|||
return None;
|
||||
}
|
||||
|
||||
let Packet {
|
||||
header:
|
||||
Header {
|
||||
command_code,
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
},
|
||||
payload,
|
||||
} = self;
|
||||
let Packet { header, payload } = self;
|
||||
|
||||
slice[0..=1].copy_from_slice(&u16::to_be_bytes(*command_code));
|
||||
slice[2..=3].copy_from_slice(&u16::to_be_bytes(*a));
|
||||
slice[4..=5].copy_from_slice(&u16::to_be_bytes(*b));
|
||||
slice[6..=7].copy_from_slice(&u16::to_be_bytes(*c));
|
||||
slice[8..=9].copy_from_slice(&u16::to_be_bytes(*d));
|
||||
header.write_to(slice);
|
||||
|
||||
if let Some(payload) = payload {
|
||||
slice[10..][..payload.len()].copy_from_slice(payload);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue