Fix #13 overflow size calculation and init zero grid

This commit is contained in:
Armin 2022-08-17 21:40:03 +02:00
parent 4aa88f4a65
commit 30caea7709

View file

@ -102,7 +102,7 @@ macro_rules! grid {
let rows = rows + 1usize; let rows = rows + 1usize;
)* )*
let mut vec = Vec::with_capacity(rows * cols); let mut vec = Vec::with_capacity(rows.checked_mul(cols).unwrap());
$( vec.push($x0); )* $( vec.push($x0); )*
$( $( vec.push($x); )* )* $( $( vec.push($x); )* )*
@ -147,7 +147,7 @@ impl<T> Grid<T> {
return Grid { data: Vec::new(), rows:0, cols: 0 } return Grid { data: Vec::new(), rows:0, cols: 0 }
} }
let mut data = Vec::new(); let mut data = Vec::new();
data.resize_with(rows * cols, T::default); data.resize_with(rows.checked_mul(cols).unwrap(), T::default);
Grid { data, cols, rows } Grid { data, cols, rows }
} }
@ -162,8 +162,11 @@ impl<T> Grid<T> {
where where
T: Clone, T: Clone,
{ {
if rows == 0 || cols == 0 {
return Grid { data: Vec::new(), rows:0, cols: 0 }
}
Grid { Grid {
data: vec![data; rows * cols], data: vec![data; rows.checked_mul(cols).unwrap()],
cols, cols,
rows, rows,
} }
@ -283,7 +286,7 @@ impl<T> Grid<T> {
/// assert!(grid.is_empty()); /// assert!(grid.is_empty());
/// ``` /// ```
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
return self.data.is_empty() self.data.is_empty()
} }
/// Clears the grid. /// Clears the grid.
@ -463,7 +466,10 @@ impl<T> Grid<T> {
/// # Panics /// # Panics
/// ///
/// Panics if the grid is not empty and `row.len() != grid.cols()`. /// Panics if the grid is not empty and `row.len() != grid.cols()`.
///
/// Also panics if `row.len() == 0`
pub fn push_row(&mut self, row: Vec<T>) { pub fn push_row(&mut self, row: Vec<T>) {
assert_ne!(row.len(), 0);
if self.rows > 0 && row.len() != self.cols { if self.rows > 0 && row.len() != self.cols {
panic!( panic!(
"pushed row does not match. Length must be {:?}, but was {:?}.", "pushed row does not match. Length must be {:?}, but was {:?}.",
@ -508,7 +514,10 @@ impl<T> Grid<T> {
/// # Panics /// # Panics
/// ///
/// Panics if the grid is not empty and `col.len() != grid.rows()`. /// Panics if the grid is not empty and `col.len() != grid.rows()`.
///
/// Also panics if `col.len() == 0`
pub fn push_col(&mut self, col: Vec<T>) { pub fn push_col(&mut self, col: Vec<T>) {
assert_ne!(col.len(), 0);
if self.cols > 0 && col.len() != self.rows { if self.cols > 0 && col.len() != self.rows {
panic!( panic!(
"pushed column does not match. Length must be {:?}, but was {:?}.", "pushed column does not match. Length must be {:?}, but was {:?}.",
@ -590,7 +599,14 @@ impl<T> Grid<T> {
/// assert_eq!(grid[2], [4,5,6]); /// assert_eq!(grid[2], [4,5,6]);
/// assert_eq!(grid.size(), (3,3)) /// assert_eq!(grid.size(), (3,3))
/// ``` /// ```
///
/// # Panics
///
/// Panics if the grid is not empty and `row.len() != grid.cols()`.
///
/// Also panics if `row.len() == 0`
pub fn insert_row(&mut self, index: usize, row: Vec<T>) { pub fn insert_row(&mut self, index: usize, row: Vec<T>) {
assert_ne!(row.len(), 0);
if row.len() != self.cols { if row.len() != self.cols {
panic!("Inserted row must be of length {}, but was {}.", self.cols, row.len()); panic!("Inserted row must be of length {}, but was {}.", self.cols, row.len());
} }
@ -616,7 +632,14 @@ impl<T> Grid<T> {
/// assert_eq!(grid[1], [4,9,5,6]); /// assert_eq!(grid[1], [4,9,5,6]);
/// assert_eq!(grid.size(), (2,4)) /// assert_eq!(grid.size(), (2,4))
/// ``` /// ```
///
/// # Panics
///
/// Panics if the grid is not empty and `col.len() != grid.rows()`.
///
/// Also panics if `col.len() == 0`
pub fn insert_col(&mut self, index: usize, col: Vec<T>) { pub fn insert_col(&mut self, index: usize, col: Vec<T>) {
assert_ne!(col.len(), 0);
if col.len() != self.rows { if col.len() != self.rows {
panic!("Inserted col must be of length {}, but was {}.", self.rows, col.len()); panic!("Inserted col must be of length {}, but was {}.", self.rows, col.len());
} }
@ -767,6 +790,20 @@ impl<T: Eq> Eq for Grid<T> {}
mod test { mod test {
use super::*; use super::*;
#[test]
#[should_panic]
fn from_vec_zero_with_cols() {
let _: Grid<u8> = Grid::from_vec(vec![], 1);
}
#[test]
fn from_vec_zero() {
let grid: Grid<u8> = Grid::from_vec(vec![], 0);
grid.is_empty();
assert_eq!(grid.rows(), 0);
assert_eq!(grid.cols(), 0);
}
#[test] #[test]
fn insert_col_at_end() { fn insert_col_at_end() {
let mut grid: Grid<u8> = Grid::from_vec(vec![1, 2, 3, 4], 2); let mut grid: Grid<u8> = Grid::from_vec(vec![1, 2, 3, 4], 2);
@ -983,6 +1020,13 @@ mod test {
grid.push_col(vec!['b', 'b']); grid.push_col(vec!['b', 'b']);
} }
#[test]
#[should_panic]
fn push_col_zero_len() {
let mut grid: Grid<char> = grid![];
grid.push_col(vec![]);
}
#[test] #[test]
fn push_row_empty() { fn push_row_empty() {
let mut grid: Grid<char> = grid![]; let mut grid: Grid<char> = grid![];
@ -991,6 +1035,13 @@ mod test {
assert_eq!(grid[0][0], 'b'); assert_eq!(grid[0][0], 'b');
} }
#[test]
#[should_panic]
fn push_empty_row() {
let mut grid = Grid::init(0, 1, 0);
grid.push_row(vec![]);
}
#[test] #[test]
#[should_panic] #[should_panic]
fn push_row_wrong_size() { fn push_row_wrong_size() {
@ -1170,6 +1221,14 @@ mod test {
Grid::init(1, 2, 'a'); Grid::init(1, 2, 'a');
} }
#[test]
fn init_empty() {
let grid = Grid::init(0, 1, 0);
assert!(grid.is_empty());
assert_eq!(grid.cols(), 0);
assert_eq!(grid.rows(), 0);
}
#[test] #[test]
fn new() { fn new() {
let grid: Grid<u8> = Grid::new(1, 2); let grid: Grid<u8> = Grid::new(1, 2);
@ -1182,6 +1241,14 @@ mod test {
let _ : Grid<u8>= Grid::new(usize::MAX, 2); let _ : Grid<u8>= Grid::new(usize::MAX, 2);
} }
#[test]
fn new_empty() {
let grid : Grid<u8> = Grid::new(0, 1);
assert!(grid.is_empty());
assert_eq!(grid.cols(), 0);
assert_eq!(grid.rows(), 0);
}
#[test] #[test]
#[should_panic] #[should_panic]
fn init_panics() { fn init_panics() {