From 6a2ee5fcfa4347dbc19a54ee689720571d7b99e8 Mon Sep 17 00:00:00 2001 From: Vinzenz Schroeter Date: Fri, 17 May 2024 23:48:30 +0200 Subject: [PATCH] add better panic messages on oob index --- servicepoint2/src/bit_vec.rs | 15 +++++++++++---- servicepoint2/src/byte_grid.rs | 11 +++++++++++ servicepoint2/src/command.rs | 4 ++-- servicepoint2/src/connection.rs | 2 +- servicepoint2/src/pixel_grid.rs | 10 ++++++++++ 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/servicepoint2/src/bit_vec.rs b/servicepoint2/src/bit_vec.rs index ebb9499..455123f 100644 --- a/servicepoint2/src/bit_vec.rs +++ b/servicepoint2/src/bit_vec.rs @@ -1,6 +1,7 @@ /// A vector of bits #[derive(Clone, PartialEq)] pub struct BitVec { + size: usize, data: Vec, } @@ -15,6 +16,7 @@ impl BitVec { pub fn new(size: usize) -> BitVec { assert_eq!(size % 8, 0); Self { + size, data: vec![0; size / 8], } } @@ -73,7 +75,7 @@ impl BitVec { /// Gets the length in bits pub fn len(&self) -> usize { - self.data.len() * 8 + self.size } /// returns true if length is 0. @@ -87,9 +89,13 @@ impl BitVec { } /// Calculates the byte index and bitmask for a specific bit in the vector - fn get_indexes(&self, index: usize) -> (usize, u8) { - let byte_index = index / 8; - let bit_in_byte_index = 7 - index % 8; + fn get_indexes(&self, bit_index: usize) -> (usize, u8) { + if bit_index >= self.size { + panic!("bit index {bit_index} is outside of range 0..<{}", self.size) + } + + let byte_index = bit_index / 8; + let bit_in_byte_index = 7 - bit_index % 8; let bit_mask: u8 = 1 << bit_in_byte_index; (byte_index, bit_mask) } @@ -106,6 +112,7 @@ impl From<&[u8]> for BitVec { /// Interpret the data as a series of bits and load then into a new `BitVec` instance. fn from(value: &[u8]) -> Self { Self { + size: value.len() * 8, data: Vec::from(value), } } diff --git a/servicepoint2/src/byte_grid.rs b/servicepoint2/src/byte_grid.rs index 5509e46..0712717 100644 --- a/servicepoint2/src/byte_grid.rs +++ b/servicepoint2/src/byte_grid.rs @@ -38,11 +38,13 @@ impl ByteGrid { /// /// returns: current byte value pub fn get(&self, x: usize, y: usize) -> u8 { + self.check_indexes(x, y); self.data[x + y * self.width] } /// Sets the byte value at the specified position pub fn set(&mut self, x: usize, y: usize, value: u8) { + self.check_indexes(x, y); self.data[x + y * self.width] = value; } @@ -65,6 +67,15 @@ impl ByteGrid { pub fn height(&self) -> usize { self.height } + + fn check_indexes(&self, x: usize, y: usize) { + if x >= self.width { + panic!("cannot access byte {x}-{y} because x is outside of bounds 0..{}", self.width) + } + if y >= self.height { + panic!("cannot access byte {x}-{y} because y is outside of bounds 0..{}", self.height) + } + } } impl From for Vec { diff --git a/servicepoint2/src/command.rs b/servicepoint2/src/command.rs index 0d46cff..27d1cd0 100644 --- a/servicepoint2/src/command.rs +++ b/servicepoint2/src/command.rs @@ -706,7 +706,7 @@ mod tests { fn error_reserved_used() { let Packet(header, payload) = Command::BitmapLinear(0, BitVec::new(8), CompressionCode::Uncompressed).into(); - let Header(command, offset, length, sub, reserved) = header; + let Header(command, offset, length, sub, _reserved) = header; let p = Packet(Header(command, offset, length, sub, 69), payload); assert_eq!( Command::try_from(p), @@ -717,7 +717,7 @@ mod tests { fn error_invalid_compression() { let Packet(header, payload) = Command::BitmapLinear(0, BitVec::new(8), CompressionCode::Uncompressed).into(); - let Header(command, offset, length, sub, reserved) = header; + let Header(command, offset, length, _sub, reserved) = header; let p = Packet(Header(command, offset, length, 42, reserved), payload); assert_eq!( Command::try_from(p), diff --git a/servicepoint2/src/connection.rs b/servicepoint2/src/connection.rs index d67e8b1..7480166 100644 --- a/servicepoint2/src/connection.rs +++ b/servicepoint2/src/connection.rs @@ -51,7 +51,7 @@ impl Connection { /// pixels.fill(true); /// /// // send pixels to display - /// connection.send(servicepoint2::Command::BitmapLinearWin(servicepoint2::Origin::top_left(), pixels, CompressionCode::Lzma).into()) + /// connection.send(servicepoint2::Command::BitmapLinearWin(servicepoint2::Origin(0, 0), pixels, CompressionCode::Lzma).into()) /// .expect("send failed"); /// ``` pub fn send(&self, packet: Packet) -> Result<(), std::io::Error> { diff --git a/servicepoint2/src/pixel_grid.rs b/servicepoint2/src/pixel_grid.rs index 39b1b08..386b465 100644 --- a/servicepoint2/src/pixel_grid.rs +++ b/servicepoint2/src/pixel_grid.rs @@ -60,6 +60,7 @@ impl PixelGrid { /// Sets the byte value at the specified position pub fn set(&mut self, x: usize, y: usize, value: bool) -> bool { + self.check_indexes(x, y); self.bit_vec.set(x + y * self.width, value) } @@ -88,6 +89,15 @@ impl PixelGrid { pub fn height(&self) -> usize { self.height } + + fn check_indexes(&self, x: usize, y: usize) { + if x >= self.width { + panic!("cannot access pixel {x}-{y} because x is outside of bounds 0..{}", self.width) + } + if y >= self.height { + panic!("cannot access pixel {x}-{y} because y is outside of bounds 0..{}", self.height) + } + } } impl From for Vec {