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-03 13:48:01 +00:00
|
|
|
$crate::Grid::from_vec(&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)*)];
|
2020-04-02 21:08:02 +00:00
|
|
|
let mut vec = Vec::new();
|
2020-04-03 13:48:01 +00:00
|
|
|
let cols = $crate::count!($($x0)*);
|
2020-04-02 21:08:02 +00:00
|
|
|
|
|
|
|
$( vec.push($x0); )*
|
|
|
|
|
|
|
|
$(
|
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;
|
|
|
|
$( vec.push($x); )*
|
|
|
|
)*
|
|
|
|
|
2020-04-03 13:48:01 +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;
|
|
|
|
/// let grid = Grid::from_vec(&vec![1,2,3,4,5,6], 3);
|
|
|
|
/// 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;
|
|
|
|
/// Grid::from_vec(&vec![1,2,3,4,5], 3);
|
|
|
|
/// ```
|
|
|
|
pub fn from_vec(vec: &Vec<T>, cols: usize) -> Grid<T> {
|
|
|
|
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.");
|
|
|
|
}
|
|
|
|
Grid {
|
|
|
|
data: vec.to_vec(),
|
|
|
|
rows: vec.len() / cols,
|
|
|
|
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() {
|
|
|
|
//unsafe { Some(&self.index(row).get_unchecked(col)) }
|
|
|
|
Some(&self.data[row * self.cols() + col])
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2020-04-01 21:29:06 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[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() {
|
|
|
|
let grid: Grid<u8> = Grid::from_vec(&vec![], 0);
|
|
|
|
assert_eq!(grid.size(), (0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn from_vec_panics_1() {
|
|
|
|
let _: Grid<u8> = Grid::from_vec(&vec![1, 2, 3], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn from_vec_panics_2() {
|
|
|
|
let _: Grid<u8> = Grid::from_vec(&vec![1, 2, 3], 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn from_vec_panics_3() {
|
|
|
|
let _: Grid<u8> = Grid::from_vec(&vec![], 1);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
#[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
|
|
|
}
|