board/
lib.rs

1//! A simple `Vec` wrapper that is accessible as if it were a 2d vector.
2//! Implements `Index<(x, y)>` and `IndexMut<(x, y)>`.
3//!
4//! The underlying `Vec` is only mutably accessible through methods of `Vec2d`.
5//! If you want ownership of `Vec`, consume the `Vec2d` with `to_vec`.
6
7use std::ops::{Index, IndexMut};
8use vec2d_error::Vec2dError;
9use serde::{Serialize, Deserialize};
10pub mod vec2d_error;
11pub type Pos = (usize, usize);
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
14/// 
15pub struct Vec2d<T: Clone> {
16    tiles: Vec<T>,
17    width: usize
18}
19
20impl<T: Clone> Index<Pos> for Vec2d<T> {
21    type Output = T;
22
23    fn index(&self, (x, y): Pos) -> &Self::Output {
24        if x >= self.width { panic!("Tried to index with x: {}, with width: {}", x, self.width) }
25        &self.tiles[y * self.width + x]
26    }
27}
28
29impl<T: Clone> IndexMut<Pos> for Vec2d<T> {
30    fn index_mut(&mut self, (x, y): Pos) -> &mut Self::Output {
31        if x >= self.width { panic!("Tried to index with x: {}, with width: {}", x, self.width) }
32        &mut self.tiles[y * self.width + x]
33    }
34}
35
36impl<T: Clone> Vec2d<T> {
37    /// Create a new `Vec2d`
38    /// # Examples
39    /// ```
40    /// let board = board::Vec2d::new('a', 2, 3).unwrap();
41    /// assert_eq!(board.tiles(), &vec!['a','a','a','a','a','a']);
42    /// assert_eq!(board.width(), 2);
43    /// assert_eq!(board.height(), 3);
44    /// ```
45    pub fn new(default: T, width: usize, height: usize) -> Result<Vec2d<T>, Vec2dError> {
46        let no_tiles = width * height;
47        if no_tiles == 0 {
48            Err(Vec2dError::WidthOrHeightIs0{ width, height })
49        } else {
50            let mut tiles = Vec::with_capacity(no_tiles);
51            for _ in 1..no_tiles {
52                tiles.push(default.clone());
53            } 
54            tiles.push(default);
55            Ok(Vec2d { tiles, width })
56        }
57    }
58
59    /// Create a new `Vec2d` from an existing `Vec`.
60    /// Moves the original vec into a `Vec2d` without copying/cloning.
61    /// # Examples
62    /// ```
63    /// let vec = vec!['a','b','c','d'];
64    /// let board = board::Vec2d::new_from_vec(vec, 2).unwrap();
65    /// assert_eq!(board[(1,0)], 'b');
66    /// let vec = vec!['a','b','c','d'];
67    /// let board = board::Vec2d::new_from_vec(vec, 3);
68    /// assert!(board.is_err());
69    /// ```
70    pub fn new_from_vec(input: Vec<T>, width: usize) -> Result<Vec2d<T>, Vec2dError> {
71        if input.len() == 0 || width == 0 {
72            Err(Vec2dError::WidthOrInputLenIs0{ input_len: input.len(), width })
73        } else if input.len() % width != 0 {
74            Err(Vec2dError::InputNotDivisibleByWidth{ input_len: input.len(), width })
75        } else {
76            Ok( Vec2d { tiles: input, width } )
77        }
78    }
79    
80    /// Apply a function to each tile in `Vec2d`
81    /// # Examples
82    /// ```
83    /// let mut board = board::Vec2d::new('a', 2, 3).unwrap();
84    /// board.for_each_tile(|tile| *tile = 'b' );
85    /// assert_eq!(board.tiles(), &vec!['b','b','b','b','b','b']);
86    /// ```
87    pub fn for_each_tile<F: FnMut(&mut T)>(&mut self, fun: F) {
88        self.tiles.iter_mut().for_each(fun);
89    }
90
91    /// Get a `&Vec<Tile>` of the `Vec2d<Tile>`
92    pub fn tiles(&self) -> &Vec<T> {
93        &self.tiles
94    }
95
96    /// Get the height of the `Vec2d`
97    /// 
98    pub fn height(&self) -> usize {
99        self.tiles.len() / self.width()
100    }
101
102    /// Get the width of the `Vec2d`
103    /// 
104    pub fn width(&self) -> usize {
105        self.width
106    }
107
108    /// Get an `Option<&Tile>` at `(x, y)`
109    /// # Examples
110    /// ```
111    /// let mut board = board::Vec2d::new('a', 2, 3).unwrap();
112    /// assert_eq!(board.get(0, 0), Some(&'a'));
113    /// assert_eq!(board.get(1, 2), Some(&'a'));
114    /// assert_eq!(board.get(2, 2), None);
115    /// ```
116    pub fn get(&self, x: usize, y: usize) -> Option<&T> {
117        if x >= self.width { return None }
118        self.tiles.get(y * self.width + x)
119    }
120
121    /// Get an `Option<&mut Tile>` at `(x, y)`
122    /// # Examples
123    /// ```
124    /// let mut board = board::Vec2d::new('a', 2, 3).unwrap();
125    /// assert_eq!(board.get_mut(0, 0), Some(&mut 'a'));
126    /// assert_eq!(board.get_mut(1, 2), Some(&mut 'a'));
127    /// assert_eq!(board.get_mut(2, 2), None);
128    /// ```
129    pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
130        if x >= self.width { return None }
131        self.tiles.get_mut(y * self.width + x)
132    }
133
134    pub fn get_row(&self, y: usize) -> Option<&[T]> {
135        if y >= self.tiles.len() / self.width { return None }
136        Some(&self.tiles[y * self.width .. (y+1) * self.width])
137    }
138
139    pub fn get_row_mut(&mut self, y: usize) -> Option<&mut [T]> {
140        if y >= self.tiles.len() / self.width { return None }
141        Some(&mut self.tiles[y * self.width .. (y+1) * self.width])
142    }
143
144    /// Get an iterator over all `(x, y)` values: `Iterator<Item = (usize, Iterator<Item = usize>)>`
145    /// # Examples
146    /// ```
147    /// let board = board::Vec2d::new('a', 2, 3).unwrap();
148    /// for (x, row) in board.iter_xy() {
149    ///     for y in row {
150    ///         assert_eq!(board[(x, y)], 'a')
151    ///     }
152    /// }
153    /// ```
154    pub fn iter_xy(&self) -> impl Iterator<Item = (usize, impl Iterator<Item = usize>)> {
155        let width = self.width;
156        let height = self.height();
157        (0..width).map(move |i|(i, 0..height))
158    }
159
160    pub fn iter_rows(&self) -> impl Iterator<Item = &[T]> {
161        self.tiles
162            .rchunks(self.width)
163            .into_iter()
164    }
165
166    pub fn iter_rows_mut(&mut self) -> impl Iterator<Item = &mut [T]> {
167        self.tiles
168            .rchunks_mut(self.width)
169            .into_iter()
170    }
171
172    /// Iterate over: `((x, y), &Tile)`
173    /// # Examples
174    /// ```
175    /// let board = board::Vec2d::new(&'a', 2, 2).unwrap();
176    /// assert!(
177    ///     board.clone().iter_with_pos()
178    ///     .all(|((x, y), tile)| board[(x, y)] == *tile )
179    /// );
180    /// ```
181    pub fn iter_with_pos<'a>(&'a self) -> impl Iterator<Item = (Pos, &T)> {
182        let width = self.width;
183        self.tiles.iter().enumerate().map(move |(nr, tile)| {
184            let x = nr % width;
185            let y = nr / width;
186            ((x, y), tile)
187        })
188    }
189
190    /// Iterate over: `((x, y), &mut Tile)`
191    /// # Examples
192    /// ```
193    /// let board = board::Vec2d::new(&'a', 2, 2).unwrap();
194    /// assert!(
195    ///     board.clone().iter_with_pos()
196    ///     .all(|((x, y), tile)| board[(x, y)] == *tile )
197    /// );
198    /// ```
199    pub fn iter_with_pos_mut<'a>(&'a mut self) -> impl Iterator<Item = (Pos, &'a mut T)> {
200        let width = self.width;
201        self.tiles.iter_mut().enumerate().map(move |(nr, tile)| {
202            let x = nr % width;
203            let y = nr / width;    
204            ((x, y), tile)
205        })
206    }
207
208    /// Consumes self to return the original `Vec`
209    /// # Examples
210    /// ```
211    /// let vec = vec!['a','b','c','d'];
212    /// let board = board::Vec2d::new_from_vec(vec.clone(), 2).unwrap();
213    /// let new_vec = board.to_vec();
214    /// assert_eq!(vec, new_vec);
215    /// ```
216    pub fn to_vec(self) -> Vec<T> {
217        self.tiles
218    }
219}
220
221#[cfg(test)]
222mod tests {
223    use super::*;
224
225    #[test]
226    fn test_new() {
227        let board = Vec2d::new('a', 2, 2).unwrap();
228        assert_eq!(board,
229            Vec2d{
230                tiles: vec!['a', 'a', 'a', 'a'],
231                width: 2
232            }
233        );
234        let board = Vec2d::new(&'a', 0, 2);
235        assert!(board.is_err())
236    }
237
238    #[test]
239    fn test_get() {
240        let board = Vec2d::new('a', 2, 3).unwrap();
241        assert_eq!(board.get(1, 1), Some(&'a'));
242        assert_eq!(board.get(0, 0), Some(&'a'));
243        assert_eq!(board.get(1, 2), Some(&'a'));
244        assert_eq!(board.get(2, 2), None);
245        assert_eq!(board.get(1, 3), None);
246    }
247
248    #[test]
249    fn test_get_mut() {
250        let mut board = Vec2d::new('a', 2, 3).unwrap();
251        assert_eq!(board.get_mut(1, 1), Some(&mut 'a'));
252        assert_eq!(board.get_mut(0, 0), Some(&mut 'a'));
253        assert_eq!(board.get_mut(1, 2), Some(&mut 'a'));
254        assert_eq!(board.get_mut(2, 2), None);
255        assert_eq!(board.get_mut(1, 3), None);
256    }
257
258}