plane_2d/
lib.rs

1//! # Two Dimensional Plane
2//! Models continuous, infinitely big (within integer and storage limits) 2D data structure.
3//! The purpose of this crate is to provide a data structure that is faster
4//! than a `HashMap<(i32, i32), T>` in specific scenarios and provides better API
5//! for working with 2D plane.
6//!
7//! This crate will always provide a 2D data structure.
8//! The `Plane<T>` type is a container for all kinds of data that implement `Default` trait.
9//! You can use `Option<T>` to store optionally initialized data.
10//!
11//! No other dependencies except for the std lib are used,
12//! besides dependencies hidden behind feature flags.
13//!
14//! # Memory layout
15//! Uses almost exact copy of [grid](https://docs.rs/grid/0.14.0/grid/) crate to use `Grid<T>` type.
16//! Stores a dense chunk of the plane in `Vec<T>` (`Grid<T>`, provided by copy of the `grid` crate)
17//! and `HashMap<(i32, i32), T>` to store cells that are out of bounds of the `Grid<T>`.
18//! Unlike `HashMap<(i32, i32), T>`, two allocations are being done.
19
20#[cfg(all(not(feature = "i32"), not(feature = "i64")))]
21compile_error!("either feature \"i32\" or \"i64\" must be enabled");
22
23#[cfg(all(feature = "i32", feature = "i64"))]
24compile_error!("feature \"i32\" and feature \"i64\" cannot be enabled at the same time");
25
26#[warn(missing_docs)]
27pub mod grid;
28pub mod immutable;
29
30#[cfg(feature = "bevy_reflect")]
31use bevy_reflect::Reflect;
32
33#[cfg(feature = "serde")]
34use serde::{
35    de::{self, Deserialize, Deserializer, MapAccess, Visitor},
36    ser::{Serialize, SerializeStruct, Serializer},
37};
38
39pub use grid::Grid;
40pub use immutable::Immutable;
41use std::hash::BuildHasher;
42use std::ops::{Index, IndexMut};
43
44#[cfg(feature = "i32")]
45type Scalar = i32;
46#[cfg(feature = "i64")]
47type Scalar = i64;
48
49#[cfg(feature = "hashbrown")]
50use hashbrown::HashMap;
51#[cfg(not(feature = "hashbrown"))]
52use std::collections::HashMap;
53
54/// Default type used
55#[cfg(feature = "hashbrown")]
56pub type DefaultHashBuilder = hashbrown::hash_map::DefaultHashBuilder;
57/// Default hash builder used for the inner `HashMap`.
58#[cfg(not(feature = "hashbrown"))]
59pub type DefaultHashBuilder = std::hash::RandomState;
60
61/// Stores elements of a certain type in an integer grid, even in negative direction.
62///
63/// Uses [`Grid<T>`] type from a [grid](https://docs.rs/grid/0.14.0/grid/) crate
64/// and a
65#[cfg_attr(feature = "i32", doc = "`HashMap<(i32, i32), T>`")]
66#[cfg_attr(feature = "i64", doc = "`HashMap<(i64, i64), T>`")]
67///  to store data on the heap.
68///
69/// Data in [`Grid<T>`] is stored inside one dimensional array using [`Vec<T>`].
70/// This is cash efficient, so it is recommended to store there dense regions of data,
71/// but it is memory inefficient if you don't need much space - it keeps memory for `rows * cols` cells,
72/// so if there are only two cells in use - one is placed on coordinate `(0,0)` and other is on `(100,100)`,
73/// there is space reserved for at least `10000` elements.
74/// Using [`HashMap`] solves that problem - it stores data outside the grid bounds.
75///
76/// Note that if the size of the Grid is zero, this data structure is identical to the
77#[cfg_attr(feature = "i32", doc = "`HashMap<(i32, i32), T>`,")]
78#[cfg_attr(feature = "i64", doc = "`HashMap<(i64, i64), T>`,")]
79/// and it'll be more effective to just use
80#[cfg_attr(feature = "i32", doc = "`HashMap<(i32, i32), T>`,")]
81#[cfg_attr(feature = "i64", doc = "`HashMap<(i64, i64), T>`")]
82/// since in this case you'll get rid of any unnecessary checks.
83///
84/// `T` should implement [`Default`] trait, because the plain is infinitely large,
85/// and you can access any point of it at any time.
86/// Whenever uninitialized cell is accessed, default value is returned.
87/// For optionally initialized data use [`Option<T>`].
88#[derive(Debug, Clone)]
89#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
90pub struct Plane<T: Default, S: BuildHasher = DefaultHashBuilder> {
91    grid: Grid<T>,
92    // grid(x, y) = world(x, y) + offset
93    offset: (Scalar, Scalar),
94    map: HashMap<(Scalar, Scalar), T, S>,
95
96    /// Is referenced by [`get`] function, because it requires immutable reference to `self`,
97    /// and in case of the value being uninitialized, function should return reference to something with the lifetime of `self`.
98    default_value: Immutable<T>,
99}
100
101#[cfg(feature = "serde")]
102impl<'de, T: Default + Deserialize<'de>, H: Default + BuildHasher> Deserialize<'de>
103    for Plane<T, H>
104{
105    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
106    where
107        D: Deserializer<'de>,
108    {
109        use std::marker::PhantomData;
110        #[derive(serde::Deserialize)]
111        #[serde(field_identifier, rename_all = "lowercase")]
112        enum Field {
113            Offset,
114            Size,
115            Grid,
116            Map,
117        }
118
119        struct PlaneVisitor<T, H> {
120            _p: PhantomData<(T, H)>,
121        }
122
123        impl<'de, T: Default + Deserialize<'de>, H: Default + BuildHasher> Visitor<'de>
124            for PlaneVisitor<T, H>
125        {
126            type Value = Plane<T, H>;
127
128            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
129                formatter.write_str("struct Grid")
130            }
131
132            fn visit_map<V>(self, mut accsess: V) -> Result<Plane<T, H>, V::Error>
133            where
134                V: MapAccess<'de>,
135            {
136                let mut offset: Option<(Scalar, Scalar)> = None;
137                let mut size: Option<(Scalar, Scalar)> = None;
138                let mut grid = None;
139                let mut map = None;
140                while let Some(key) = accsess.next_key()? {
141                    match key {
142                        Field::Offset => {
143                            if offset.is_some() {
144                                return Err(de::Error::duplicate_field("offset"));
145                            }
146                            offset = Some(accsess.next_value()?);
147                        }
148                        Field::Size => {
149                            if size.is_some() {
150                                return Err(de::Error::duplicate_field("size"));
151                            }
152                            size = Some(accsess.next_value()?);
153                        }
154                        Field::Grid => {
155                            if grid.is_some() {
156                                return Err(de::Error::duplicate_field("grid"));
157                            }
158                            grid = Some(accsess.next_value()?);
159                        }
160                        Field::Map => {
161                            if map.is_some() {
162                                return Err(de::Error::duplicate_field("map"));
163                            }
164                            map = Some(accsess.next_value()?);
165                        }
166                    }
167                }
168
169                let (x_min, y_min) = offset.ok_or_else(|| de::Error::missing_field("offset"))?;
170                let map = map.ok_or_else(|| de::Error::missing_field("map"))?;
171
172                if let Some(grid) = grid {
173                    Ok(Plane::from_grid_and_hash_map(grid, map, -x_min, -y_min))
174                } else if let Some((x_size, y_size)) = size {
175                    Ok(Plane::from_hash_map(
176                        map,
177                        -x_min,
178                        -y_min,
179                        x_size - x_min,
180                        y_size - y_min,
181                    ))
182                } else {
183                    Err(de::Error::missing_field("grid or size"))
184                }
185            }
186        }
187
188        const FIELDS: &'static [&'static str] = &["cols", "data", "order"];
189        deserializer.deserialize_struct("Grid", FIELDS, PlaneVisitor { _p: PhantomData })
190    }
191}
192
193#[cfg(feature = "serde")]
194impl<T: Default + Serialize, H: BuildHasher> Serialize for Plane<T, H> {
195    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
196    where
197        S: Serializer,
198    {
199        // 3 is the number of fields in the struct.
200        let mut state = serializer.serialize_struct("Plane", 3)?;
201        state.serialize_field("offset", &self.offset)?;
202        state.serialize_field("grid", &self.grid)?;
203        state.serialize_field("map", &self.map)?;
204        state.end()
205    }
206}
207
208#[inline]
209fn rows_cols(x_min: Scalar, y_min: Scalar, x_max: Scalar, y_max: Scalar) -> (usize, usize) {
210    ((x_max - x_min + 1) as usize, (y_max - y_min + 1) as usize)
211}
212
213impl<T: Default, S: Default + BuildHasher> Default for Plane<T, S> {
214    /// Creates new `Plane<T>` with internal `Grid<T>` of size 0.
215    /// Basically identical to
216    #[cfg_attr(feature = "i32", doc = "`HashMap<(i32, i32), T>`,")]
217    #[cfg_attr(feature = "i64", doc = "`HashMap<(i64, i64), T>`,")]
218    /// better use it instead, because Plane will be doing unnecessary comparisons
219    fn default() -> Self {
220        Self {
221            grid: Grid::new(0, 0),
222            offset: (0, 0),
223            map: HashMap::default(),
224            default_value: Immutable::default(),
225        }
226    }
227}
228
229impl<T: Default> Plane<T, DefaultHashBuilder> {
230    #[inline]
231    pub fn new(x_min: Scalar, y_min: Scalar, x_max: Scalar, y_max: Scalar) -> Self {
232        Self::default_hasher(x_min, y_min, x_max, y_max)
233    }
234}
235
236impl<T: Default, S: Default + BuildHasher> Plane<T, S> {
237    #[inline]
238    pub fn default_hasher(x_min: Scalar, y_min: Scalar, x_max: Scalar, y_max: Scalar) -> Self {
239        Self::with_hasher(x_min, y_min, x_max, y_max, Default::default())
240    }
241    #[inline]
242    pub fn from_grid(grid: Grid<T>, x_min: Scalar, y_min: Scalar) -> Self {
243        Self::from_grid_and_hash_map(grid, HashMap::default(), x_min, y_min)
244    }
245}
246
247impl<T: Default, S: BuildHasher> Plane<T, S> {
248    /// Returns [`Plane`] whose array-based grid is within specified bounds
249    pub fn with_hasher(
250        x_min: Scalar,
251        y_min: Scalar,
252        x_max: Scalar,
253        y_max: Scalar,
254        hasher: S,
255    ) -> Self {
256        let (rows, cols): (usize, usize) = rows_cols(x_min, y_min, x_max, y_max);
257        Self::from_grid_and_hash_map(
258            Grid::new(rows, cols),
259            HashMap::with_hasher(hasher),
260            x_min,
261            y_min,
262        )
263    }
264
265    #[inline]
266    pub fn inner_grid(&self) -> &Grid<T> {
267        &self.grid
268    }
269    #[inline]
270    pub fn inner_grid_mut(&mut self) -> &mut Grid<T> {
271        &mut self.grid
272    }
273    #[inline]
274    pub fn inner_hash_map(&self) -> &HashMap<(Scalar, Scalar), T, S> {
275        &self.map
276    }
277    #[inline]
278    pub fn inner_hash_map_mut(&mut self) -> &mut HashMap<(Scalar, Scalar), T, S> {
279        &mut self.map
280    }
281
282    pub fn from_hash_map(
283        map: HashMap<(Scalar, Scalar), T, S>,
284        x_min: Scalar,
285        y_min: Scalar,
286        x_max: Scalar,
287        y_max: Scalar,
288    ) -> Self {
289        let mut plane = Self::from_grid_and_hash_map(Grid::new(0, 0), map, 0, 0);
290        plane.relocate_grid(x_min, x_max, y_min, y_max);
291        plane
292    }
293
294    #[inline]
295    pub fn from_grid_with_hasher(grid: Grid<T>, x_min: Scalar, y_min: Scalar, hasher: S) -> Self {
296        Self::from_grid_and_hash_map(grid, HashMap::with_hasher(hasher), x_min, y_min)
297    }
298
299    /// Creates instance of [`Plane<T>`] from [`Grid<T>`] and [`HashMap<(Scalar, Scalar), T>`]
300    /// # Note
301    /// Doesn't remove items from `map` if they are initialized and overlapping with `grid`. Their existence will be ignored.
302    /// When you are calling [`Plane::inner_hash_map`], [`Plane::inner_hash_map_mut`], [`Plane::iter_all`], [`Plane::iter_all_mut`] or [`Plane::into_iter_all`]
303    /// those values may or may not still exist in the hash map.
304    pub fn from_grid_and_hash_map(
305        grid: Grid<T>,
306        map: HashMap<(Scalar, Scalar), T, S>,
307        x_min: Scalar,
308        y_min: Scalar,
309    ) -> Self {
310        Self {
311            grid,
312            offset: (-x_min, -y_min),
313            map,
314            default_value: Immutable::default(),
315        }
316    }
317
318    pub fn into_hash_map(self) -> HashMap<(Scalar, Scalar), T, S> {
319        let mut map = self.map;
320
321        for ((x, y), val) in self.grid.into_iter_indexed() {
322            let vec = (x as Scalar - self.offset.0, y as Scalar - self.offset.1);
323            map.insert(vec, val);
324        }
325
326        map
327    }
328
329    pub fn global_coordinates_from_grid(&self, x: usize, y: usize) -> (Scalar, Scalar) {
330        let x = x as Scalar - self.offset.0;
331        let y = y as Scalar - self.offset.1;
332        (x, y)
333    }
334
335    pub fn grid_coordinates_from_global(&self, x: Scalar, y: Scalar) -> Option<(usize, usize)> {
336        let x = x + self.offset.0;
337        let y = y + self.offset.1;
338
339        if 0 <= x && x < self.grid.rows() as Scalar && 0 <= y && y < self.grid.cols() as Scalar {
340            Some((x as usize, y as usize))
341        } else {
342            None
343        }
344    }
345
346    /// Returns a reference to an element that should be contained in `Grid<T>` container without performing bound checks.
347    /// Generally not recommended, use with caution!
348    ///
349    /// # Safety
350    ///
351    /// Calling this method with an out-of-bounds index is undefined behavior even if the resulting reference is not used.
352    pub unsafe fn get_unchecked(&self, x: Scalar, y: Scalar) -> &T {
353        let x = (x + self.offset.0) as usize;
354        let y = (y + self.offset.1) as usize;
355
356        self.grid.get_unchecked(x, y)
357    }
358
359    /// Returns a mutable reference to an element that should be contained in `Grid<T>` container without performing bound checks.
360    /// Generally not recommended, use with caution!
361    ///
362    /// # Safety
363    ///
364    /// Calling this method with an out-of-bounds index is undefined behavior even if the resulting reference is not used.
365    pub unsafe fn get_unchecked_mut(&mut self, x: Scalar, y: Scalar) -> &mut T {
366        let x = (x + self.offset.0) as usize;
367        let y = (y + self.offset.1) as usize;
368
369        self.grid.get_unchecked_mut(x, y)
370    }
371
372    /// Access a certain element on the plane-2d.
373    /// Returns [`Default`] value if uninitialized element is being accessed.
374    pub fn get(&self, x: Scalar, y: Scalar) -> &T {
375        if let Some((x, y)) = self.grid_coordinates_from_global(x, y) {
376            // Safety: `grid_coordinates_from_global` is guaranteed to return Some
377            // whenever the coords are within the bounds of internal grid
378            unsafe { self.grid.get_unchecked(x, y) }
379        } else {
380            let val = self.map.get(&(x, y));
381
382            val.unwrap_or(&self.default_value)
383        }
384    }
385
386    /// Mutable access to a certain element on the plane-2d.
387    /// Returns [`Default`] value if uninitialized element is being accessed.
388    pub fn get_mut(&mut self, x: Scalar, y: Scalar) -> &mut T {
389        if let Some((x, y)) = self.grid_coordinates_from_global(x, y) {
390            // Safety: `grid_coordinates_from_global` is guaranteed to return Some
391            // whenever the coords are within the bounds of internal grid
392            unsafe { self.grid.get_unchecked_mut(x, y) }
393        } else {
394            self.map.entry((x, y)).or_default()
395        }
396    }
397
398    /// Insert element at the coordinate.
399    /// Returns [`Default`] value if uninitialized element is being accessed.
400    pub fn insert(&mut self, value: T, x: Scalar, y: Scalar) -> T {
401        if let Some((x, y)) = self.grid_coordinates_from_global(x, y) {
402            // Safety: safe since `within_grid_bounds` is guaranteed to return true
403            // whenever the coords are within the bounds of internal grid
404            std::mem::replace(unsafe { self.grid.get_unchecked_mut(x, y) }, value)
405        } else {
406            self.map.insert((x, y), value).unwrap_or_default()
407        }
408    }
409
410    /// Changes position of  the base grid structure.
411    /// Iterates over all elements in previous grid and all elements in new grid
412    pub fn relocate_grid(&mut self, x_min: Scalar, y_min: Scalar, x_max: Scalar, y_max: Scalar) {
413        let (rows, cols) = rows_cols(x_min, y_min, x_max, y_max);
414        let mut new_grid = Grid::new(rows, cols);
415
416        let old_grid = std::mem::replace(&mut self.grid, Grid::new(0, 0));
417
418        for ((x, y), val) in old_grid.into_iter_indexed() {
419            let vec = self.global_coordinates_from_grid(x, y);
420            self.map.insert(vec, val);
421        }
422
423        for ((x, y), val) in new_grid.indexed_iter_mut() {
424            let vec = self.global_coordinates_from_grid(x, y);
425            *val = self.map.remove(&vec).unwrap_or_default();
426        }
427
428        self.grid = new_grid;
429        self.offset = (-x_min, -y_min);
430    }
431
432    /// Iterates over all the items within the rectangle area inclusively.
433    /// Returns [`Default`] value if uninitialized element is being accessed.
434    /// Order of iteration is deterministic, but can change in future versions.
435    pub fn iter_rect(
436        &self,
437        x_min: Scalar,
438        y_min: Scalar,
439        x_max: Scalar,
440        y_max: Scalar,
441    ) -> impl Iterator<Item = ((Scalar, Scalar), &T)> {
442        (x_min..=x_max).flat_map(move |x| (y_min..=y_max).map(move |y| ((x, y), self.get(x, y))))
443    }
444
445    /// Mutably iterates over all the items within the rectangle area inclusively.
446    /// Returns [`Default`] value if uninitialized element is being accessed.
447    /// Order of iteration is deterministic, but can change in future versions .
448    pub fn foreach_rect_mut(
449        &mut self,
450        x_min: Scalar,
451        y_min: Scalar,
452        x_max: Scalar,
453        y_max: Scalar,
454        mut func: impl FnMut((Scalar, Scalar), &mut T),
455    ) {
456        for x in x_min..=x_max {
457            for y in y_min..=y_max {
458                func((x, y), self.get_mut(x, y))
459            }
460        }
461    }
462
463    /// Iterate over all the elements stored inside the grid and hashmap. May return value from HashMap even if it is overlapping with Grid   
464    pub fn iter_all(&self) -> impl Iterator<Item = ((Scalar, Scalar), &T)> {
465        self.grid
466            .indexed_iter()
467            .map(move |((x, y), elem)| {
468                (
469                    (x as Scalar - self.offset.0, y as Scalar - self.offset.1),
470                    elem,
471                )
472            })
473            .chain(self.map.iter().map(|(vec, elem)| (*vec, elem)))
474    }
475
476    /// Mutably iterate over all the elements stored inside the grid and hashmap. May return value from HashMap even if it is overlapping with Grid   
477    pub fn iter_all_mut(&mut self) -> impl Iterator<Item = ((Scalar, Scalar), &mut T)> {
478        let offset = self.offset;
479
480        self.grid
481            .indexed_iter_mut()
482            .map(move |((x, y), elem)| ((x as Scalar - offset.0, y as Scalar - offset.1), elem))
483            .chain(self.map.iter_mut().map(|(vec, elem)| (*vec, elem)))
484    }
485
486    /// Iterate over all the elements stored inside the grid and hashmap. May return value from HashMap even if it is overlapping with Grid   
487    pub fn into_iter_all(self) -> impl Iterator<Item = ((Scalar, Scalar), T)> {
488        self.grid
489            .into_iter_indexed()
490            .map(move |((x, y), elem)| {
491                (
492                    (x as Scalar - self.offset.0, y as Scalar - self.offset.1),
493                    elem,
494                )
495            })
496            .chain(self.map)
497    }
498}
499
500impl<T, S: BuildHasher> Plane<Option<T>, S> {
501    /// Iterate over all the initialized elements
502    pub fn iter(&self) -> impl Iterator<Item = ((Scalar, Scalar), &T)> {
503        self.grid
504            .indexed_iter()
505            .filter_map(move |((x, y), elem)| {
506                elem.as_ref().map(|el| {
507                    (
508                        (x as Scalar - self.offset.0, y as Scalar - self.offset.1),
509                        el,
510                    )
511                })
512            })
513            .chain(
514                self.map
515                    .iter()
516                    .filter_map(|(vec, elem)| elem.as_ref().map(|el| (*vec, el))),
517            )
518    }
519
520    /// Mutably iterate over all the initialized elements
521    pub fn iter_mut(&mut self) -> impl Iterator<Item = ((Scalar, Scalar), &mut T)> {
522        let offset = self.offset;
523
524        self.grid
525            .indexed_iter_mut()
526            .filter_map(move |((x, y), elem)| {
527                elem.as_mut()
528                    .map(|el| ((x as Scalar - offset.0, y as Scalar - offset.1), el))
529            })
530            .chain(
531                self.map
532                    .iter_mut()
533                    .filter_map(|(vec, elem)| elem.as_mut().map(|el| (*vec, el))),
534            )
535    }
536
537    /// Consume plane-2d to get all the initialized elements
538    pub fn into_iter(self) -> impl Iterator<Item = ((Scalar, Scalar), T)> {
539        self.grid
540            .into_iter_indexed()
541            .filter_map(move |((x, y), elem)| {
542                elem.map(|el| {
543                    (
544                        (x as Scalar - self.offset.0, y as Scalar - self.offset.1),
545                        el,
546                    )
547                })
548            })
549            .chain(
550                self.map
551                    .into_iter()
552                    .filter_map(|(vec, elem)| elem.map(|el| (vec, el))),
553            )
554    }
555}
556
557impl<T: Default, S: Default + BuildHasher> From<Grid<T>> for Plane<T, S> {
558    #[inline]
559    fn from(value: Grid<T>) -> Self {
560        Self::from_grid(value, 0, 0)
561    }
562}
563
564impl<T: Default, S: BuildHasher> From<HashMap<(Scalar, Scalar), T, S>> for Plane<T, S> {
565    #[inline]
566    fn from(value: HashMap<(Scalar, Scalar), T, S>) -> Self {
567        Self::from_hash_map(value, 0, 0, 0, 0)
568    }
569}
570
571impl<T: Default, S: BuildHasher> Index<(Scalar, Scalar)> for Plane<T, S> {
572    type Output = T;
573    #[inline]
574    fn index(&self, (x, y): (Scalar, Scalar)) -> &Self::Output {
575        self.get(x, y)
576    }
577}
578
579impl<T: Default, S: BuildHasher> IndexMut<(Scalar, Scalar)> for Plane<T, S> {
580    #[inline]
581    fn index_mut(&mut self, (x, y): (Scalar, Scalar)) -> &mut Self::Output {
582        self.get_mut(x, y)
583    }
584}
585
586#[cfg(test)]
587mod tests {
588    use super::grid::{grid, Grid};
589    use super::Plane;
590    #[cfg(feature = "hashbrown")]
591    use hashbrown::HashMap;
592    #[cfg(not(feature = "hashbrown"))]
593    use std::collections::HashMap;
594
595    #[test]
596    fn test_iter() {
597        let grid: Grid<Option<i32>> = grid![
598            [Some(1), Some(2)]
599            [Some(3), Some(4)]
600        ];
601        let mut hash_map = HashMap::new();
602        hash_map.insert((23, 40), Some(19));
603        hash_map.insert((40, 40), Some(13));
604        let plane: Plane<Option<i32>> = Plane::from_grid_and_hash_map(grid, hash_map, 2, 2);
605
606        let mut elements: Vec<_> = plane.iter().map(|(a, v)| (a, *v)).collect();
607        elements.sort_by(|(_, v1), (_, v2)| v1.cmp(v2));
608
609        assert_eq!(
610            elements,
611            vec![
612                ((2, 2), 1),
613                ((2, 3), 2),
614                ((3, 2), 3),
615                ((3, 3), 4),
616                ((40, 40), 13),
617                ((23, 40), 19),
618            ]
619        );
620    }
621
622    #[test]
623    fn test_iter_mut() {
624        let grid: Grid<Option<i32>> = grid![
625            [Some(1), Some(2)]
626            [Some(3), Some(4)]
627        ];
628        let mut hash_map = HashMap::new();
629        hash_map.insert((23, 40), Some(19));
630        hash_map.insert((40, 40), Some(13));
631
632        let mut plane: Plane<Option<i32>> = Plane::from_grid_and_hash_map(grid, hash_map, 2, 2);
633
634        for (_, elem) in plane.iter_mut() {
635            *elem += 1;
636        }
637
638        let mut elements: Vec<_> = plane.iter().map(|(a, v)| (a, *v)).collect();
639        elements.sort_by(|(_, v1), (_, v2)| v1.cmp(v2));
640
641        assert_eq!(
642            elements,
643            vec![
644                ((2, 2), 2),
645                ((2, 3), 3),
646                ((3, 2), 4),
647                ((3, 3), 5),
648                ((40, 40), 14),
649                ((23, 40), 20),
650            ]
651        );
652    }
653
654    #[test]
655    fn test_into_iter() {
656        let grid: Grid<Option<i32>> = grid![
657            [Some(1), Some(2)]
658            [Some(3), Some(4)]
659        ];
660        let mut hash_map = HashMap::new();
661        hash_map.insert((23, 40), Some(19));
662        hash_map.insert((40, 40), Some(13));
663        let plane: Plane<Option<i32>> = Plane::from_grid_and_hash_map(grid, hash_map, 2, 2);
664
665        let mut elements: Vec<_> = plane.into_iter().collect();
666        elements.sort_by(|(_, v1), (_, v2)| v1.cmp(v2));
667
668        assert_eq!(
669            elements,
670            vec![
671                ((2, 2), 1),
672                ((2, 3), 2),
673                ((3, 2), 3),
674                ((3, 3), 4),
675                ((40, 40), 13),
676                ((23, 40), 19),
677            ]
678        );
679    }
680
681    #[test]
682    fn test_default_initialization() {
683        let plane: Plane<Option<()>> = Plane::default();
684        let elements: Vec<_> = plane.into_iter().collect();
685
686        assert_eq!(elements.len(), 0);
687    }
688
689    #[test]
690    fn test_inserting_element() {
691        let mut plane = Plane::new(1, 1, 4, 4);
692
693        assert_eq!(*plane.get(1, 1), None);
694        assert_eq!(*plane.get(4, 4), None);
695        assert_eq!(*plane.get(1, 100), None);
696
697        assert_eq!(plane.insert(Some(5), 1, 1), None);
698        assert_eq!(*plane.get(1, 1), Some(5));
699
700        assert_eq!(plane.insert(Some(6), -1, -1), None);
701        assert_eq!(*plane.get(-1, -1), Some(6));
702
703        assert_eq!(plane.insert(Some(8), -1, -1), Some(6));
704        assert_eq!(*plane.get(-1, -1), Some(8));
705
706        assert_eq!(plane.insert(Some(7), 4, 4), None);
707        assert_eq!(*plane.get(4, 4), Some(7));
708
709        assert_eq!(plane.insert(Some(9), 4, 4), Some(7));
710        assert_eq!(*plane.get(4, 4), Some(9));
711    }
712
713    #[test]
714    fn test_get_element_mut() {
715        let mut plane = Plane::new(1, 1, 4, 4);
716        plane.insert(Some(8), 1, 1);
717        if let Some(elem) = plane.get_mut(1, 1) {
718            *elem = 10;
719        }
720        assert_eq!(*plane.get(1, 1), Some(10));
721    }
722
723    #[test]
724    fn test_iter_rect() {
725        let mut plane = Plane::new(1, 1, 4, 4);
726        plane.insert((1, 1), 1, 1);
727        plane.insert((2, 1), 2, 1);
728        plane.insert((3, 1), 3, 1);
729        plane.insert((4, 1), 4, 1);
730        plane.insert((5, 1), 5, 1);
731
732        plane.insert((1, 2), 1, 2);
733        plane.insert((2, 2), 2, 2);
734        plane.insert((3, 2), 3, 2);
735        plane.insert((4, 2), 4, 2);
736        plane.insert((5, 2), 5, 2);
737
738        plane.insert((1, 3), 1, 3);
739        plane.insert((2, 3), 2, 3);
740        plane.insert((3, 3), 3, 3);
741        plane.insert((4, 3), 4, 3);
742        plane.insert((5, 3), 5, 3);
743
744        plane.insert((1, 4), 1, 4);
745        plane.insert((2, 4), 2, 4);
746        plane.insert((3, 4), 3, 4);
747        plane.insert((4, 4), 4, 4);
748        plane.insert((5, 4), 5, 4);
749
750        plane.insert((1, 5), 1, 5);
751        plane.insert((2, 5), 2, 5);
752        plane.insert((3, 5), 3, 5);
753        plane.insert((4, 5), 4, 5);
754        plane.insert((5, 5), 5, 5);
755
756        let mut value: Vec<_> = plane.iter_rect(2, 2, 6, 5).map(|(a, v)| (a, *v)).collect();
757        value.sort_by(
758            |((x1, y1), _), ((x2, y2), _)| {
759                if x1 == x2 {
760                    y1.cmp(y2)
761                } else {
762                    x1.cmp(x2)
763                }
764            },
765        );
766
767        assert_eq!(
768            value,
769            vec![
770                ((2, 2), (2, 2)),
771                ((2, 3), (2, 3)),
772                ((2, 4), (2, 4)),
773                ((2, 5), (2, 5)),
774                ((3, 2), (3, 2)),
775                ((3, 3), (3, 3)),
776                ((3, 4), (3, 4)),
777                ((3, 5), (3, 5)),
778                ((4, 2), (4, 2)),
779                ((4, 3), (4, 3)),
780                ((4, 4), (4, 4)),
781                ((4, 5), (4, 5)),
782                ((5, 2), (5, 2)),
783                ((5, 3), (5, 3)),
784                ((5, 4), (5, 4)),
785                ((5, 5), (5, 5)),
786                ((6, 2), (0, 0)),
787                ((6, 3), (0, 0)),
788                ((6, 4), (0, 0)),
789                ((6, 5), (0, 0)),
790            ]
791        );
792    }
793
794    #[test]
795    fn test_iter_rect_mut() {
796        let mut plane = Plane::new(1, 1, 4, 4);
797        plane.insert((1, 1), 1, 1);
798        plane.insert((2, 1), 2, 1);
799        plane.insert((3, 1), 3, 1);
800        plane.insert((4, 1), 4, 1);
801        plane.insert((5, 1), 5, 1);
802
803        plane.insert((1, 2), 1, 2);
804        plane.insert((2, 2), 2, 2);
805        plane.insert((3, 2), 3, 2);
806        plane.insert((4, 2), 4, 2);
807        plane.insert((5, 2), 5, 2);
808
809        plane.insert((1, 3), 1, 3);
810        plane.insert((2, 3), 2, 3);
811        plane.insert((3, 3), 3, 3);
812        plane.insert((4, 3), 4, 3);
813        plane.insert((5, 3), 5, 3);
814
815        plane.insert((1, 4), 1, 4);
816        plane.insert((2, 4), 2, 4);
817        plane.insert((3, 4), 3, 4);
818        plane.insert((4, 4), 4, 4);
819        plane.insert((5, 4), 5, 4);
820
821        plane.insert((1, 5), 1, 5);
822        plane.insert((2, 5), 2, 5);
823        plane.insert((3, 5), 3, 5);
824        plane.insert((4, 5), 4, 5);
825        plane.insert((5, 5), 5, 5);
826
827        plane.foreach_rect_mut(3, 2, 6, 5, |_, (xv, yv)| {
828            *xv += 10;
829            *yv += 20;
830        });
831
832        let mut value: Vec<_> = plane.iter_rect(2, 2, 7, 5).map(|(a, v)| (a, *v)).collect();
833        value.sort_by(
834            |((x1, y1), _), ((x2, y2), _)| {
835                if x1 == x2 {
836                    y1.cmp(y2)
837                } else {
838                    x1.cmp(x2)
839                }
840            },
841        );
842
843        assert_eq!(
844            value,
845            vec![
846                ((2, 2), (2, 2)),
847                ((2, 3), (2, 3)),
848                ((2, 4), (2, 4)),
849                ((2, 5), (2, 5)),
850                ((3, 2), (13, 22)),
851                ((3, 3), (13, 23)),
852                ((3, 4), (13, 24)),
853                ((3, 5), (13, 25)),
854                ((4, 2), (14, 22)),
855                ((4, 3), (14, 23)),
856                ((4, 4), (14, 24)),
857                ((4, 5), (14, 25)),
858                ((5, 2), (15, 22)),
859                ((5, 3), (15, 23)),
860                ((5, 4), (15, 24)),
861                ((5, 5), (15, 25)),
862                ((6, 2), (10, 20)),
863                ((6, 3), (10, 20)),
864                ((6, 4), (10, 20)),
865                ((6, 5), (10, 20)),
866                ((7, 2), (0, 0)),
867                ((7, 3), (0, 0)),
868                ((7, 4), (0, 0)),
869                ((7, 5), (0, 0)),
870            ]
871        );
872    }
873}