diff --git a/crates/servicepoint/src/byte_grid.rs b/crates/servicepoint/src/byte_grid.rs index bc06534..bc58c7e 100644 --- a/crates/servicepoint/src/byte_grid.rs +++ b/crates/servicepoint/src/byte_grid.rs @@ -1,3 +1,4 @@ +use crate::grid::RefGrid; use crate::{DataRef, Grid}; /// A 2D grid of bytes @@ -42,6 +43,10 @@ impl ByteGrid { } } + fn is_position_valid(&self, x: isize, y: isize) -> bool { + x > 0 && x < self.width as isize && y > 0 && y < self.height as isize + } + fn check_indexes(&self, x: usize, y: usize) { assert!( x < self.width, @@ -54,6 +59,11 @@ impl ByteGrid { self.height ); } + + pub fn get_mut(&mut self, x: usize, y: usize) -> &mut u8 { + self.check_indexes(x, y); + &mut self.data[x + y * self.width] + } } impl Grid for ByteGrid { @@ -91,6 +101,22 @@ impl Grid for ByteGrid { self.data[x + y * self.width] } + fn get_optional(&self, x: isize, y: isize) -> Option { + if self.is_position_valid(x, y) { + Some(self.get(x as usize, y as usize)) + } else { + None + } + } + + fn set_optional(&mut self, x: isize, y: isize, value: u8) -> Option { + if self.is_position_valid(x, y) { + Some(self.set(x as usize, y as usize, value)) + } else { + None + } + } + fn fill(&mut self, value: u8) { self.data.fill(value); } @@ -123,6 +149,34 @@ impl From for Vec { } } +impl RefGrid for ByteGrid { + fn get_ref(&self, x: usize, y: usize) -> &u8 { + self.check_indexes(x, y); + &self.data[x + y * self.width] + } + + fn get_ref_optional(&self, x: isize, y: isize) -> Option<&u8> { + if self.is_position_valid(x, y) { + Some(&self.data[x as usize + y as usize * self.width]) + } else { + None + } + } + + fn get_ref_mut(&mut self, x: usize, y: usize) -> &mut u8 { + self.check_indexes(x, y); + &mut self.data[x + y * self.width] + } + + fn get_ref_mut_optional(&mut self, x: isize, y: isize) -> Option<&mut u8> { + if self.is_position_valid(x, y) { + Some(&mut self.data[x as usize + y as usize * self.width]) + } else { + None + } + } +} + #[cfg(test)] mod tests { use crate::{ByteGrid, DataRef, Grid}; diff --git a/crates/servicepoint/src/grid.rs b/crates/servicepoint/src/grid.rs index b9502f4..79cdbfb 100644 --- a/crates/servicepoint/src/grid.rs +++ b/crates/servicepoint/src/grid.rs @@ -51,3 +51,46 @@ pub trait Grid { /// the height in y-direction fn height(&self) -> usize; } + +/// A grid that can return cells as references. +pub trait RefGrid { + /// Get a reference to the current value at the specified position + /// + /// # Arguments + /// + /// * `x` and `y`: position of the cell + /// + /// # Panics + /// + /// When accessing `x` or `y` out of bounds. + fn get_ref(&self, x: usize, y: usize) -> &T; + + /// Get a reference to the current value at the specified position if the position is in bounds. + /// + /// # Arguments + /// + /// * `x` and `y`: position of the cell + /// + /// returns: Reference to cell or None + fn get_ref_optional(&self, x: isize, y: isize) -> Option<&T>; + + /// Get a mutable reference to the current value at the specified position + /// + /// # Arguments + /// + /// * `x` and `y`: position of the cell + /// + /// # Panics + /// + /// When accessing `x` or `y` out of bounds. + fn get_ref_mut(&mut self, x: usize, y: usize) -> &mut T; + + /// Get a mutable reference to the current value at the specified position if position is in bounds. + /// + /// # Arguments + /// + /// * `x` and `y`: position of the cell + /// + /// returns: Reference to cell or None + fn get_ref_mut_optional(&mut self, x: isize, y: isize) -> Option<&mut T>; +} diff --git a/crates/servicepoint/src/lib.rs b/crates/servicepoint/src/lib.rs index d68801c..1951087 100644 --- a/crates/servicepoint/src/lib.rs +++ b/crates/servicepoint/src/lib.rs @@ -8,7 +8,7 @@ pub use crate::command::{Brightness, Command, Offset, Origin}; pub use crate::compression_code::CompressionCode; pub use crate::connection::Connection; pub use crate::data_ref::DataRef; -pub use crate::grid::Grid; +pub use crate::grid::{Grid, RefGrid}; pub use crate::packet::{Header, Packet, Payload}; pub use crate::pixel_grid::PixelGrid; diff --git a/crates/servicepoint/src/pixel_grid.rs b/crates/servicepoint/src/pixel_grid.rs index c6d02dd..e6a3840 100644 --- a/crates/servicepoint/src/pixel_grid.rs +++ b/crates/servicepoint/src/pixel_grid.rs @@ -60,6 +60,10 @@ impl PixelGrid { } } + fn is_position_valid(&self, x: isize, y: isize) -> bool { + x > 0 && x < self.width as isize && y > 0 && y < self.height as isize + } + fn check_indexes(&self, x: usize, y: usize) { assert!( x < self.width, @@ -96,6 +100,27 @@ impl Grid for PixelGrid { self.bit_vec.get(x + y * self.width) } + fn get_optional(&self, x: isize, y: isize) -> Option { + if self.is_position_valid(x, y) { + Some(self.get(x as usize, y as usize)) + } else { + None + } + } + + fn set_optional( + &mut self, + x: isize, + y: isize, + value: bool, + ) -> Option { + if self.is_position_valid(x, y) { + Some(self.set(x as usize, y as usize, value)) + } else { + None + } + } + /// Sets the state of all pixels in the `PixelGrid`. /// /// # Arguments