Compare commits

...

3 commits

Author SHA1 Message Date
Vinzenz Schroeter d6229ece87 adjust mod structure
Some checks failed
Rust / build (pull_request) Failing after 1m4s
2025-03-08 12:09:07 +01:00
Vinzenz Schroeter 03f84c337f adjust tests for higher coverage 2025-03-08 11:56:49 +01:00
Vinzenz Schroeter 2ff49aaf7a move TypedCommand to own mod 2025-03-08 11:47:25 +01:00
11 changed files with 188 additions and 183 deletions

View file

@ -50,13 +50,14 @@
mod bitmap; mod bitmap;
mod bitmap_legacy; mod bitmap_legacy;
mod bitvec; mod bitvec;
mod char_brightness; mod brightness_grid;
mod clear; mod clear;
mod cp437_data; mod cp437_grid;
mod fade_out; mod fade_out;
mod global_brightness; mod brightness;
mod hard_reset; mod hard_reset;
mod utf8_data; mod typed;
mod char_grid;
use crate::command_code::CommandCode; use crate::command_code::CommandCode;
use crate::*; use crate::*;
@ -65,166 +66,20 @@ use std::fmt::Debug;
pub use bitmap::*; pub use bitmap::*;
pub use bitmap_legacy::*; pub use bitmap_legacy::*;
pub use bitvec::*; pub use bitvec::*;
pub use char_brightness::*; pub use brightness_grid::*;
pub use clear::*; pub use clear::*;
pub use cp437_data::*; pub use cp437_grid::*;
pub use fade_out::*; pub use fade_out::*;
pub use global_brightness::*; pub use brightness::*;
pub use hard_reset::*; pub use hard_reset::*;
pub use utf8_data::*; pub use typed::*;
pub use char_grid::*;
/// Represents a command that can be sent to the display. /// Represents a command that can be sent to the display.
pub trait Command: Debug + Clone + PartialEq + Into<Packet> {} pub trait Command: Debug + Clone + PartialEq + Into<Packet> {}
impl<T: Debug + Clone + PartialEq + Into<Packet>> Command for T {} impl<T: Debug + Clone + PartialEq + Into<Packet>> Command for T {}
/// This enum contains all commands provided by the library.
/// This is useful in case you want one data type for all kinds of commands without using `dyn`.
///
/// Please look at the contained structs for documentation per command.
#[derive(Debug, Clone, PartialEq)]
#[allow(missing_docs)]
pub enum TypedCommand {
Clear(ClearCommand),
CharGrid(CharGridCommand),
Cp437Grid(Cp437GridCommand),
Bitmap(BitmapCommand),
Brightness(BrightnessCommand),
BrightnessGrid(BrightnessGridCommand),
BitVec(BitVecCommand),
HardReset(HardResetCommand),
FadeOut(FadeOutCommand),
#[allow(deprecated)]
#[deprecated]
BitmapLegacy(BitmapLegacyCommand),
}
/// Err values for [TypedCommand::try_from].
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum TryFromPacketError {
/// the contained command code does not correspond to a known command
#[error("The command code {0:?} does not correspond to a known command")]
InvalidCommand(u16),
/// the expected payload size was n, but size m was found
#[error("the expected payload size was {0}, but size {1} was found")]
UnexpectedPayloadSize(usize, usize),
/// Header fields not needed for the command have been used.
///
/// Note that these commands would usually still work on the actual display.
#[error("Header fields not needed for the command have been used")]
ExtraneousHeaderValues,
/// The contained compression code is not known. This could be of disabled features.
#[error("The compression code {0:?} does not correspond to a known compression algorithm.")]
InvalidCompressionCode(u16),
/// Decompression of the payload failed. This can be caused by corrupted packets.
#[error("The decompression of the payload failed")]
DecompressionFailed,
/// The given brightness value is out of bounds
#[error("The given brightness value {0} is out of bounds.")]
InvalidBrightness(u8),
/// Some provided text was not valid UTF-8.
#[error(transparent)]
InvalidUtf8(#[from] std::string::FromUtf8Error),
}
impl TryFrom<Packet> for TypedCommand {
type Error = TryFromPacketError;
/// Try to interpret the [Packet] as one containing a [Command]
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
let Packet {
header: Header { command_code, .. },
..
} = packet;
let command_code = match CommandCode::try_from(command_code) {
Err(()) => {
return Err(TryFromPacketError::InvalidCommand(command_code));
}
Ok(value) => value,
};
Ok(match command_code {
CommandCode::Clear => {
TypedCommand::Clear(commands::ClearCommand::try_from(packet)?)
}
CommandCode::Brightness => TypedCommand::Brightness(
commands::BrightnessCommand::try_from(packet)?,
),
CommandCode::HardReset => {
TypedCommand::HardReset(commands::HardResetCommand::try_from(packet)?)
}
CommandCode::FadeOut => {
TypedCommand::FadeOut(commands::FadeOutCommand::try_from(packet)?)
}
CommandCode::Cp437Data => {
TypedCommand::Cp437Grid(commands::Cp437GridCommand::try_from(packet)?)
}
CommandCode::CharBrightness => {
TypedCommand::BrightnessGrid(commands::BrightnessGridCommand::try_from(packet)?)
}
CommandCode::Utf8Data => {
TypedCommand::CharGrid(commands::CharGridCommand::try_from(packet)?)
}
#[allow(deprecated)]
CommandCode::BitmapLegacy => {
TypedCommand::BitmapLegacy(commands::BitmapLegacyCommand::try_from(packet)?)
}
CommandCode::BitmapLinear
| CommandCode::BitmapLinearOr
| CommandCode::BitmapLinearAnd
| CommandCode::BitmapLinearXor => {
TypedCommand::BitVec(commands::BitVecCommand::try_from(packet)?)
}
CommandCode::BitmapLinearWinUncompressed => {
TypedCommand::Bitmap(commands::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_zlib")]
CommandCode::BitmapLinearWinZlib => {
TypedCommand::Bitmap(commands::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_bzip2")]
CommandCode::BitmapLinearWinBzip2 => {
TypedCommand::Bitmap(commands::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_lzma")]
CommandCode::BitmapLinearWinLzma => {
TypedCommand::Bitmap(commands::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_zstd")]
CommandCode::BitmapLinearWinZstd => {
TypedCommand::Bitmap(commands::BitmapCommand::try_from(packet)?)
}
})
}
}
impl From<TypedCommand> for Packet {
fn from(command: TypedCommand) -> Self {
match command {
TypedCommand::Clear(c) => c.into(),
TypedCommand::CharGrid(c) => c.into(),
TypedCommand::Cp437Grid(c) => c.into(),
TypedCommand::Bitmap(c) => c.into(),
TypedCommand::Brightness(c) => c.into(),
TypedCommand::BrightnessGrid(c) => c.into(),
TypedCommand::BitVec(c) => c.into(),
TypedCommand::HardReset(c) => c.into(),
TypedCommand::FadeOut(c) => c.into(),
#[allow(deprecated)]
TypedCommand::BitmapLegacy(c) => c.into(),
}
}
}
pub(self) fn check_command_code_only( pub(self) fn check_command_code_only(
packet: Packet, packet: Packet,
code: CommandCode, code: CommandCode,
@ -284,56 +139,60 @@ mod tests {
#[test] #[test]
fn round_trip_clear() { fn round_trip_clear() {
round_trip(TypedCommand::Clear(commands::ClearCommand)); round_trip(ClearCommand.into());
} }
#[test] #[test]
fn round_trip_hard_reset() { fn round_trip_hard_reset() {
round_trip(TypedCommand::HardReset(commands::HardResetCommand)); round_trip(HardResetCommand.into());
} }
#[test] #[test]
fn round_trip_fade_out() { fn round_trip_fade_out() {
round_trip(TypedCommand::FadeOut(commands::FadeOutCommand)); round_trip(FadeOutCommand.into());
} }
#[test] #[test]
fn round_trip_brightness() { fn round_trip_brightness() {
round_trip(TypedCommand::Brightness(commands::BrightnessCommand { round_trip(
BrightnessCommand {
brightness: Brightness::try_from(6).unwrap(), brightness: Brightness::try_from(6).unwrap(),
})); }
.into(),
);
} }
#[test] #[test]
#[allow(deprecated)] #[allow(deprecated)]
fn round_trip_bitmap_legacy() { fn round_trip_bitmap_legacy() {
round_trip(TypedCommand::BitmapLegacy(commands::BitmapLegacyCommand)); round_trip(BitmapLegacyCommand.into());
} }
#[test] #[test]
fn round_trip_char_brightness() { fn round_trip_char_brightness() {
round_trip(TypedCommand::BrightnessGrid( round_trip(
commands::BrightnessGridCommand { BrightnessGridCommand {
origin: Origin::new(5, 2), origin: Origin::new(5, 2),
grid: BrightnessGrid::new(7, 5), grid: BrightnessGrid::new(7, 5),
}, }
)); .into(),
);
} }
#[test] #[test]
fn round_trip_cp437_data() { fn round_trip_cp437_data() {
round_trip(TypedCommand::Cp437Grid(commands::Cp437GridCommand { round_trip(Cp437GridCommand {
origin: Origin::new(5, 2), origin: Origin::new(5, 2),
grid: Cp437Grid::new(7, 5), grid: Cp437Grid::new(7, 5),
})); }.into());
} }
#[test] #[test]
fn round_trip_utf8_data() { fn round_trip_utf8_data() {
round_trip(TypedCommand::CharGrid(commands::CharGridCommand { round_trip(CharGridCommand {
origin: Origin::new(5, 2), origin: Origin::new(5, 2),
grid: CharGrid::new(7, 5), grid: CharGrid::new(7, 5),
})); }.into());
} }
#[test] #[test]
@ -345,18 +204,18 @@ mod tests {
BinaryOperation::Or, BinaryOperation::Or,
BinaryOperation::Xor, BinaryOperation::Xor,
] { ] {
round_trip(TypedCommand::BitVec(commands::BitVecCommand { round_trip(BitVecCommand {
offset: 23, offset: 23,
bitvec: BitVec::repeat(false, 40), bitvec: BitVec::repeat(false, 40),
compression, compression,
operation, operation,
})); }.into());
} }
round_trip(TypedCommand::Bitmap(commands::BitmapCommand { round_trip(BitmapCommand {
origin: Origin::ZERO, origin: Origin::ZERO,
bitmap: Bitmap::max_sized(), bitmap: Bitmap::max_sized(),
compression, compression,
})); }.into());
} }
} }

149
src/commands/typed.rs Normal file
View file

@ -0,0 +1,149 @@
use crate::{BitVecCommand, BitmapCommand, BitmapLegacyCommand, BrightnessCommand, BrightnessGridCommand, CharGridCommand, ClearCommand, Command, Cp437GridCommand, FadeOutCommand, HardResetCommand, Header, Packet};
use crate::command_code::CommandCode;
/// This enum contains all commands provided by the library.
/// This is useful in case you want one data type for all kinds of commands without using `dyn`.
///
/// Please look at the contained structs for documentation per command.
#[derive(Debug, Clone, PartialEq)]
#[allow(missing_docs)]
pub enum TypedCommand {
Clear(ClearCommand),
CharGrid(CharGridCommand),
Cp437Grid(Cp437GridCommand),
Bitmap(BitmapCommand),
Brightness(BrightnessCommand),
BrightnessGrid(BrightnessGridCommand),
BitVec(BitVecCommand),
HardReset(HardResetCommand),
FadeOut(FadeOutCommand),
#[allow(deprecated)]
#[deprecated]
BitmapLegacy(BitmapLegacyCommand),
}
/// Err values for [TypedCommand::try_from].
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum TryFromPacketError {
/// the contained command code does not correspond to a known command
#[error("The command code {0:?} does not correspond to a known command")]
InvalidCommand(u16),
/// the expected payload size was n, but size m was found
#[error("the expected payload size was {0}, but size {1} was found")]
UnexpectedPayloadSize(usize, usize),
/// Header fields not needed for the command have been used.
///
/// Note that these commands would usually still work on the actual display.
#[error("Header fields not needed for the command have been used")]
ExtraneousHeaderValues,
/// The contained compression code is not known. This could be of disabled features.
#[error("The compression code {0:?} does not correspond to a known compression algorithm.")]
InvalidCompressionCode(u16),
/// Decompression of the payload failed. This can be caused by corrupted packets.
#[error("The decompression of the payload failed")]
DecompressionFailed,
/// The given brightness value is out of bounds
#[error("The given brightness value {0} is out of bounds.")]
InvalidBrightness(u8),
/// Some provided text was not valid UTF-8.
#[error(transparent)]
InvalidUtf8(#[from] std::string::FromUtf8Error),
}
impl TryFrom<Packet> for TypedCommand {
type Error = TryFromPacketError;
/// Try to interpret the [Packet] as one containing a [Command]
fn try_from(packet: Packet) -> Result<Self, Self::Error> {
let Packet {
header: Header { command_code, .. },
..
} = packet;
let command_code = match CommandCode::try_from(command_code) {
Err(()) => {
return Err(TryFromPacketError::InvalidCommand(command_code));
}
Ok(value) => value,
};
Ok(match command_code {
CommandCode::Clear => {
TypedCommand::Clear(crate::ClearCommand::try_from(packet)?)
}
CommandCode::Brightness => TypedCommand::Brightness(
crate::BrightnessCommand::try_from(packet)?,
),
CommandCode::HardReset => {
TypedCommand::HardReset(crate::HardResetCommand::try_from(packet)?)
}
CommandCode::FadeOut => {
TypedCommand::FadeOut(crate::FadeOutCommand::try_from(packet)?)
}
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::BitmapLinear
| CommandCode::BitmapLinearOr
| CommandCode::BitmapLinearAnd
| CommandCode::BitmapLinearXor => {
TypedCommand::BitVec(crate::BitVecCommand::try_from(packet)?)
}
CommandCode::BitmapLinearWinUncompressed => {
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_zlib")]
CommandCode::BitmapLinearWinZlib => {
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_bzip2")]
CommandCode::BitmapLinearWinBzip2 => {
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_lzma")]
CommandCode::BitmapLinearWinLzma => {
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
}
#[cfg(feature = "compression_zstd")]
CommandCode::BitmapLinearWinZstd => {
TypedCommand::Bitmap(crate::BitmapCommand::try_from(packet)?)
}
})
}
}
impl From<TypedCommand> for Packet {
fn from(command: TypedCommand) -> Self {
match command {
TypedCommand::Clear(c) => c.into(),
TypedCommand::CharGrid(c) => c.into(),
TypedCommand::Cp437Grid(c) => c.into(),
TypedCommand::Bitmap(c) => c.into(),
TypedCommand::Brightness(c) => c.into(),
TypedCommand::BrightnessGrid(c) => c.into(),
TypedCommand::BitVec(c) => c.into(),
TypedCommand::HardReset(c) => c.into(),
TypedCommand::FadeOut(c) => c.into(),
#[allow(deprecated)]
TypedCommand::BitmapLegacy(c) => c.into(),
}
}
}

View file

@ -1,4 +1,4 @@
use crate::{brightness::Brightness, grid::Grid, ByteGrid, ValueGrid}; use crate::{Brightness, Grid, ByteGrid, ValueGrid};
/// A grid containing brightness values. /// A grid containing brightness values.
/// ///

View file

@ -1,21 +1,21 @@
mod bitmap;
mod bit_vec; mod bit_vec;
mod bitmap;
mod brightness_grid; mod brightness_grid;
mod byte_grid; mod byte_grid;
mod char_grid; mod char_grid;
mod cp437_grid; mod cp437_grid;
mod data_ref; mod data_ref;
mod grid;
mod value_grid; mod value_grid;
pub use bit_vec::{bitvec, BitVec}; pub use bit_vec::{bitvec, BitVec};
pub use bitmap::Bitmap; pub use bitmap::Bitmap;
pub use cp437_grid::Cp437Grid;
pub use data_ref::DataRef;
pub use brightness_grid::BrightnessGrid; pub use brightness_grid::BrightnessGrid;
pub use byte_grid::ByteGrid; pub use byte_grid::ByteGrid;
pub use char_grid::CharGrid; pub use char_grid::CharGrid;
pub use cp437_grid::Cp437Grid;
pub use data_ref::DataRef;
pub use grid::Grid;
pub use value_grid::{ pub use value_grid::{
IterGridRows, SetValueSeriesError, TryLoadValueGridError, Value, ValueGrid, IterGridRows, SetValueSeriesError, TryLoadValueGridError, Value, ValueGrid,
}; };

View file

@ -61,7 +61,6 @@ pub use crate::compression_code::CompressionCode;
pub use crate::connections::*; pub use crate::connections::*;
pub use crate::constants::*; pub use crate::constants::*;
pub use crate::containers::*; pub use crate::containers::*;
pub use crate::grid::Grid;
pub use crate::origin::{Origin, Pixels, Tiles}; pub use crate::origin::{Origin, Pixels, Tiles};
pub use crate::packet::{Header, Packet, Payload}; pub use crate::packet::{Header, Packet, Payload};
@ -73,10 +72,8 @@ mod compression_code;
mod connections; mod connections;
mod constants; mod constants;
mod containers; mod containers;
mod grid;
mod origin; mod origin;
mod packet; mod packet;
mod parser;
#[cfg(feature = "cp437")] #[cfg(feature = "cp437")]
mod cp437; mod cp437;

View file