grid/src/lib.rs

401 lines
9.6 KiB
Rust
Raw Normal View History

2020-04-05 12:48:43 +00:00
use std::fmt;
2020-04-01 20:17:54 +00:00
use std::ops::Index;
2020-04-01 21:29:06 +00:00
use std::ops::IndexMut;
2020-04-01 20:17:54 +00:00
2020-04-03 13:48:01 +00:00
/// Stores elements of a certain type in a 2D grid structure.
2020-04-01 20:17:54 +00:00
pub struct Grid<T> {
data: Vec<T>,
2020-04-02 21:08:02 +00:00
cols: usize,
2020-04-01 21:29:06 +00:00
rows: usize,
2020-04-01 20:17:54 +00:00
}
2020-04-03 13:48:01 +00:00
#[doc(hidden)]
#[macro_export]
2020-04-02 21:08:02 +00:00
macro_rules! count {
() => (0usize);
2020-04-03 13:48:01 +00:00
( $x:tt $($xs:tt)* ) => (1usize + $crate::count!($($xs)*));
2020-04-02 21:08:02 +00:00
}
2020-04-03 13:48:01 +00:00
/// Init a grid with values.
/// ```
/// use grid::grid;
/// let grid = grid![[1, 2, 3]
/// [4, 5, 6]
/// [7, 8, 9]];
/// assert_eq!(grid.size(), (3, 3))
/// ```
2020-04-02 21:08:02 +00:00
#[macro_export]
macro_rules! grid {
() => {
Grid {
rows: 0,
cols: 0,
data: vec![],
}
};
( [$( $x:expr ),* ]) => { {
let vec = vec![$($x),*];
2020-04-04 16:18:37 +00:00
let len = vec.len();
$crate::Grid::from_vec(vec, len)
2020-04-02 21:08:02 +00:00
} };
2020-04-02 21:23:23 +00:00
( [$( $x0:expr ),*] $([$( $x:expr ),*])* ) => {
2020-04-02 21:08:02 +00:00
{
2020-04-03 13:48:01 +00:00
let mut _assert_width0 = [(); $crate::count!($($x0)*)];
let cols = $crate::count!($($x0)*);
2020-04-04 16:43:28 +00:00
let rows = 1usize;
2020-04-02 21:08:02 +00:00
$(
2020-04-03 13:48:01 +00:00
let _assert_width = [(); $crate::count!($($x)*)];
2020-04-02 21:08:02 +00:00
_assert_width0 = _assert_width;
2020-04-04 16:43:28 +00:00
let rows = rows + 1usize;
2020-04-02 21:08:02 +00:00
)*
2020-04-04 16:43:28 +00:00
let mut vec = Vec::with_capacity(rows * cols);
$( vec.push($x0); )*
$( $( vec.push($x); )* )*
2020-04-04 16:18:37 +00:00
$crate::Grid::from_vec(vec, cols)
2020-04-02 21:08:02 +00:00
}
};
}
2020-04-01 20:17:54 +00:00
impl<T: Clone> Grid<T> {
2020-04-02 21:08:02 +00:00
/// Init a grid of size rows x columns with default values of the given type.
/// For example this will generate a 2x3 grid of zeros:
/// ```
/// use grid::Grid;
/// let grid : Grid<u8> = Grid::new(2,2);
/// assert_eq!(grid[0][0], 0);
/// ```
pub fn new(rows: usize, cols: usize) -> Grid<T>
where
T: Default,
{
if rows < 1 || cols < 1 {
panic!("Grid size of rows and columns must be greater than zero.");
}
Grid {
data: vec![T::default(); rows * cols],
cols: cols,
rows: rows,
}
}
/// Init a grid of size rows x columns with the given data element.
pub fn init(rows: usize, cols: usize, data: T) -> Grid<T> {
if rows < 1 || cols < 1 {
2020-04-01 21:29:06 +00:00
panic!("Grid size of rows and columns must be greater than zero.");
}
2020-04-01 20:17:54 +00:00
Grid {
2020-04-02 21:08:02 +00:00
data: vec![data; rows * cols],
cols: cols,
2020-04-01 21:29:06 +00:00
rows: rows,
2020-04-01 20:17:54 +00:00
}
}
2020-04-03 13:48:01 +00:00
/// Returns a grid from a vector with a given column length.
/// The length of `vec` must be a multiple of `cols`.
///
/// For example:
///
/// ```
/// use grid::Grid;
2020-04-04 17:13:55 +00:00
/// let grid = Grid::from_vec(vec![1,2,3,4,5,6], 3);
2020-04-03 13:48:01 +00:00
/// assert_eq!(grid.size(), (2, 3));
/// ```
///
/// will create a grid with the following layout:
/// [1,2,3]
/// [4,5,6]
///
/// This example will fail, because `vec.len()` is not a multiple of `cols`:
///
/// ``` should_panic
/// use grid::Grid;
2020-04-04 17:13:55 +00:00
/// Grid::from_vec(vec![1,2,3,4,5], 3);
2020-04-03 13:48:01 +00:00
/// ```
2020-04-04 16:18:37 +00:00
pub fn from_vec(vec: Vec<T>, cols: usize) -> Grid<T> {
2020-04-03 13:48:01 +00:00
if vec.len() == 0 {
if cols == 0 {
return grid![];
} else {
panic!("Vector length is zero, but cols is {:?}", cols);
}
}
if vec.len() % cols != 0 {
panic!("Vector length must be a multiple of cols.");
}
2020-04-04 16:18:37 +00:00
let rows = vec.len();
2020-04-03 13:48:01 +00:00
Grid {
2020-04-04 16:18:37 +00:00
data: vec,
rows: rows / cols,
2020-04-03 13:48:01 +00:00
cols: cols,
}
}
2020-04-02 21:08:02 +00:00
/// Access a certain element in the grid.
/// Returns None if an element beyond the grid bounds is tried to be accessed.
2020-04-03 13:48:01 +00:00
pub fn get(&self, row: usize, col: usize) -> Option<&T> {
if row < self.rows && col < self.cols() {
2020-04-04 11:28:18 +00:00
unsafe { Some(&self.data.get_unchecked(row * self.cols() + col)) }
2020-04-03 13:48:01 +00:00
} else {
None
}
2020-04-01 21:29:06 +00:00
}
2020-04-04 19:54:44 +00:00
/// Mutable access to a certain element in the grid.
/// Returns None if an element beyond the grid bounds is tried to be accessed.
pub fn get_mut(&mut self, row: usize, col: usize) -> Option<&mut T> {
if row < self.rows && col < self.cols() {
let cols = self.cols();
unsafe { Some(self.data.get_unchecked_mut(row * cols + col)) }
} else {
None
}
}
2020-04-02 21:08:02 +00:00
/// Returns the size of the gird as a two element tuple.
/// First element are the number of rows and the second the columns.
2020-04-01 21:29:06 +00:00
pub fn size(&self) -> (usize, usize) {
2020-04-02 21:08:02 +00:00
(self.rows, self.cols)
2020-04-01 20:17:54 +00:00
}
2020-04-03 13:48:01 +00:00
/// Returns the number of rows of the grid.
pub fn rows(&self) -> usize {
self.rows
}
/// Returns the number of columns of the grid.
pub fn cols(&self) -> usize {
self.cols
}
2020-04-01 20:17:54 +00:00
}
2020-04-04 19:11:45 +00:00
impl<T: Clone> Clone for Grid<T> {
fn clone(&self) -> Self {
Grid {
rows: self.rows,
cols: self.cols,
data: self.data.clone(),
}
}
}
2020-04-01 20:17:54 +00:00
impl<T: Clone> Index<usize> for Grid<T> {
type Output = [T];
fn index(&self, idx: usize) -> &Self::Output {
2020-04-03 13:48:01 +00:00
if idx < self.rows {
&self.data[(idx * &self.cols)..]
} else {
2020-04-01 21:29:06 +00:00
panic!(
2020-04-03 13:48:01 +00:00
"index {:?} out of bounds. Grid has {:?} rows.",
2020-04-01 21:29:06 +00:00
self.rows, idx
);
}
}
}
impl<T: Clone> IndexMut<usize> for Grid<T> {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
2020-04-02 21:08:02 +00:00
&mut self.data[(idx * &self.cols)..]
2020-04-01 20:17:54 +00:00
}
}
2020-04-05 12:48:43 +00:00
impl<T: fmt::Debug> fmt::Debug for Grid<T> {
#[allow(unused_must_use)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[");
if self.cols > 0 {
for (i, _) in self.data.iter().enumerate().step_by(self.cols) {
write!(f, "{:?}", &self.data[i..(i + self.cols)]);
}
}
write!(f, "]")
}
}
2020-04-01 20:17:54 +00:00
#[cfg(test)]
mod test {
use super::*;
2020-04-05 12:48:43 +00:00
#[test]
fn fmt_empty() {
let grid: Grid<u8> = grid![];
assert_eq!(format!("{:?}", grid), "[]");
}
#[test]
fn fmt_row() {
let grid: Grid<u8> = grid![[1, 2, 3]];
assert_eq!(format!("{:?}", grid), "[[1, 2, 3]]");
}
#[test]
fn fmt_grid() {
let grid: Grid<u8> = grid![[1,2,3][4,5,6][7,8,9]];
assert_eq!(format!("{:?}", grid), "[[1, 2, 3][4, 5, 6][7, 8, 9]]");
}
2020-04-04 19:11:45 +00:00
#[test]
fn clone() {
let grid = grid![[1, 2, 3][4, 5, 6]];
let mut clone = grid.clone();
clone[0][2] = 10;
assert_eq!(grid[0][2], 3);
assert_eq!(clone[0][2], 10);
}
2020-04-01 20:17:54 +00:00
#[test]
2020-04-02 21:08:02 +00:00
fn macro_init() {
2020-04-02 21:23:23 +00:00
let grid = grid![[1, 2, 3][4, 5, 6]];
2020-04-02 21:08:02 +00:00
assert_eq!(grid[0][0], 1);
assert_eq!(grid[0][1], 2);
assert_eq!(grid[0][2], 3);
assert_eq!(grid[1][0], 4);
assert_eq!(grid[1][1], 5);
assert_eq!(grid[1][2], 6);
2020-04-01 20:17:54 +00:00
}
2020-04-02 21:08:02 +00:00
2020-04-02 21:23:23 +00:00
#[test]
fn macro_init_2() {
let grid = grid![[1, 2, 3]
[4, 5, 6]
2020-04-03 13:48:01 +00:00
[7, 8, 9]];
2020-04-02 21:23:23 +00:00
assert_eq!(grid.size(), (3, 3))
}
2020-04-03 13:48:01 +00:00
#[test]
fn macro_init_char() {
let grid = grid![['a', 'b', 'c']
['a', 'b', 'c']
['a', 'b', 'c']];
assert_eq!(grid.size(), (3, 3));
assert_eq!(grid[1][1], 'b');
}
2020-04-02 21:08:02 +00:00
#[test]
fn macro_one_row() {
let grid: Grid<usize> = grid![[1, 2, 3, 4]];
2020-04-02 21:23:23 +00:00
assert_eq!(grid.size(), (1, 4));
2020-04-02 21:08:02 +00:00
assert_eq!(grid[0][0], 1);
assert_eq!(grid[0][1], 2);
assert_eq!(grid[0][2], 3);
}
#[test]
fn macro_init_empty() {
let grid: Grid<usize> = grid![];
assert_eq!(grid.size(), (0, 0));
}
2020-04-03 13:48:01 +00:00
#[test]
fn from_vec_zero() {
2020-04-04 16:18:37 +00:00
let grid: Grid<u8> = Grid::from_vec(vec![], 0);
2020-04-03 13:48:01 +00:00
assert_eq!(grid.size(), (0, 0));
}
#[test]
#[should_panic]
fn from_vec_panics_1() {
2020-04-04 16:18:37 +00:00
let _: Grid<u8> = Grid::from_vec(vec![1, 2, 3], 0);
2020-04-03 13:48:01 +00:00
}
#[test]
#[should_panic]
fn from_vec_panics_2() {
2020-04-04 16:18:37 +00:00
let _: Grid<u8> = Grid::from_vec(vec![1, 2, 3], 2);
2020-04-03 13:48:01 +00:00
}
#[test]
#[should_panic]
fn from_vec_panics_3() {
2020-04-04 16:18:37 +00:00
let _: Grid<u8> = Grid::from_vec(vec![], 1);
2020-04-03 13:48:01 +00:00
}
2020-04-02 21:08:02 +00:00
#[test]
fn init() {
Grid::init(1, 2, 3);
Grid::init(1, 2, 1.2);
Grid::init(1, 2, 'a');
}
#[test]
fn new() {
let grid: Grid<u8> = Grid::new(1, 2);
assert_eq!(grid[0][0], 0);
}
2020-04-01 21:29:06 +00:00
#[test]
#[should_panic]
2020-04-02 21:08:02 +00:00
fn init_panics() {
Grid::init(0, 2, 3);
2020-04-01 21:29:06 +00:00
}
#[test]
#[should_panic]
fn ctr_panics_2() {
2020-04-02 21:08:02 +00:00
Grid::init(1, 0, 3);
2020-04-01 21:29:06 +00:00
}
2020-04-01 20:17:54 +00:00
#[test]
fn get() {
2020-04-02 21:08:02 +00:00
let grid = Grid::init(1, 2, 3);
2020-04-01 20:17:54 +00:00
assert_eq!(grid.get(0, 0), Some(&3));
}
2020-04-01 21:29:06 +00:00
#[test]
fn get_none() {
2020-04-02 21:08:02 +00:00
let grid = Grid::init(1, 2, 3);
2020-04-01 21:29:06 +00:00
assert_eq!(grid.get(1, 0), None);
}
2020-04-01 20:17:54 +00:00
2020-04-04 19:54:44 +00:00
#[test]
fn get_mut() {
let mut grid = Grid::init(1, 2, 3);
let mut_ref = grid.get_mut(0, 0).unwrap();
*mut_ref = 5;
assert_eq!(grid[0][0], 5);
}
#[test]
fn get_mut_none() {
let mut grid = Grid::init(1, 2, 3);
let mut_ref = grid.get_mut(1, 4);
assert_eq!(mut_ref, None);
}
2020-04-01 20:17:54 +00:00
#[test]
fn idx() {
2020-04-02 21:08:02 +00:00
let grid = Grid::init(1, 2, 3);
2020-04-01 20:17:54 +00:00
assert_eq!(grid[0][0], 3);
}
2020-04-01 21:29:06 +00:00
#[test]
#[should_panic]
fn idx_panic_1() {
2020-04-02 21:08:02 +00:00
let grid = Grid::init(1, 2, 3);
2020-04-01 21:29:06 +00:00
grid[20][0];
}
#[test]
#[should_panic]
fn idx_panic_2() {
2020-04-02 21:08:02 +00:00
let grid = Grid::init(1, 2, 3);
2020-04-01 21:29:06 +00:00
grid[0][20];
}
#[test]
fn idx_set() {
2020-04-02 21:08:02 +00:00
let mut grid = Grid::init(1, 2, 3);
2020-04-01 21:29:06 +00:00
grid[0][0] = 4;
assert_eq!(grid[0][0], 4);
}
#[test]
fn size() {
2020-04-02 21:08:02 +00:00
let grid = Grid::init(1, 2, 3);
2020-04-01 21:29:06 +00:00
assert_eq!(grid.size(), (1, 2));
}
2020-04-01 20:17:54 +00:00
}