griddy/
lib.rs

1use std::{
2    iter::StepBy,
3    slice::{Iter, IterMut},
4};
5
6#[derive(Eq, PartialEq, Clone, Debug)]
7pub struct Grid<T> {
8    width: usize,
9    height: usize,
10    data: Vec<T>,
11}
12
13impl<T> Grid<T> {
14    pub fn new(width: usize, height: usize) -> Self
15    where
16        T: Default,
17    {
18        let mut data = Vec::with_capacity(width * height);
19        data.resize_with(width * height, T::default);
20
21        Self {
22            width,
23            height,
24            data,
25        }
26    }
27
28    pub fn init(width: usize, height: usize, value: T) -> Self
29    where
30        T: Clone,
31    {
32        Self {
33            width,
34            height,
35            data: vec![value; width * height],
36        }
37    }
38
39    pub fn from_vec(vec: Vec<T>, width: usize) -> Self {
40        assert_eq!(vec.len() % width, 0);
41
42        Self {
43            width,
44            height: vec.len() / width,
45            data: vec,
46        }
47    }
48
49    pub unsafe fn get_unchecked(&self, x: usize, y: usize) -> &T {
50        self.data.get_unchecked(x + y * self.width)
51    }
52
53    pub unsafe fn get_unchecked_mut(&mut self, x: usize, y: usize) -> &mut T {
54        self.data.get_unchecked_mut(x + y * self.width)
55    }
56
57    pub fn get(&self, x: usize, y: usize) -> Option<&T> {
58        self.data.get(x + y * self.width)
59    }
60
61    pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
62        self.data.get_mut(x + y * self.width)
63    }
64
65    pub fn size(&self) -> (usize, usize) {
66        (self.width, self.height)
67    }
68
69    pub fn width(&self) -> usize {
70        self.width
71    }
72
73    pub fn height(&self) -> usize {
74        self.height
75    }
76
77    pub fn rows(&self) -> usize {
78        self.height
79    }
80
81    pub fn cols(&self) -> usize {
82        self.width
83    }
84
85    pub fn is_empty(&self) -> bool {
86        self.data.is_empty()
87    }
88
89    pub fn clear(&mut self) {
90        self.width = 0;
91        self.height = 0;
92        self.data.clear();
93    }
94
95    pub fn iter(&self) -> Iter<T> {
96        self.data.iter()
97    }
98
99    pub fn iter_mut(&mut self) -> IterMut<T> {
100        self.data.iter_mut()
101    }
102
103    pub fn iter_col(&self, col: usize) -> StepBy<Iter<T>> {
104        self.data[col..].iter().step_by(self.width)
105    }
106
107    pub fn iter_col_mut(&mut self, col: usize) -> StepBy<IterMut<T>> {
108        self.data[col..].iter_mut().step_by(self.width)
109    }
110
111    pub fn iter_row(&self, row: usize) -> Iter<T> {
112        let start = row * self.width;
113        self.data[start..(start + self.width)].iter()
114    }
115
116    pub fn iter_row_mut(&mut self, row: usize) -> IterMut<T> {
117        let start = row * self.width;
118        self.data[start..(start + self.width)].iter_mut()
119    }
120
121    pub fn flatten(&self) -> &Vec<T> {
122        &self.data
123    }
124
125    pub fn into_vec(self) -> Vec<T> {
126        self.data
127    }
128
129    pub fn fill(&mut self, value: T)
130    where
131        T: Clone,
132    {
133        self.data.fill(value);
134    }
135
136    pub fn fill_with(&mut self, func: impl FnMut() -> T) {
137        self.data.fill_with(func);
138    }
139
140    pub fn map<U>(self, func: impl FnMut(T) -> U) -> Grid<U> {
141        Grid {
142            width: self.width,
143            height: self.height,
144            data: self.data.into_iter().map(func).collect(),
145        }
146    }
147}
148
149impl<T> Grid<Option<T>> {
150    pub fn or(self, other: Self) -> Self {
151        assert_eq!(self.width, other.width);
152        assert_eq!(self.height, other.height);
153
154        Self {
155            width: self.width,
156            height: self.height,
157            data: self
158                .into_vec()
159                .into_iter()
160                .zip(other.into_vec().into_iter())
161                .map(|(a, b)| a.or(b))
162                .collect(),
163        }
164    }
165
166    pub fn and_then<U>(self, f: impl FnOnce(T) -> Option<U> + Clone) -> Grid<Option<U>> {
167        Grid {
168            width: self.width,
169            height: self.height,
170            data: self
171                .into_vec()
172                .into_iter()
173                .map(|a| a.and_then(f.clone()))
174                .collect(),
175        }
176    }
177
178    pub fn option_map<U>(self, f: impl FnOnce(T) -> U + Clone) -> Grid<Option<U>> {
179        Grid {
180            width: self.width,
181            height: self.height,
182            data: self
183                .into_vec()
184                .into_iter()
185                .map(|a| a.map(f.clone()))
186                .collect(),
187        }
188    }
189}
190
191#[cfg(test)]
192mod tests {
193    use super::*;
194
195    #[test]
196    fn and_then_works() {
197        let g = Grid::from_vec(vec![None, Some(2), Some(3), Some(4)], 2);
198        let r = g.and_then(|x| Some(x * x));
199
200        assert_eq!(r, Grid::from_vec(vec![None, Some(4), Some(9), Some(16)], 2));
201    }
202}