Skip to main content

hexga_math/geometry/grid/
iter_mut.rs

1use super::*;
2
3pub struct GridViewIterMut<'a, G, T, Idx, const N: usize>
4where
5    G: IGrid<T, Idx, N>,
6    Idx: Integer,
7    T: 'a,
8{
9    grid: &'a mut G,
10    rect: RectangleIter<Idx, N>,
11    phantom: std::marker::PhantomData<T>,
12}
13
14impl<'a, G, T, Idx, const N: usize> GridViewIterMut<'a, G, T, Idx, N>
15where
16    G: IGrid<T, Idx, N>,
17    Idx: Integer,
18    T: 'a,
19{
20    pub fn new(grid: &'a mut G) -> Self
21    {
22        let rect = grid.rect().iter_index();
23        Self {
24            grid,
25            rect: rect,
26            phantom: std::marker::PhantomData,
27        }
28    }
29
30    pub fn from_rect(grid: &'a mut G, rect: Rectangle<Idx, N>) -> Option<Self>
31    {
32        if !grid.rect().is_rect_inside(rect)
33        {
34            return None;
35        }
36        else
37        {
38            Some(unsafe { Self::from_rect_unchecked(grid, rect) })
39        }
40    }
41
42    pub unsafe fn from_rect_unchecked(grid: &'a mut G, rect: Rectangle<Idx, N>) -> Self
43    {
44        Self {
45            grid,
46            rect: rect.iter_index(),
47            phantom: std::marker::PhantomData,
48        }
49    }
50
51    pub fn from_rect_intersect(grid: &'a mut G, rect: Rectangle<Idx, N>) -> Self
52    {
53        let rect = grid.rect().intersect_or_empty(rect).iter_index();
54        Self {
55            grid,
56            rect,
57            phantom: std::marker::PhantomData,
58        }
59    }
60}
61
62impl<'a, G, T, Idx, const N: usize> Iterator for GridViewIterMut<'a, G, T, Idx, N>
63where
64    G: IGrid<T, Idx, N>,
65    Idx: Integer,
66{
67    type Item = (Vector<Idx, N>, &'a mut T);
68
69    fn next(&mut self) -> Option<Self::Item>
70    {
71        let idx = self.rect.next()?;
72        // # Safety
73        // Each index are different
74        Some((idx, unsafe {
75            (&mut *(&mut *self.grid as *mut G)).get_unchecked_mut(idx)
76        }))
77    }
78
79    fn size_hint(&self) -> (usize, Option<usize>) { self.rect.size_hint() }
80}
81impl<'a, G, T, Idx, const N: usize> std::iter::FusedIterator for GridViewIterMut<'a, G, T, Idx, N>
82where
83    G: IGrid<T, Idx, N>,
84    Idx: Integer,
85    RectangleIter<Idx, N>: std::iter::FusedIterator,
86{
87}
88impl<'a, G, T, Idx, const N: usize> std::iter::ExactSizeIterator
89    for GridViewIterMut<'a, G, T, Idx, N>
90where
91    G: IGrid<T, Idx, N>,
92    Idx: Integer,
93    RectangleIter<Idx, N>: std::iter::ExactSizeIterator,
94{
95}
96
97impl<'a, G, T, Idx, const N: usize> MapIntern for GridViewMut<'a, G, T, Idx, N>
98where
99    G: IGrid<T, Idx, N>,
100    Idx: Integer,
101{
102    type Item = T;
103
104    fn map_intern<F>(mut self, mut f: F) -> Self
105    where
106        F: FnMut(Self::Item) -> Self::Item,
107    {
108        self.iter_mut().for_each(|(_, v)| {
109            unsafe {
110                // Temporary moving the reference
111                let old = std::ptr::read(v);
112                let new = f(old);
113                std::ptr::write(v, new);
114            }
115        });
116        self
117    }
118}
119
120impl<'a, G, T, Idx, const N: usize> MapInternWith for GridViewMut<'a, G, T, Idx, N>
121where
122    G: IGrid<T, Idx, N>,
123    Idx: Integer,
124    T: Clone,
125{
126    fn map_with_intern<F>(mut self, mut other: Self, mut f: F) -> Self
127    where
128        F: FnMut(Self::Item, Self::Item) -> Self::Item,
129    {
130        assert_eq!(self.size(), other.size(), "size mismatch");
131        self.iter_mut()
132            .zip(other.iter_mut())
133            .for_each(|((_, a), (_, b))| {
134                unsafe {
135                    // Temporary moving the reference
136                    let old = std::ptr::read(a);
137                    let new = f(old, b.clone());
138                    std::ptr::write(a, new);
139                }
140            });
141        self
142    }
143}