add a bunch of lints and change more panics to result/option
Some checks failed
Rust / build (pull_request) Failing after 1m7s

This commit is contained in:
Vinzenz Schroeter 2025-03-12 22:45:29 +01:00
parent 4ccbd57ba8
commit 08ed6a6fee
12 changed files with 145 additions and 39 deletions

View file

@ -9,6 +9,7 @@ homepage = "https://docs.rs/crate/servicepoint"
repository = "https://git.berlin.ccc.de/servicepoint/servicepoint"
readme = "README.md"
keywords = ["cccb", "cccb-servicepoint"]
rust-version = "1.70.0"
[lib]
crate-type = ["rlib"]
@ -55,6 +56,23 @@ clap = { version = "4.5", features = ["derive"] }
[lints.rust]
missing-docs = "warn"
deprecated-safe = "warn"
future-incompatible = "warn"
keyword-idents = "warn"
let-underscore = "warn"
nonstandard-style = "warn"
refining_impl_trait_reachable = "warn"
rust-2024-compatibility = "warn"
[lints.clippy]
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"
incompatible_msrv = "forbid"
[lints.rustdoc]
private_doc_tests = "warn"
unescaped_backticks = "warn"
[package.metadata.docs.rs]
all-features = true

View file

@ -60,6 +60,8 @@ There should be no breaking changes in patch releases, but there may also be fea
All of this means for you: please specify the full version including patch in your Cargo.toml until 1.0 is released.
Release notes are published [here](https://git.berlin.ccc.de/servicepoint/servicepoint/releases), please check them before updating.
## Features
This library has multiple optional dependencies.

View file

@ -15,7 +15,7 @@ use rand::{
///
/// let b = Brightness::try_from(7).unwrap();
/// # let connection = FakeConnection;
/// let result = connection.send(b);
/// let result = connection.send(BrightnessCommand::from(b));
/// ```
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)]
pub struct Brightness(u8);
@ -90,7 +90,7 @@ mod tests {
fn rand_brightness() {
let mut rng = rand::thread_rng();
for _ in 0..100 {
let _: Brightness = rng.gen();
let _: Brightness = rng.r#gen();
}
}
@ -104,6 +104,6 @@ mod tests {
#[cfg(feature = "rand")]
fn test() {
let mut rng = rand::thread_rng();
assert_ne!(rng.gen::<Brightness>(), rng.gen());
assert_ne!(rng.r#gen::<Brightness>(), rng.r#gen());
}
}

View file

@ -1,6 +1,6 @@
use crate::{
command_code::CommandCode, commands::TryFromPacketError, Brightness,
Header, Packet, TypedCommand,
command_code::CommandCode, commands::check_command_code,
commands::TryFromPacketError, Brightness, Header, Packet, TypedCommand,
};
/// Set the brightness of all tiles to the same value.
@ -41,7 +41,7 @@ impl TryFrom<Packet> for BrightnessCommand {
let Packet {
header:
Header {
command_code: _,
command_code,
a,
b,
c,
@ -49,6 +49,9 @@ impl TryFrom<Packet> for BrightnessCommand {
},
payload,
} = packet;
check_command_code(command_code, CommandCode::Brightness)?;
if payload.len() != 1 {
return Err(TryFromPacketError::UnexpectedPayloadSize(
1,

View file

@ -1,6 +1,7 @@
use crate::{
command_code::CommandCode, commands::TryFromPacketError, BrightnessGrid,
ByteGrid, Header, Origin, Packet, Tiles, TypedCommand,
command_code::CommandCode, commands::check_command_code,
commands::TryFromPacketError, BrightnessGrid, ByteGrid, Header, Origin,
Packet, Tiles, TypedCommand,
};
/// Set the brightness of individual tiles in a rectangular area of the display.
@ -29,7 +30,7 @@ impl TryFrom<Packet> for BrightnessGridCommand {
let Packet {
header:
Header {
command_code: _,
command_code,
a: x,
b: y,
c: width,
@ -38,8 +39,21 @@ impl TryFrom<Packet> for BrightnessGridCommand {
payload,
} = packet;
let grid =
ByteGrid::load(width as usize, height as usize, &payload).unwrap();
check_command_code(command_code, CommandCode::CharBrightness)?;
let expected_size = width as usize * height as usize;
if payload.len() != expected_size {
return Err(TryFromPacketError::UnexpectedPayloadSize(
payload.len(),
expected_size,
));
}
let grid = ByteGrid::from_raw_parts_unchecked(
width as usize,
height as usize,
payload,
);
let grid = match BrightnessGrid::try_from(grid) {
Ok(grid) => grid,
Err(val) => return Err(TryFromPacketError::InvalidBrightness(val)),

View file

@ -1,6 +1,7 @@
use crate::{
command_code::CommandCode, commands::TryFromPacketError, CharGrid, Header,
Origin, Packet, Tiles, TypedCommand,
command_code::CommandCode, commands::check_command_code,
commands::TryFromPacketError, CharGrid, Header, Origin, Packet, Tiles,
TypedCommand,
};
/// Show text on the screen.
@ -40,19 +41,35 @@ impl TryFrom<Packet> for CharGridCommand {
let Packet {
header:
Header {
command_code: _,
a,
b,
c,
d,
command_code,
a: origin_x,
b: origin_y,
c: width,
d: height,
},
payload,
} = packet;
check_command_code(command_code, CommandCode::Utf8Data)?;
let payload: Vec<_> =
String::from_utf8(payload.clone())?.chars().collect();
let expected_size = width as usize * height as usize;
if payload.len() != expected_size {
return Err(TryFromPacketError::UnexpectedPayloadSize(
expected_size,
payload.len(),
));
}
Ok(Self {
origin: Origin::new(a as usize, b as usize),
grid: CharGrid::load(c as usize, d as usize, &payload).unwrap(),
origin: Origin::new(origin_x as usize, origin_y as usize),
grid: CharGrid::from_raw_parts_unchecked(
width as usize,
height as usize,
payload,
),
})
}
}

View file

@ -1,6 +1,7 @@
use crate::{
command_code::CommandCode, commands::TryFromPacketError, Cp437Grid, Header,
Origin, Packet, Tiles, TypedCommand,
command_code::CommandCode, commands::check_command_code,
commands::TryFromPacketError, Cp437Grid, Header, Origin, Packet, Tiles,
TypedCommand,
};
/// Show text on the screen.
@ -51,17 +52,32 @@ impl TryFrom<Packet> for Cp437GridCommand {
let Packet {
header:
Header {
command_code: _,
a,
b,
c,
d,
command_code,
a: origin_x,
b: origin_y,
c: width,
d: height,
},
payload,
} = packet;
check_command_code(command_code, CommandCode::Cp437Data)?;
let expected_size = width as usize * height as usize;
if payload.len() != expected_size {
return Err(TryFromPacketError::UnexpectedPayloadSize(
expected_size,
payload.len(),
));
}
Ok(Self {
origin: Origin::new(a as usize, b as usize),
grid: Cp437Grid::load(c as usize, d as usize, &payload).unwrap(),
origin: Origin::new(origin_x as usize, origin_y as usize),
grid: Cp437Grid::from_raw_parts_unchecked(
width as usize,
height as usize,
payload,
),
})
}
}

View file

@ -106,6 +106,17 @@ fn check_command_code_only(
}
}
fn check_command_code(
actual: u16,
expected: CommandCode,
) -> Result<(), TryFromPacketError> {
if actual != u16::from(expected) {
Err(TryFromPacketError::InvalidCommand(actual))
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::*;

View file

@ -67,6 +67,7 @@ pub(crate) fn into_decompressed(
}
}
#[allow(clippy::unwrap_used)]
pub(crate) fn into_compressed(
kind: CompressionCode,
payload: Payload,

View file

@ -20,10 +20,13 @@ pub type BrightnessGrid = ValueGrid<Brightness>;
impl BrightnessGrid {
/// Like [Self::load], but ignoring any out-of-range brightness values
pub fn saturating_load(width: usize, height: usize, data: &[u8]) -> Self {
pub fn saturating_load(
width: usize,
height: usize,
data: &[u8],
) -> Option<Self> {
ValueGrid::load(width, height, data)
.unwrap()
.map(Brightness::saturating_from)
.map(move |grid| grid.map(Brightness::saturating_from))
}
}
@ -42,7 +45,7 @@ impl From<&BrightnessGrid> for ByteGrid {
.iter()
.map(|brightness| (*brightness).into())
.collect::<Vec<u8>>();
ValueGrid::load(value.width(), value.height(), &u8s).unwrap()
Self::from_raw_parts_unchecked(value.width(), value.height(), u8s)
}
}
@ -54,10 +57,11 @@ impl TryFrom<ByteGrid> for BrightnessGrid {
.iter()
.map(|b| Brightness::try_from(*b))
.collect::<Result<Vec<_>, _>>()?;
Ok(
BrightnessGrid::load(value.width(), value.height(), &brightnesses)
.unwrap(),
)
Ok(Self::from_raw_parts_unchecked(
value.width(),
value.height(),
brightnesses,
))
}
}
@ -88,7 +92,7 @@ mod tests {
]
)
.unwrap(),
BrightnessGrid::saturating_load(2, 2, &[255u8, 23, 0, 42])
BrightnessGrid::saturating_load(2, 2, &[255u8, 23, 0, 42]).unwrap()
);
}
}

View file

@ -51,6 +51,8 @@ impl CharGrid {
let height = lines.len();
let mut result = Self::new(width, height);
for (row, text_line) in lines.iter().enumerate() {
#[allow(clippy::unwrap_used)]
// we calculated the width before setting
result.set_row_str(row, text_line).unwrap()
}
result

View file

@ -101,6 +101,20 @@ impl<T: Value> ValueGrid<T> {
})
}
#[must_use]
pub(crate) fn from_raw_parts_unchecked(
width: usize,
height: usize,
data: Vec<T>,
) -> Self {
debug_assert_eq!(data.len(), width * height);
Self {
data,
width,
height,
}
}
/// Iterate over all cells in [ValueGrid].
///
/// Order is equivalent to the following loop:
@ -189,7 +203,11 @@ impl<T: Value> ValueGrid<T> {
.iter()
.map(|elem| f(*elem))
.collect::<Vec<_>>();
ValueGrid::load(self.width(), self.height(), &data).unwrap()
ValueGrid {
width: self.width(),
height: self.height(),
data,
}
}
/// Copies a row from the grid.