mirror of
https://github.com/cccb/servicepoint.git
synced 2025-01-18 18:10:14 +01:00
add better panic messages on oob index
This commit is contained in:
parent
312fff95b3
commit
6a2ee5fcfa
|
@ -1,6 +1,7 @@
|
||||||
/// A vector of bits
|
/// A vector of bits
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct BitVec {
|
pub struct BitVec {
|
||||||
|
size: usize,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ impl BitVec {
|
||||||
pub fn new(size: usize) -> BitVec {
|
pub fn new(size: usize) -> BitVec {
|
||||||
assert_eq!(size % 8, 0);
|
assert_eq!(size % 8, 0);
|
||||||
Self {
|
Self {
|
||||||
|
size,
|
||||||
data: vec![0; size / 8],
|
data: vec![0; size / 8],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +75,7 @@ impl BitVec {
|
||||||
|
|
||||||
/// Gets the length in bits
|
/// Gets the length in bits
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.data.len() * 8
|
self.size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns true if length is 0.
|
/// 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
|
/// Calculates the byte index and bitmask for a specific bit in the vector
|
||||||
fn get_indexes(&self, index: usize) -> (usize, u8) {
|
fn get_indexes(&self, bit_index: usize) -> (usize, u8) {
|
||||||
let byte_index = index / 8;
|
if bit_index >= self.size {
|
||||||
let bit_in_byte_index = 7 - index % 8;
|
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;
|
let bit_mask: u8 = 1 << bit_in_byte_index;
|
||||||
(byte_index, bit_mask)
|
(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.
|
/// Interpret the data as a series of bits and load then into a new `BitVec` instance.
|
||||||
fn from(value: &[u8]) -> Self {
|
fn from(value: &[u8]) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
size: value.len() * 8,
|
||||||
data: Vec::from(value),
|
data: Vec::from(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,13 @@ impl ByteGrid {
|
||||||
///
|
///
|
||||||
/// returns: current byte value
|
/// returns: current byte value
|
||||||
pub fn get(&self, x: usize, y: usize) -> u8 {
|
pub fn get(&self, x: usize, y: usize) -> u8 {
|
||||||
|
self.check_indexes(x, y);
|
||||||
self.data[x + y * self.width]
|
self.data[x + y * self.width]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the byte value at the specified position
|
/// Sets the byte value at the specified position
|
||||||
pub fn set(&mut self, x: usize, y: usize, value: u8) {
|
pub fn set(&mut self, x: usize, y: usize, value: u8) {
|
||||||
|
self.check_indexes(x, y);
|
||||||
self.data[x + y * self.width] = value;
|
self.data[x + y * self.width] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +67,15 @@ impl ByteGrid {
|
||||||
pub fn height(&self) -> usize {
|
pub fn height(&self) -> usize {
|
||||||
self.height
|
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<ByteGrid> for Vec<u8> {
|
impl From<ByteGrid> for Vec<u8> {
|
||||||
|
|
|
@ -706,7 +706,7 @@ mod tests {
|
||||||
fn error_reserved_used() {
|
fn error_reserved_used() {
|
||||||
let Packet(header, payload)
|
let Packet(header, payload)
|
||||||
= Command::BitmapLinear(0, BitVec::new(8), CompressionCode::Uncompressed).into();
|
= 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);
|
let p = Packet(Header(command, offset, length, sub, 69), payload);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Command::try_from(p),
|
Command::try_from(p),
|
||||||
|
@ -717,7 +717,7 @@ mod tests {
|
||||||
fn error_invalid_compression() {
|
fn error_invalid_compression() {
|
||||||
let Packet(header, payload)
|
let Packet(header, payload)
|
||||||
= Command::BitmapLinear(0, BitVec::new(8), CompressionCode::Uncompressed).into();
|
= 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);
|
let p = Packet(Header(command, offset, length, 42, reserved), payload);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Command::try_from(p),
|
Command::try_from(p),
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl Connection {
|
||||||
/// pixels.fill(true);
|
/// pixels.fill(true);
|
||||||
///
|
///
|
||||||
/// // send pixels to display
|
/// // 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");
|
/// .expect("send failed");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn send(&self, packet: Packet) -> Result<(), std::io::Error> {
|
pub fn send(&self, packet: Packet) -> Result<(), std::io::Error> {
|
||||||
|
|
|
@ -60,6 +60,7 @@ impl PixelGrid {
|
||||||
|
|
||||||
/// Sets the byte value at the specified position
|
/// Sets the byte value at the specified position
|
||||||
pub fn set(&mut self, x: usize, y: usize, value: bool) -> bool {
|
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)
|
self.bit_vec.set(x + y * self.width, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +89,15 @@ impl PixelGrid {
|
||||||
pub fn height(&self) -> usize {
|
pub fn height(&self) -> usize {
|
||||||
self.height
|
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<PixelGrid> for Vec<u8> {
|
impl From<PixelGrid> for Vec<u8> {
|
||||||
|
|
Loading…
Reference in a new issue