make the optional methods the primary ones to avoid redundant checks

This commit is contained in:
Vinzenz Schroeter 2025-07-09 22:30:41 +02:00
parent cabf1d32ed
commit 23e2dc4f1a
12 changed files with 79 additions and 56 deletions

View file

@ -2,8 +2,8 @@
use clap::Parser;
use servicepoint::{
Bitmap, BitmapCommand, CompressionCode, Origin, Packet, UdpSocketExt,
FRAME_PACING, PIXEL_HEIGHT, PIXEL_WIDTH,
Bitmap, BitmapCommand, CompressionCode, GridMut, Origin, Packet,
UdpSocketExt, FRAME_PACING, PIXEL_HEIGHT, PIXEL_WIDTH,
};
use std::{net::UdpSocket, thread, time::Duration};

View file

@ -2,7 +2,9 @@
use clap::Parser;
use rand::Rng;
use servicepoint::{Bitmap, BitmapCommand, Grid, UdpSocketExt, FRAME_PACING};
use servicepoint::{
Bitmap, BitmapCommand, Grid, GridMut, UdpSocketExt, FRAME_PACING,
};
use std::{net::UdpSocket, thread};
#[derive(Parser, Debug)]

View file

@ -2,8 +2,8 @@
use clap::Parser;
use servicepoint::{
Bitmap, BitmapCommand, CompressionCode, UdpSocketExt, FRAME_PACING,
PIXEL_HEIGHT, PIXEL_WIDTH,
Bitmap, BitmapCommand, CompressionCode, GridMut, UdpSocketExt,
FRAME_PACING, PIXEL_HEIGHT, PIXEL_WIDTH,
};
use std::{net::UdpSocket, thread};

View file

@ -5,7 +5,7 @@ use clap::Parser;
use rand::Rng;
use servicepoint::{
Bitmap, BitmapCommand, Brightness, BrightnessGrid, BrightnessGridCommand,
GlobalBrightnessCommand, Grid, Origin, UdpSocketExt, TILE_HEIGHT,
GlobalBrightnessCommand, Grid, GridMut, Origin, UdpSocketExt, TILE_HEIGHT,
TILE_WIDTH,
};
use std::{net::UdpSocket, time::Duration};

View file

@ -2,7 +2,7 @@
use clap::Parser;
use servicepoint::{
Bitmap, BitmapCommand, UdpSocketExt, FRAME_PACING, PIXEL_HEIGHT,
Bitmap, BitmapCommand, GridMut, UdpSocketExt, FRAME_PACING, PIXEL_HEIGHT,
PIXEL_WIDTH,
};
use std::{net::UdpSocket, thread, time::Duration};

View file

