static_array2d/
lib.rs

1//! static_array2d provides an interface for 2d slices.
2//!
3//! It differs from `array2d` and `array2ds` by using the stack
4//! instead of the heap through rust's constant generics.
5
6#![no_std]
7/// A statically sized 2-dimensional array
8#[derive(Clone)]
9pub struct Grid<const W: usize, const H: usize, T> {
10    pub data: [[T; W]; H],
11}
12
13/// A statically sized 2-dimensional array with equal width and height
14pub type SquareGrid<const W: usize, T> = Grid<W, W, T>;
15
16impl<const W: usize, const H: usize, T: Default + Copy> Default for Grid<W, H, T> {
17    fn default() -> Self {
18        Self {
19            data: [[T::default(); W]; H],
20        }
21    }
22}
23
24impl<const W: usize, const H: usize, T> From<[[T; W]; H]> for Grid<W, H, T> {
25    fn from(value: [[T; W]; H]) -> Self {
26        Self { data: value }
27    }
28}
29
30impl<const W: usize, const H: usize, T> Grid<W, H, T> {
31    pub fn iter(&self) -> impl Iterator<Item = (usize, usize, &T)> {
32        self.data
33            .iter()
34            .enumerate()
35            .flat_map(|(y, row)| row.iter().enumerate().map(move |(x, item)| (x, y, item)))
36    }
37
38    pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
39        self.data.iter_mut().enumerate().flat_map(|(y, row)| {
40            row.iter_mut()
41                .enumerate()
42                .map(move |(x, item)| (x, y, item))
43        })
44    }
45
46    #[must_use]
47    pub fn get(&self, x: usize, y: usize) -> Option<&T> {
48        self.data.get(y)?.get(x)
49    }
50
51    #[must_use]
52    pub fn get_mut(&mut self, x: usize, y: usize) -> Option<&mut T> {
53        self.data.get_mut(y)?.get_mut(x)
54    }
55
56    /// # Safety
57    ///
58    /// Calling this method with an out-of-bounds index is *[undefined behavior]*
59    /// even if the resulting reference is not used.
60    ///
61    /// [`get`]: slice::get
62    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
63    #[must_use]
64    pub unsafe fn get_unchecked(&self, x: usize, y: usize) -> &T {
65        self.data.get_unchecked(y).get_unchecked(x)
66    }
67
68    /// # Safety
69    ///
70    /// Calling this method with an out-of-bounds index is *[undefined behavior]*
71    /// even if the resulting reference is not used.
72    ///
73    /// [`get`]: slice::get
74    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
75    #[must_use]
76    pub unsafe fn get_unchecked_mut(&mut self, x: usize, y: usize) -> &mut T {
77        self.data.get_unchecked_mut(y).get_unchecked_mut(x)
78    }
79}