Compare commits

...

2 commits

Author SHA1 Message Date
Vinzenz Schroeter fe1aa3ebd1 do not use () as Err, clean up error handling
Some checks failed
Rust / build (pull_request) Failing after 1m15s
2025-03-25 21:42:17 +01:00
Vinzenz Schroeter 373d0efe55 remove TryFrom<&Origin<Pixels>> for Origin<Tiles> 2025-03-25 21:38:36 +01:00
10 changed files with 67 additions and 116 deletions

View file

@ -33,8 +33,12 @@ impl From<CommandCode> for u16 {
}
}
#[derive(Debug, thiserror::Error, Eq, PartialEq)]
#[error("The command code {0} is not known.")]
pub struct InvalidCommandCodeError(pub u16);
impl TryFrom<u16> for CommandCode {
type Error = ();
type Error = InvalidCommandCodeError;
/// Returns the enum value for the specified `u16` or `Error` if the code is unknown.
fn try_from(value: u16) -> Result<Self, Self::Error> {
@ -97,7 +101,7 @@ impl TryFrom<u16> for CommandCode {
value if value == CommandCode::Utf8Data as u16 => {
Ok(CommandCode::Utf8Data)
}
_ => Err(()),
_ => Err(InvalidCommandCodeError(value)),
}
}
}

View file

@ -1,5 +1,5 @@
use crate::{
command_code::CommandCode,
command_code::{CommandCode, InvalidCommandCodeError},
commands::errors::{TryFromPacketError, TryIntoPacketError},
compression::into_compressed,
compression::into_decompressed,
@ -83,10 +83,7 @@ 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).map_err(
|()| TryFromPacketError::InvalidCommand(packet.header.command_code),
)?;
let code = CommandCode::try_from(packet.header.command_code)?;
match code {
CommandCode::BitmapLinearWinUncompressed => {
Self::packet_into_bitmap_win(
@ -111,9 +108,9 @@ impl TryFrom<Packet> for BitmapCommand {
Self::packet_into_bitmap_win(packet, CompressionCode::Zstd)
}
_ => Err(TryFromPacketError::InvalidCommand(
packet.header.command_code,
)),
_ => {
Err(InvalidCommandCodeError(packet.header.command_code).into())
}
}
}
}
@ -182,9 +179,7 @@ mod tests {
..Default::default()
}
}),
Err(TryFromPacketError::InvalidCommand(
CommandCode::Brightness.into()
))
Err(InvalidCommandCodeError(CommandCode::Brightness.into()).into())
);
}

View file

@ -1,7 +1,8 @@
use crate::{
command_code::CommandCode, commands::errors::TryFromPacketError,
compression::into_compressed, compression::into_decompressed, BitVec,
CompressionCode, Header, Offset, Packet, TryIntoPacketError, TypedCommand,
command_code::CommandCode, command_code::InvalidCommandCodeError,
commands::errors::TryFromPacketError, compression::into_compressed,
compression::into_decompressed, BitVec, CompressionCode, Header, Offset,
Packet, TryIntoPacketError, TypedCommand,
};
/// Binary operations for use with the [`BitVecCommand`] command.
@ -86,29 +87,21 @@ impl TryFrom<Packet> for BitVecCommand {
},
payload,
} = packet;
let command_code = CommandCode::try_from(command_code)
.map_err(|()| TryFromPacketError::InvalidCommand(command_code))?;
let command_code = CommandCode::try_from(command_code)?;
let operation = match command_code {
CommandCode::BitmapLinear => BinaryOperation::Overwrite,
CommandCode::BitmapLinearAnd => BinaryOperation::And,
CommandCode::BitmapLinearOr => BinaryOperation::Or,
CommandCode::BitmapLinearXor => BinaryOperation::Xor,
_ => {
return Err(TryFromPacketError::InvalidCommand(
command_code.into(),
))
return Err(InvalidCommandCodeError(command_code.into()).into());
}
};
if reserved != 0 {
return Err(TryFromPacketError::ExtraneousHeaderValues);
}
let compression = match CompressionCode::try_from(sub) {
Err(()) => {
return Err(TryFromPacketError::InvalidCompressionCode(sub));
}
Ok(value) => value,
};
let compression = CompressionCode::try_from(sub)?;
let payload = match into_decompressed(compression, payload) {
None => return Err(TryFromPacketError::DecompressionFailed),
Some(value) => value,
@ -138,6 +131,7 @@ impl From<BitVecCommand> for TypedCommand {
mod tests {
use super::*;
use crate::commands::tests::{round_trip, TestImplementsCommand};
use crate::compression_code::InvalidCompressionCodeError;
use crate::{commands, Bitmap, BitmapCommand, Origin};
impl TestImplementsCommand for BitVecCommand {}
@ -152,9 +146,7 @@ mod tests {
..Default::default()
}
}),
Err(TryFromPacketError::InvalidCommand(
CommandCode::Brightness.into()
))
Err(InvalidCommandCodeError(CommandCode::Brightness.into()).into())
);
}
@ -285,7 +277,7 @@ mod tests {
};
assert_eq!(
TypedCommand::try_from(p),
Err(TryFromPacketError::InvalidCompressionCode(42))
Err(InvalidCompressionCodeError(42).into())
);
}