@ -145,7 +145,7 @@ impl Bitmap {
///
/// Order is equivalent to the following loop:
/// ```
/// # use servicepoint::{Bitmap, Grid};
/// # use servicepoint::{Bitmap, Grid, GridMut};
/// # let mut grid = Bitmap::new(8, 2).unwrap();
/// # let value = false;
/// for y in 0..grid.height() {
@ -210,9 +210,13 @@ impl Bitmap {
impl Grid<bool> for Bitmap {
#[must_use]
#[allow(unused, reason = "False positive because of #[inherent]")]
pub fn get(&self, x: usize, y: usize) -> bool {
self.assert_in_bounds(x, y);
self.bit_vec[x + y * self.width]
pub fn get_optional(&self, x: usize, y: usize) -> Option<bool> {
let index = x + y * self.width;
if self.is_in_bounds(x, y) {
Some(self.bit_vec[index])
} else {
None
}
}
#[must_use]
@ -241,9 +245,13 @@ impl GridMut<bool> for Bitmap {
///
/// When accessing `x` or `y` out of bounds.
#[allow(unused, reason = "False positive because of #[inherent]")]
pub fn set(&mut self, x: usize, y: usize, value: bool) {
self.assert_in_bounds(x, y);
self.bit_vec.set(x + y * self.width, value);
pub fn set_optional(&mut self, x: usize, y: usize, value: bool) -> bool {
if self.is_in_bounds(x, y) {
self.bit_vec.set(x + y * self.width, value);
true
} else {
false
}
}
/// Sets the state of all pixels in the [Bitmap].
@ -344,7 +352,10 @@ pub enum LoadBitmapError {
#[cfg(test)]
mod tests {
use crate::{Bitmap, DataRef, DisplayBitVec, LoadBitmapError, ValueGrid};
use crate::{
Bitmap, DataRef, DisplayBitVec, Grid, GridMut, LoadBitmapError,
ValueGrid,
};
#[test]
fn fill() {

View file

@ -93,7 +93,7 @@ impl TryFrom<ByteGrid> for BrightnessGrid {
#[cfg(test)]
mod tests {
use crate::{Brightness, BrightnessGrid, DataRef, ValueGrid};
use crate::{Brightness, BrightnessGrid, DataRef, GridMut, ValueGrid};
#[test]
fn to_u8_grid() {

View file

@ -1,4 +1,4 @@
use crate::{CharGridMutExt, TryLoadValueGridError, ValueGrid};
use crate::{CharGridMutExt, GridMut, TryLoadValueGridError, ValueGrid};
use std::string::FromUtf8Error;
/// A grid containing UTF-8 characters.

View file

@ -1,4 +1,4 @@
use crate::ValueGrid;
use crate::{GridMut, ValueGrid};
/// A grid containing codepage 437 characters.
///

View file

@ -12,7 +12,11 @@ pub trait Grid<T> {
///
/// When accessing `x` or `y` out of bounds.
#[must_use]
fn get(&self, x: usize, y: usize) -> T;
fn get(&self, x: usize, y: usize) -> T {
#[allow(clippy::panic, reason = "This is the version that panics - _optional does not")]
self.get_optional(x, y)
.unwrap_or_else(|| panic!("Cannot access index ({x}, {y}) because it is out of bounds for a grid of dimension {}x{}", self.width(), self.height()))
}
/// Get the current value at the specified position if the position is inside of bounds
///
@ -22,13 +26,7 @@ pub trait Grid<T> {
///
/// returns: Value at position or None
#[must_use]
fn get_optional(&self, x: usize, y: usize) -> Option<T> {
if self.is_in_bounds(x, y) {
Some(self.get(x, y))
} else {
None
}
}
fn get_optional(&self, x: usize, y: usize) -> Option<T>;
/// the size in x-direction
#[must_use]
@ -102,7 +100,14 @@ pub trait GridMut<T: Clone>: Grid<T> {
/// # Panics
///
/// When accessing `x` or `y` out of bounds.
fn set(&mut self, x: usize, y: usize, value: T);
fn set(&mut self, x: usize, y: usize, value: T) {
#[allow(
clippy::expect_used,
reason = "This is the version that panics - _optional does not"
)]
let worked = self.set_optional(x, y, value);
assert!(worked, "Cannot access index ({x}, {y}) because it is out of bounds for a grid of dimension {}x{}", self.width(), self.height());
}
/// Sets the value at the specified position if the position is inside of bounds
///
@ -112,14 +117,7 @@ pub trait GridMut<T: Clone>: Grid<T> {
///
/// returns: true if the value has been set
#[must_use]
fn set_optional(&mut self, x: usize, y: usize, value: T) -> bool {
if self.is_in_bounds(x, y) {
self.set(x, y, value);
true
} else {
false
}
}
fn set_optional(&mut self, x: usize, y: usize, value: T) -> bool;
/// Sets all cells in the grid to the specified value
fn fill(&mut self, value: T);
@ -270,4 +268,4 @@ mod test {
})
);
}
}
}

View file

@ -273,20 +273,14 @@ pub enum TryLoadValueGridError {
#[inherent]
impl<T: Value> Grid<T> for ValueGrid<T> {
/// Gets the current value at the specified position.
///
/// # Arguments
///
/// - `x` and `y`: position of the cell to read
///
/// # Panics
///
/// When accessing `x` or `y` out of bounds.
#[must_use]
#[allow(unused, reason = "False positive because of #[inherent]")]
pub fn get(&self, x: usize, y: usize) -> T {
self.assert_in_bounds(x, y);
self.data[x + y * self.width]
pub fn get_optional(&self, x: usize, y: usize) -> Option<T> {
if self.is_in_bounds(x, y) {
Some(self.data[x + y * self.width])
} else {
None
}
}
#[must_use]
@ -313,9 +307,13 @@ impl<T: Value> GridMut<T> for ValueGrid<T> {
///
/// When accessing `x` or `y` out of bounds.
#[allow(unused, reason = "False positive because of #[inherent]")]
pub fn set(&mut self, x: usize, y: usize, value: T) {
self.assert_in_bounds(x, y);
self.data[x + y * self.width] = value;
pub fn set_optional(&mut self, x: usize, y: usize, value: T) -> bool {
if self.is_in_bounds(x, y) {
self.data[x + y * self.width] = value;
true
} else {
false
}
}
#[allow(unused, reason = "False positive because of #[inherent]")]
@ -410,7 +408,7 @@ impl<T: Value> Iterator for EnumerateGrid<'_, T> {
#[cfg(test)]
mod tests {
use crate::{SetValueSeriesError, ValueGrid, *};
use crate::{DataRef, Grid, GridMut, ValueGrid};
#[test]
fn fill() {

View file

@ -119,8 +119,12 @@ macro_rules! define_window {
{
#[must_use]
#[allow(unused, reason = "False positive because of #[inherent]")]
pub fn get(&self, x: usize, y: usize) -> TElement {
self.grid.get(self.xs.start + x, self.ys.start + y)
pub fn get_optional(&self, x: usize, y: usize) -> Option<TElement> {
if self.is_in_bounds(x, y) {
Some(self.grid.get(self.xs.start + x, self.ys.start + y))
} else {
None
}
}
#[must_use]
@ -146,8 +150,18 @@ impl<TElement: Copy, TGrid: GridMut<TElement>> GridMut<TElement>
for WindowMut<'_, TElement, TGrid>
{
#[allow(unused, reason = "False positive because of #[inherent]")]
pub fn set(&mut self, x: usize, y: usize, value: TElement) {
self.grid.set(self.xs.start + x, self.ys.start + y, value);
pub fn set_optional(
&mut self,
x: usize,
y: usize,
value: TElement,
) -> bool {
if self.is_in_bounds(x, y) {
self.grid.set(self.xs.start + x, self.ys.start + y, value);
true
} else {
false
}
}
#[allow(unused, reason = "False positive because of #[inherent]")]