View file

@ -1,6 +1,7 @@
use crate::{
command_code::CommandCode, commands::check_command_code_only,
commands::errors::TryFromPacketError, Packet, TypedCommand,
command_code::CommandCode,
commands::{check_command_code_only, errors::TryFromPacketError},
Packet, TypedCommand,
};
use std::fmt::Debug;
@ -43,6 +44,7 @@ impl From<ClearCommand> for TypedCommand {
#[cfg(test)]
mod tests {
use super::*;
use crate::command_code::InvalidCommandCodeError;
use crate::commands::tests::TestImplementsCommand;
use crate::Header;
@ -85,9 +87,7 @@ mod tests {
payload: vec![],
};
assert_eq!(
Err(TryFromPacketError::InvalidCommand(
CommandCode::HardReset.into()
)),
Err(InvalidCommandCodeError(CommandCode::HardReset.into()).into()),
ClearCommand::try_from(p)
);
}

View file

@ -1,12 +1,15 @@
use crate::LoadBitmapError;
use crate::{
command_code::InvalidCommandCodeError,
compression_code::InvalidCompressionCodeError, LoadBitmapError,
};
use std::num::TryFromIntError;
/// Err values for [`crate::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),
#[error(transparent)]
InvalidCommand(#[from] InvalidCommandCodeError),
/// 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),
@ -16,8 +19,8 @@ pub enum TryFromPacketError {
#[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),
#[error(transparent)]
InvalidCompression(#[from] InvalidCompressionCodeError),
/// Decompression of the payload failed. This can be caused by corrupted packets.
#[error("The decompression of the payload failed")]
DecompressionFailed,

View file

@ -11,7 +11,7 @@ mod fade_out;
mod hard_reset;
mod typed;
use crate::command_code::CommandCode;
use crate::command_code::{CommandCode, InvalidCommandCodeError};
use crate::{Header, Packet};
use std::fmt::Debug;
@ -99,9 +99,7 @@ fn check_command_code_only(
payload,
} = packet;
if packet.header.command_code != u16::from(code) {
Some(TryFromPacketError::InvalidCommand(
packet.header.command_code,
))
Some(InvalidCommandCodeError(packet.header.command_code).into())
} else if !payload.is_empty() {
Some(TryFromPacketError::UnexpectedPayloadSize(0, payload.len()))
} else if a != 0 || b != 0 || c != 0 || d != 0 {
@ -114,11 +112,11 @@ fn check_command_code_only(
fn check_command_code(
actual: u16,
expected: CommandCode,
) -> Result<(), TryFromPacketError> {
) -> Result<(), InvalidCommandCodeError> {
if actual == u16::from(expected) {
Ok(())
} else {
Err(TryFromPacketError::InvalidCommand(actual))
Err(InvalidCommandCodeError(actual))
}
}
@ -126,6 +124,10 @@ fn check_command_code(
mod tests {
use crate::*;
#[allow(
unused,
reason = "false positive, used in submodules that check if structs impl Command"
)]
pub(crate) trait TestImplementsCommand: Command {}
pub(crate) fn round_trip(original: TypedCommand) {

View file

@ -2,7 +2,7 @@ use crate::{
command_code::CommandCode, commands::errors::TryFromPacketError,
BitVecCommand, BitmapCommand, BrightnessCommand, BrightnessGridCommand,
CharGridCommand, ClearCommand, Cp437GridCommand, FadeOutCommand,
HardResetCommand, Header, Packet, TryIntoPacketError,
HardResetCommand, Packet, TryIntoPacketError,
};
/// This enum contains all commands provided by the library.
@ -31,18 +31,7 @@ impl TryFrom<Packet> for TypedCommand {
/// 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 {
Ok(match CommandCode::try_from(packet.header.command_code)? {
CommandCode::Clear => {
TypedCommand::Clear(crate::ClearCommand::try_from(packet)?)
}
@ -119,9 +108,10 @@ impl TryFrom<TypedCommand> for Packet {
#[cfg(test)]
mod tests {
use crate::commands::errors::TryFromPacketError;
use crate::commands::tests::TestImplementsCommand;
use crate::{Header, Packet, TypedCommand};
use crate::{
command_code::InvalidCommandCodeError,
commands::tests::TestImplementsCommand, Header, Packet, TypedCommand,
};
impl TestImplementsCommand for TypedCommand {}
@ -138,9 +128,6 @@ mod tests {
payload: vec![],
};
let result = TypedCommand::try_from(p);
assert!(matches!(
result,
Err(TryFromPacketError::InvalidCommand(0xFF))
));
assert_eq!(result, Err(InvalidCommandCodeError(0xFF).into()));
}
}

View file

@ -54,6 +54,10 @@ impl CompressionCode {
];
}
#[derive(Debug, thiserror::Error, Eq, PartialEq)]
#[error("The compression code {0} is not known.")]
pub struct InvalidCompressionCodeError(pub u16);
impl From<CompressionCode> for u16 {
fn from(value: CompressionCode) -> Self {
value as u16
@ -61,7 +65,7 @@ impl From<CompressionCode> for u16 {
}
impl TryFrom<u16> for CompressionCode {
type Error = ();
type Error = InvalidCompressionCodeError;
fn try_from(value: u16) -> Result<Self, Self::Error> {
match value {
@ -84,7 +88,7 @@ impl TryFrom<u16> for CompressionCode {
value if value == CompressionCode::Zstd as u16 => {
Ok(CompressionCode::Zstd)
}
_ => Err(()),
_ => Err(InvalidCompressionCodeError(value)),
}
}
}

View file

@ -66,27 +66,6 @@ impl From<&Origin<Tiles>> for Origin<Pixels> {
}
}
impl TryFrom<&Origin<Pixels>> for Origin<Tiles> {
type Error = ();
fn try_from(value: &Origin<Pixels>) -> Result<Self, Self::Error> {
let (x, x_rem) = (value.x / TILE_SIZE, value.x % TILE_SIZE);
if x_rem != 0 {
return Err(());
}
let (y, y_rem) = (value.y / TILE_SIZE, value.y % TILE_SIZE);
if y_rem != 0 {
return Err(());
}
Ok(Self {
x,
y,
phantom_data: PhantomData,
})
}
}
impl<Unit: DisplayUnit> Default for Origin<Unit> {
fn default() -> Self {
Self::ZERO
@ -105,28 +84,6 @@ mod tests {
assert_eq!(actual, expected);
}
#[test]
fn origin_pixel_to_tile() {
let pixel: Origin<Pixels> = Origin::new(8, 16);
let actual: Origin<Tiles> = Origin::try_from(&pixel).unwrap();
let expected: Origin<Tiles> = Origin::new(1, 2);
assert_eq!(actual, expected);
}
#[test]
#[should_panic]
fn origin_pixel_to_tile_fail_y() {
let pixel: Origin<Pixels> = Origin::new(8, 15);
let _: Origin<Tiles> = Origin::try_from(&pixel).unwrap();
}
#[test]
#[should_panic]
fn origin_pixel_to_tile_fail_x() {
let pixel: Origin<Pixels> = Origin::new(7, 16);
let _: Origin<Tiles> = Origin::try_from(&pixel).unwrap();
}
#[test]
fn origin_add() {
assert_eq!(

View file

@ -92,15 +92,19 @@ impl From<Packet> for Vec<u8> {
}
}
#[derive(Debug, thiserror::Error, Eq, PartialEq)]
#[error("The provided slice is smaller than the header size, so it cannot be read as a packet.")]
pub struct SliceSmallerThanHeader;
impl TryFrom<&[u8]> for Packet {
type Error = ();
type Error = SliceSmallerThanHeader;
/// Tries to interpret the bytes as a [Packet].
///
/// returns: `Error` if slice is not long enough to be a [Packet]
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
if value.len() < size_of::<Header>() {
return Err(());
return Err(SliceSmallerThanHeader);
}
let header = {
@ -124,7 +128,7 @@ impl TryFrom<&[u8]> for Packet {
}
impl TryFrom<Vec<u8>> for Packet {
type Error = ();
type Error = SliceSmallerThanHeader;
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
Self::try_from(value.as_slice())
@ -203,6 +207,9 @@ mod tests {
#[test]
fn too_small() {
let data = vec![0u8; 4];
assert_eq!(Packet::try_from(data.as_slice()), Err(()));
assert_eq!(
Packet::try_from(data.as_slice()),
Err(SliceSmallerThanHeader)
);
}
}