grid_math/
lib.rs

1//! Basic representation of Grid, Cell, and assosiated mathematical operations. Helpful in CLI-based gamedev.
2//!
3//! This module contains the [`Cell`] type, representing the basic unit of [`Grid`],
4//! the [`Grid`] type, representing a two-dimentional field of [`Cell`]s,
5//! the [`Cells`] type, representing an iterator over every [`Cell`] on the [`Grid`],
6//! the [`Rows`] and the [`Columns`] types, representing iterators over subgrids of [`Grid`],
7//! and the [`GridMap<V>`] type, representing a wrapper around the [`HashMap<Cell, V>`]
8//!
9//! # Usecases
10//!
11//! One of the best usecases of this crate is for developing `CLI` based games:
12//! `Cell` has two fields representing position on the `Grid`, which are both `u8`,
13//! and the `Grid` consists of the `start` and the `end` `Cell`s,
14//! making the largest possible `Grid` to be 255x255, which is enough for most terminal games.
15//!
16//! # Note
17//!
18//! - `Cell`'s global position currently represented in the `u8` for simplicity,
19//!   and because this is enough for most terminal games. This may be changed to be a scalar generic in the future.
20//! - Error handling is currently rather stupid (just checks with panic!), but this helps to prevent scary logical bugs.
21//! - Crate is in the "work in progress" state, so the public API may change in the future. Feel free to contribute!
22//!
23//! # Examples
24//!
25//! Perform some basic calculations for `Cell`:
26//! ```
27//! use grid_math::{Cell, Grid};
28//!
29//! let grid = Grid::new(10, 10);
30//! let start = grid.start();
31//! let next = start.saturating_right(grid, 5).wrapping_down(grid, 15).strict_left(grid, 1);
32//!
33//! assert!(next.within(grid));
34//! assert_eq!(next, Cell::new(4, 5));
35//! ```
36//!
37//! Map every `Cell` on the `Grid` to the custom `String` representation:
38//! ```
39//! use grid_math::{Cell, Grid};
40//!
41//! let grid = Grid::new(3, 3);
42//! let grid_string = grid
43//!     .rows()
44//!     .map(|row| {
45//!         row.cells().map(|_| " [#]")
46//!             .chain(std::iter::once("\n\n"))
47//!             .collect::<String>()
48//!     })
49//!     .collect::<String>();
50//! assert_eq!(grid_string,
51//! " \
52//!  [#] [#] [#]
53//!
54//!  [#] [#] [#]
55//!
56//!  [#] [#] [#]
57//!
58//! "
59//! );
60//! ```
61//!
62//! Store some actual data on the `Grid`, using `GridMap`:
63//! ```
64//! use grid_math::{Cell, Grid, GridMap};
65//!
66//! let grid = Grid::new(5, 5);
67//! let mut map: GridMap<char> = GridMap::from(grid);
68//! map.insert(map.grid().start(), '#');
69//! map.insert(map.grid().end(), '@');
70//!
71//! assert_eq!(map.len(), 2);
72//! assert_eq!(map.get(&Cell::new(0, 0)).unwrap(), &'#');
73//! ```
74
75use rand::seq::IteratorRandom;
76use std::collections::HashMap;
77use std::convert::{From, Into};
78use std::fmt;
79use std::iter::Filter;
80use std::ops::{Deref, DerefMut};
81
82/// `Cell` represents the basic unit of `Grid`.
83///
84/// Consists of global positions `global_width: u8` and `global_depth: u8`, alongside with methods implementing
85/// common mathematical operations for safe interactions with grids and other cells
86///
87/// Due to low memory size, `Cell` implements `Copy` trait, so all methods take `self` (copy) as first argument
88///
89/// # Examples
90///
91/// You can create Cell using new(global_width, global_depth):
92/// ```
93/// use grid_math::Cell;
94///
95/// let cell = Cell::new(10, 15);
96/// ```
97///
98/// Or use functionality of implemented `From` and `Into` traits:
99/// ```
100/// use grid_math::Cell;
101///
102/// let cell = Cell::from((9, 9));
103/// let cell: Cell = (6, 7).into();
104/// ```
105///
106/// To read global_width or global_depth values, use getters:
107/// ```
108/// use grid_math::Cell;
109///
110/// let cell = Cell::new(10, 10);
111/// let w = cell.global_width();
112/// let d = cell.global_depth();
113/// ```
114/// Or use `into()` provided by `Into` trait:
115/// ```
116/// use grid_math::Cell;
117///
118/// let cell = Cell::new(10, 10);
119/// let (w, d): (u8, u8) = cell.into();
120/// ```
121///
122/// 'Cell' implements `Display` and `Debug` trait, so you can easily print it out:
123/// ```
124/// use grid_math::Cell;
125///
126/// let cell = Cell::new(10, 10);
127/// println!("Cell: {cell}"); // Cell: (10, 10)
128/// assert_eq!(format!("{cell}"), "(10, 10)");
129/// ```
130///
131/// Other methods involve interactions with `Grid`
132///
133/// `Cell` is designed to not mutate it's contents.
134/// Instead, all operations return new instances of `Cell`
135///
136/// Also worth noting, that all operations on `Cell` are verified to be logically correct,
137/// otherwise logically incorrect operations will be met with panic!
138///
139/// Here is a brief overview of `Cell` and `Grid` interactions:
140///
141/// Check if `Cell` is within the `Grid`:
142/// ```
143/// use grid_math::{Cell, Grid};
144///
145/// let cell = Cell::new(3, 4);
146/// let grid = Grid::new(10, 10); // 10x10 grid starting at (0,0)
147/// assert!(cell.within(grid));
148/// ```
149///
150/// Get relative to the `Grid` position of `Cell`:
151/// (`Grid` can start not only from (0,0))
152/// ```
153/// use grid_math::{Cell, Grid};
154///
155/// let cell = Cell::new(3, 4);
156/// let grid = Grid::indented(8, 8, (2, 1)); // 8x8 grid starting at (2,1)
157/// let (width, depth) = (cell.width(grid), cell.depth(grid));
158/// // cell's width on grid = cell.global_width - grid.start.global_width
159/// // cell's depth on grid = cell.global_depth - grid.start.global_depth
160/// assert_eq!((width, depth), (1, 3));
161/// // get gaps between width and depth grid borders and cell:
162/// let (width_gap, depth_gap) = (cell.width_gap(grid), cell.depth_gap(grid));
163/// assert_eq!((width_gap, depth_gap), (6, 4));
164/// // get member of grid by relative position:
165/// let member = grid.member(width, depth);
166/// assert_eq!(cell, member);
167/// ```
168///
169/// Perform some move calculations of `Cell` on `Grid`:
170/// ```
171/// use grid_math::{Cell, Grid};
172///
173/// let grid = Grid::new(10, 10);
174/// let cell = grid.start(); // get grid's first cell
175/// let next = cell.strict_right(grid, 3); // move to the right by 3, panics if grid bounds overflow occures
176/// assert_eq!(next, Cell::new(3, 0));
177/// let next = cell.saturating_down(grid, 15); // move down by 15, returns grid bound if overflow occures
178/// assert_eq!(next, Cell::new(0, 9));
179/// let next = cell.wrapping_right(grid, 5).strict_left(grid, 2).project_down(grid); // chain of movements
180/// assert_eq!(next, Cell::new(3, 9));
181/// ```
182///
183/// To get more examples, look at `Cell` and `Grid` methods documentation.
184///
185///
186#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
187pub struct Cell {
188    global_width: u8,
189    global_depth: u8,
190}
191
192/// `Grid` represents the field of `Cell`
193///
194/// Consists of `start: Cell` and `end: Cell` fields, alongside with methods implementing
195/// common mathematical operations for safe interactions with cells and other grids
196///
197/// `Grid` has two axis: width, and depth:
198///
199/// (0,0) [#] [#] [#] [#] (5,0)
200///
201///  [#]  [#] [#] [#] [#]  [#]
202///
203///  [#]  [#] [#] [#] [#]  [#]
204///
205///  [#]  [#] [#] [#] [#]  [#]
206///
207///  [#]  [#] [#] [#] [#]  [#]
208///
209/// (0,5) [#] [#] [#] [#] (5,5)
210///
211/// Due to low memory size, `Grid` implements `Copy` trait, so all methods take `self` (copy) as first argument
212///
213/// # Examples
214///
215/// You can create Grid using new(width, depth) or indented(width, depth, indent):
216/// ```
217/// use grid_math::Grid;
218///
219/// let grid = Grid::new(5, 5); // new 5x5 grid, starting at (0,0)
220/// let grid = Grid::indented(5, 5, (1, 2)); // new 5x5 grid, starting at (1,2)
221/// ```
222///
223/// Or use functionality of implemented `From` and `Into` traits:
224/// ```
225/// use grid_math::{Grid, Cell};
226///
227/// let grid = Grid::from(((1, 2), (5, 6))); // new field where `start` is (1,2), `end` is (5,6)
228/// let grid: Grid = ((1, 2), (5, 6)).into();
229/// //same for (cell, cell):
230/// let grid = Grid::from((Cell::new(1, 2), Cell::new(5, 6)));
231/// let grid: Grid = (Cell::new(1, 2), Cell::new(5, 6)).into();
232/// // backwards:
233/// let (start, end) = grid.into();
234/// assert_eq!((start, end), (Cell::new(1, 2), Cell::new(5, 6)));
235/// let ((w1, d1), (w2, d2)) = grid.into();
236/// assert_eq!(((w1, d1), (w2, d2)), ((1, 2), (5, 6)));
237/// ```
238///
239/// Important:
240/// When creating `Grid` from cells, you specify `start` and `end` cell, not width and depth
241/// This means that if you create grid with `start` (1, 2) and `end` (5, 6),
242/// this will be 5x5 grid, not 4x4 as you can think (5 - 1 = 4, 6 - 2 = 4)
243/// this is because `start` and `end` bounds included, they are actual members of grid,
244/// where the `start` is the first cell on the grid, and `end` is the last cell on grid
245///
246/// To read `start` and `end` fields, or to calculate other common attributes, use getters:
247/// ```
248/// use grid_math::{Grid, Cell};
249///
250/// let grid = Grid::indented(8, 8, (3, 3)); // 8x8 grid, starting at (3,3)
251/// let (start, end) = (grid.start(), grid.end());
252/// assert_eq!((start, end), (Cell::new(3, 3), Cell::new(10, 10)));
253/// let (width, depth) = (grid.width(), grid.depth());
254/// assert_eq!((width, depth), (8, 8));
255/// let size = grid.size();
256/// assert_eq!(size, 64);
257/// ```
258///
259/// 'Grid' implements `Display` and `Debug` trait, so you can easily print it out:
260/// ```
261/// use grid_math::Grid;
262///
263/// let grid = Grid::new(10, 10);
264/// println!("Grid: {grid}"); // Grid: [(0, 0):(9, 9)]
265/// assert_eq!(format!("{grid}"), "[(0, 0):(9, 9)]");
266/// ```
267///
268/// Other advanced operations include interactions with other grids and cells:
269///
270/// Check if cell or subgrid is within grid:
271/// ```
272/// use grid_math::{Grid, Cell};
273///
274/// let grid = Grid::new(10, 10);
275/// let cell = Cell::new(3, 4);
276/// let subgrid = Grid::indented(5, 5, (2, 2));
277/// assert!(subgrid.within(grid));
278/// assert!(cell.within(grid));
279/// ```
280///
281/// Get `Cell` from `Grid` by relative position:
282/// ```
283/// use grid_math::{Grid, Cell};
284///
285/// let grid = Grid::indented(5, 5, (2, 2));
286/// let member = grid.member(2, 2);
287///
288/// assert_eq!(member, Cell::new(4, 4));
289/// ```
290///
291/// Important:
292/// When creating `Grid`, we specify `width` and `depth` in terms of length
293/// But when we address member of `Grid`, we specify `width` and `depth` in terms of indexes
294/// This means that `Grid` with `width` 5, and start at (0,*), will has `end` at (4,*),
295/// because we have (0,*) (1,*) (2,*) (3,*) (4,*), which is 5 elements in total
296/// So we used `width` 5 at `Grid` creation and got `Grid` with last cell (4,*)
297/// But if we use `width` 5 when indexing member of `Grid`, we will get an error, because indexing starts at 0
298///
299/// Get subgrid from `Grid` by relative position:
300/// ```
301/// use grid_math::{Grid, Cell};
302///
303/// let grid = Grid::indented(5, 5, (2, 2));
304/// assert_eq!(format!("{grid}"), "[(2, 2):(6, 6)]");
305/// // get subgrid starting at current grid start, with specified width and depth:
306/// let area = grid.area(3, 3);
307/// assert_eq!(format!("{area}"), "[(2, 2):(4, 4)]");
308/// // get subgrid starting at indent from current grid start and specified width and depth:
309/// let slice = grid.slice(3, 3, (1, 1));
310/// assert_eq!(format!("{slice}"), "[(3, 3):(5, 5)]");
311/// ```
312///
313/// Perform some move calculations of `Cell` on `Grid`:
314/// ```
315/// use grid_math::{Cell, Grid};
316///
317/// let grid = Grid::new(10, 10);
318/// let cell = grid.start(); // get grid's first cell
319/// let next = cell.strict_right(grid, 3); // move to the right by 3, panics if grid bounds overflow occures
320/// assert_eq!(next, Cell::new(3, 0));
321/// let next = cell.saturating_down(grid, 15); // move down by 15, returns grid bound if overflow occures
322/// assert_eq!(next, Cell::new(0, 9));
323/// let next = cell.wrapping_right(grid, 5).strict_left(grid, 2).project_down(grid); // chain of movements
324/// assert_eq!(next, Cell::new(3, 9));
325/// ```
326///
327/// Perform some actually usefull operations, using `Iterator` functionality:
328/// ```
329/// use grid_math::{Cell, Grid};
330///
331/// let grid = Grid::new(3, 3);
332/// let grid_string = grid
333///     .rows()
334///     .map(|row| {
335///         row.cells().map(|_| " [#]")
336///             .chain(std::iter::once("\n\n"))
337///             .collect::<String>()
338///     })
339///     .collect::<String>();
340/// assert_eq!(grid_string,
341/// " \
342///  [#] [#] [#]
343///
344///  [#] [#] [#]
345///
346///  [#] [#] [#]
347///
348/// "
349/// );
350/// ```
351///
352/// To get more examples, look at `Cell` and `Grid` methods documentation.
353///
354///
355#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
356pub struct Grid {
357    start: Cell,
358    end: Cell,
359}
360
361/// `Cells` represents an iterator over every `Cell` on the `Grid`
362///
363/// # Examples
364///
365/// Get every `Cell` on `width` and `depth` axis:
366/// ```
367/// use grid_math::{Cell, Grid};
368///
369/// let grid = Grid::new(3, 3);
370///
371/// let axis_cells: Vec<Cell> = grid
372///     .cells()
373///     .filter(|cell| {
374///         cell.global_width() == grid.start().global_width() || cell.global_depth() == grid.start().global_depth()
375///     })
376///     .collect();
377/// assert_eq!(axis_cells, vec![
378///     Cell::new(0, 0),
379///     Cell::new(1, 0),
380///     Cell::new(2, 0),
381///     Cell::new(0, 1),
382///     Cell::new(0, 2),
383/// ]);
384/// ```
385///
386#[derive(Debug, Clone, Copy, PartialEq, Eq)]
387pub struct Cells {
388    grid: Grid,
389    current: Cell,
390    consumed: bool,
391}
392
393/// `Rows` represents an iterator over every row of `Cell` on the `Grid`
394///
395/// Every element of 'Rows' returns `Grid`
396///
397/// # Examples
398///
399/// Print out `Grid` in custom format:
400/// ```
401/// use grid_math::{Cell, Grid};
402///
403/// let grid = Grid::new(3, 3);
404/// let grid_string = grid
405///     .rows()
406///     .map(|row| {
407///         row.cells().map(|_| " [#]")
408///             .chain(std::iter::once("\n\n"))
409///             .collect::<String>()
410///     })
411///     .collect::<String>();
412/// assert_eq!(grid_string,
413/// " \
414///  [#] [#] [#]
415///
416///  [#] [#] [#]
417///
418///  [#] [#] [#]
419///
420/// "
421/// );
422/// ```
423///
424#[derive(Debug, Clone, Copy, PartialEq, Eq)]
425pub struct Rows {
426    grid: Grid,
427    current: Grid,
428    consumed: bool,
429}
430
431/// `Columns` represents an iterator over every column of `Cell` on the `Grid`
432///
433/// Every element of 'Columns' returns `Grid`
434///
435/// # Examples
436///
437/// Get every `Cell` on the first column of `Grid`:
438/// ```
439/// use grid_math::{Cell, Grid};
440///
441/// let grid = Grid::new(3, 3);
442///
443/// let first_column_cells: Vec<Cell> = grid
444///     .columns()
445///     .next()
446///     .unwrap()
447///     .cells()
448///     .collect();
449///
450/// assert_eq!(first_column_cells, vec![
451///     Cell::new(0, 0),
452///     Cell::new(0, 1),
453///     Cell::new(0, 2),
454/// ]);
455/// ```
456#[derive(Debug, Clone, Copy, PartialEq, Eq)]
457pub struct Columns {
458    grid: Grid,
459    current: Grid,
460    consumed: bool,
461}
462
463/// `GridMap<V>` represents a wrapper around the `HashMap<Cell, V>`
464///
465/// `GridMap` is helpful for storing some actual data on the `Grid`.
466/// It implements `Deref` and `DerefMut` traits, so we can call methods from `HashMap`
467/// directly on the `GridMap`.
468///
469/// The main difference between the `GridMap<V>` and the `HashMap<Cell, V>` is that
470/// the `GridMap<V>` has actual bounds, that are defined by the inner `Grid`.
471///
472/// `GridMap` currently has rather stupid error handling, but this helps to prevent scary logical bugs.
473///
474/// # Examples
475///
476/// ```
477/// use grid_math::{Cell, Grid, GridMap};
478///
479/// let grid = Grid::new(5, 5);
480/// let mut map: GridMap<char> = GridMap::from(grid);
481/// map.insert(map.grid().start(), '#');
482/// map.insert(map.grid().end(), '@');
483/// assert_eq!(map.len(), 2);
484/// assert_eq!(map.get(&Cell::new(0, 0)).unwrap(), &'#');
485/// ```
486///
487/// ```should_panic
488/// use grid_math::{Cell, Grid, GridMap};
489///
490/// let grid = Grid::new(5, 5);
491/// let cell = Cell::new(6, 6);
492/// let mut map: GridMap<char> = GridMap::from(grid);
493/// map.insert(cell, '#'); // panic!
494/// ```
495#[derive(Debug, Clone)]
496pub struct GridMap<V> {
497    grid: Grid,
498    hashmap: HashMap<Cell, V>,
499}
500
501impl Cell {
502    /// Creates new `Cell` with specified `global_width: u8` and `global_depth: u8` global position
503    ///
504    /// # Examples
505    ///
506    /// ```
507    /// use grid_math::Cell;
508    ///
509    /// let cell = Cell::new(10, 15);
510    /// ```
511    pub fn new(global_width: u8, global_depth: u8) -> Self {
512        Self {
513            global_width,
514            global_depth,
515        }
516    }
517
518    /// Checks if the `Cell` is within the given `Grid`
519    ///
520    /// # Examples
521    ///
522    /// ```
523    /// use grid_math::{Cell, Grid};
524    ///
525    /// let grid = Grid::new(10, 10);
526    /// let cell = Cell::new(5, 5);
527    /// assert!(cell.within(grid));
528    ///
529    /// let cell = Cell::new(9, 15);
530    /// assert!(!cell.within(grid));
531    /// ```
532    pub fn within(self, grid: Grid) -> bool {
533        (grid.start.global_width..=grid.end.global_width).contains(&self.global_width)
534            && (grid.start.global_depth..=grid.end.global_depth).contains(&self.global_depth)
535    }
536
537    /// Checks if the `Cell` is within the given `Grid`
538    ///
539    /// # Panics
540    /// Panics if the `Cell` is not within the given `Grid`
541    ///
542    /// # Examples
543    ///
544    /// ```should_panic
545    /// use grid_math::{Cell, Grid};
546    ///
547    /// let grid = Grid::new(10, 10);
548    /// let cell = Cell::new(9, 15);
549    /// cell.within_panic(grid);
550    /// ```
551    pub fn within_panic(self, grid: Grid) {
552        if !self.within(grid) {
553            panic!("cell is not within given grid! cell:{self}, grid:{grid}")
554        }
555    }
556
557    /// Returns `global_width` field of `Cell`
558    ///
559    /// # Examples
560    ///
561    /// ```
562    /// use grid_math::Cell;
563    ///
564    /// let cell = Cell::new(8, 8);
565    /// let w = cell.global_width();
566    /// assert_eq!(w, 8);
567    /// ```
568    pub fn global_width(self) -> u8 {
569        self.global_width
570    }
571
572    /// Returns `global_depth` field of `Cell`
573    ///
574    /// # Examples
575    ///
576    /// ```
577    /// use grid_math::Cell;
578    ///
579    /// let cell = Cell::new(8, 8);
580    /// let d = cell.global_depth();
581    /// assert_eq!(d, 8);
582    /// ```
583    pub fn global_depth(self) -> u8 {
584        self.global_depth
585    }
586
587    /// Calculates the `width` of the `Cell` relative to the given `Grid`
588    /// `width` here means position / index / x of `Cell` on width axis
589    ///
590    /// # Panics
591    /// Panics if the `Cell` is not within the given `Grid`
592    ///
593    /// # Examples
594    ///
595    /// ```
596    /// use grid_math::{Cell, Grid};
597    ///
598    /// let cell = Cell::new(8, 8);
599    /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
600    /// let width = cell.width(grid); // width = 4
601    /// assert_eq!(width, 4);
602    /// ```
603    pub fn width(self, grid: Grid) -> u8 {
604        self.within_panic(grid);
605        self.global_width - grid.start.global_width
606    }
607
608    /// Calculates the gap between the `width` of `Cell` and the `width` of `Grid`
609    ///
610    /// # Panics
611    /// Panics if the `Cell` is not within the given `Grid`
612    ///
613    /// # Examples
614    ///
615    /// ```
616    /// use grid_math::{Cell, Grid};
617    ///
618    /// let cell = Cell::new(8, 8);
619    /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
620    /// let width_gap = cell.width_gap(grid); // width_gap = 2
621    /// assert_eq!(width_gap, 2);
622    /// ```
623    pub fn width_gap(self, grid: Grid) -> u8 {
624        self.within_panic(grid);
625        grid.end.global_width - self.global_width
626    }
627
628    /// Calculates the `depth` of `Cell` relative to the given `Grid`
629    /// `depth` here means position / index / y of `Cell` on depth axis
630    ///
631    /// # Panics
632    /// Panics if the `Cell` is not within the given `Grid`
633    ///
634    /// # Examples
635    ///
636    /// ```
637    /// use grid_math::{Cell, Grid};
638    ///
639    /// let cell = Cell::new(8, 8);
640    /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
641    /// let depth = cell.depth(grid); // depth = 4
642    /// assert_eq!(depth, 4);
643    /// ```
644    pub fn depth(self, grid: Grid) -> u8 {
645        self.within_panic(grid);
646        self.global_depth - grid.start.global_depth
647    }
648
649    /// Calculates the gap between the `depth` of `Cell` and the `depth` of `Grid`
650    ///
651    /// # Panics
652    /// Panics if the `Cell` is not within the given `Grid`
653    ///
654    /// # Examples
655    ///
656    /// ```
657    /// use grid_math::{Cell, Grid};
658    ///
659    /// let cell = Cell::new(8, 8);
660    /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
661    /// let depth_gap = cell.depth_gap(grid); // depth_gap = 2
662    /// assert_eq!(depth_gap, 2);
663    /// ```
664    pub fn depth_gap(self, grid: Grid) -> u8 {
665        self.within_panic(grid);
666        grid.end.global_depth - self.global_depth
667    }
668
669    /// Checks if the `up` operation on `Cell` will violate the given `Grid` upper border
670    ///
671    /// # Panics
672    /// Panics if the `Cell` is not within the given `Grid`
673    ///
674    /// # Examples
675    ///
676    /// ```
677    /// use grid_math::{Cell, Grid};
678    ///
679    /// let grid = Grid::new(10, 10);
680    /// let cell = Cell::new(2, 2);
681    /// assert!(cell.will_underflow_depth(grid, 3));
682    /// assert!(!cell.will_underflow_depth(grid, 2));
683    /// ```
684    pub fn will_underflow_depth(self, grid: Grid, step: u8) -> bool {
685        self.within_panic(grid);
686        self.global_depth < step || self.global_depth - step < grid.start.global_depth
687    }
688
689    /// Checks if the `down` operation on `Cell` will violate the given `Grid` lower border
690    ///
691    /// # Panics
692    /// Panics if the `Cell` is not within the given `Grid`
693    ///
694    /// # Examples
695    ///
696    /// ```
697    /// use grid_math::{Cell, Grid};
698    ///
699    /// let grid = Grid::new(10, 10);
700    /// let cell = Cell::new(7, 7);
701    /// assert!(cell.will_overflow_depth(grid, 3));
702    /// assert!(!cell.will_overflow_depth(grid, 2));
703    /// ```
704    pub fn will_overflow_depth(self, grid: Grid, step: u8) -> bool {
705        self.within_panic(grid);
706        self.global_depth > u8::MAX - step || self.global_depth + step > grid.end.global_depth
707    }
708
709    /// Checks if the `left` operation on `Cell` will violate the given `Grid` left border
710    ///
711    /// # Panics
712    /// Panics if the `Cell` is not within the given `Grid`
713    ///
714    /// # Examples
715    ///
716    /// ```
717    /// use grid_math::{Cell, Grid};
718    ///
719    /// let grid = Grid::new(10, 10);
720    /// let cell = Cell::new(2, 2);
721    /// assert!(cell.will_underflow_width(grid, 3));
722    /// assert!(!cell.will_underflow_width(grid, 2));
723    /// ```
724    pub fn will_underflow_width(self, grid: Grid, step: u8) -> bool {
725        self.within_panic(grid);
726        self.global_width < step || self.global_width - step < grid.start.global_width
727    }
728
729    /// Checks if the `right` operation on `Cell` will violate the given `Grid` right border
730    ///
731    /// # Panics
732    /// Panics if the `Cell` is not within the given `Grid`
733    ///
734    /// # Examples
735    ///
736    /// ```
737    /// use grid_math::{Cell, Grid};
738    ///
739    /// let grid = Grid::new(10, 10);
740    /// let cell = Cell::new(7, 7);
741    /// assert!(cell.will_overflow_width(grid, 3));
742    /// assert!(!cell.will_overflow_width(grid, 2));
743    /// ```
744    pub fn will_overflow_width(self, grid: Grid, step: u8) -> bool {
745        self.within_panic(grid);
746        self.global_width > u8::MAX - step || self.global_width + step > grid.end.global_width
747    }
748
749    /// Moves current `Cell` upwards by `step` relative to the given `Grid`
750    /// This operation does not mutate current `Cell` fields,
751    /// instead it calculates new position and returns new `Cell`
752    ///
753    /// # Panics
754    /// Panics if the `Cell` is not within the given `Grid`
755    /// Panics if this operation will violate the given `Grid` upper border
756    ///
757    /// # Examples
758    ///
759    /// ```
760    /// use grid_math::{Cell, Grid};
761    ///
762    /// let grid = Grid::new(10, 10);
763    /// let cell = Cell::new(2, 2);
764    /// let next = cell.strict_up(grid, 2);
765    /// assert_eq!(next, Cell::new(2, 0));
766    /// ```
767    ///
768    /// ```should_panic
769    /// use grid_math::{Cell, Grid};
770    ///
771    /// let grid = Grid::new(10, 10);
772    /// let cell = Cell::new(2, 2);
773    /// let next = cell.strict_up(grid, 3); // panic!
774    /// ```
775    pub fn strict_up(self, grid: Grid, step: u8) -> Cell {
776        if self.will_underflow_depth(grid, step) {
777            panic!(
778                "this operation will violate grid upper bounds! cell:{self}, grid:{grid}, step:{step}"
779            );
780        }
781        Cell {
782            global_width: self.global_width,
783            global_depth: self.global_depth - step,
784        }
785    }
786
787    /// Moves current `Cell` downwards by `step` relative to the given `Grid`
788    /// This operation does not mutate current `Cell` fields,
789    /// instead it calculates new position and returns new `Cell`
790    ///
791    /// # Panics
792    /// Panics if the `Cell` is not within the given `Grid`
793    /// Panics if this operation will violate the given `Grid` lower border
794    ///
795    /// # Examples
796    ///
797    /// ```
798    /// use grid_math::{Cell, Grid};
799    ///
800    /// let grid = Grid::new(10, 10);
801    /// let cell = Cell::new(7, 7);
802    /// let next = cell.strict_down(grid, 2);
803    /// assert_eq!(next, Cell::new(7, 9));
804    /// ```
805    ///
806    /// ```should_panic
807    /// use grid_math::{Cell, Grid};
808    ///
809    /// let grid = Grid::new(10, 10);
810    /// let cell = Cell::new(7, 7);
811    /// let next = cell.strict_down(grid, 3); // panic!
812    /// ```
813    pub fn strict_down(self, grid: Grid, step: u8) -> Cell {
814        if self.will_overflow_depth(grid, step) {
815            panic!(
816                "this operation will violate grid lower bounds! cell:{self}, grid:{grid}, step:{step}"
817            );
818        }
819        Cell {
820            global_width: self.global_width,
821            global_depth: self.global_depth + step,
822        }
823    }
824
825    /// Moves current `Cell` to the left by `step` relative to the given `Grid`
826    /// This operation does not mutate current `Cell` fields,
827    /// instead it calculates new position and returns new `Cell`
828    ///
829    /// # Panics
830    /// Panics if the `Cell` is not within the given `Grid`
831    /// Panics if this operation will violate the given `Grid` left border
832    ///
833    /// # Examples
834    ///
835    /// ```
836    /// use grid_math::{Cell, Grid};
837    ///
838    /// let grid = Grid::new(10, 10);
839    /// let cell = Cell::new(2, 2);
840    /// let next = cell.strict_left(grid, 2);
841    /// assert_eq!(next, Cell::new(0, 2));
842    /// ```
843    ///
844    /// ```should_panic
845    /// use grid_math::{Cell, Grid};
846    ///
847    /// let grid = Grid::new(10, 10);
848    /// let cell = Cell::new(2, 2);
849    /// let next = cell.strict_left(grid, 3); // panic!
850    /// ```
851    pub fn strict_left(self, grid: Grid, step: u8) -> Cell {
852        if self.will_underflow_width(grid, step) {
853            panic!(
854                "this operation will violate grid left bounds! cell:{self}, grid:{grid}, step:{step}"
855            );
856        }
857        Cell {
858            global_width: self.global_width - step,
859            global_depth: self.global_depth,
860        }
861    }
862
863    /// Moves current `Cell` to the right by `step` relative to the given `Grid`
864    /// This operation does not mutate current `Cell` fields,
865    /// instead it calculates new position and returns new `Cell`
866    ///
867    /// # Panics
868    /// Panics if the `Cell` is not within the given `Grid`
869    /// Panics if this operation will violate the given `Grid` right border
870    ///
871    /// # Examples
872    ///
873    /// ```
874    /// use grid_math::{Cell, Grid};
875    ///
876    /// let grid = Grid::new(10, 10);
877    /// let cell = Cell::new(7, 7);
878    /// let next = cell.strict_right(grid, 2);
879    /// assert_eq!(next, Cell::new(9, 7));
880    /// ```
881    ///
882    /// ```should_panic
883    /// use grid_math::{Cell, Grid};
884    ///
885    /// let grid = Grid::new(10, 10);
886    /// let cell = Cell::new(7, 7);
887    /// let next = cell.strict_right(grid, 3); // panic!
888    /// ```
889    pub fn strict_right(self, grid: Grid, step: u8) -> Cell {
890        if self.will_overflow_width(grid, step) {
891            panic!(
892                "this operation will violate grid right bounds! cell:{self}, grid:{grid}, step:{step}"
893            );
894        }
895        Cell {
896            global_width: self.global_width + step,
897            global_depth: self.global_depth,
898        }
899    }
900
901    /// Moves current `Cell` upwards by `step` relative to the given `Grid`
902    ///
903    /// This operation does not mutate current `Cell` fields,
904    /// instead it calculates new position and returns new `Cell`
905    ///
906    /// If this operation will cross `Grid` upper border,
907    /// returns `Cell` with `depth` = `Grid` upper depth limit
908    ///
909    /// # Panics
910    /// Panics if the `Cell` is not within the given `Grid`
911    ///
912    /// # Examples
913    ///
914    /// ```
915    /// use grid_math::{Cell, Grid};
916    ///
917    /// let grid = Grid::new(10, 10);
918    /// let cell = Cell::new(2, 2);
919    /// let next = cell.saturating_up(grid, 2);
920    /// assert_eq!(next, Cell::new(2, 0));
921    /// let next = cell.saturating_up(grid, 5);
922    /// assert_eq!(next, Cell::new(2, 0));
923    /// ```
924    pub fn saturating_up(self, grid: Grid, step: u8) -> Cell {
925        let next_depth = if self.will_underflow_depth(grid, step) {
926            grid.start.global_depth
927        } else {
928            self.global_depth - step
929        };
930        Cell {
931            global_width: self.global_width,
932            global_depth: next_depth,
933        }
934    }
935
936    /// Moves current `Cell` downwards by `step` relative to the given `Grid`
937    ///
938    /// This operation does not mutate current `Cell` fields,
939    /// instead it calculates new position and returns new `Cell`
940    ///
941    /// If this operation will cross `Grid` lower border,
942    /// returns `Cell` with `depth` = `Grid` lower depth limit
943    ///
944    /// # Panics
945    /// Panics if the `Cell` is not within the given `Grid`
946    ///
947    /// # Examples
948    ///
949    /// ```
950    /// use grid_math::{Cell, Grid};
951    ///
952    /// let grid = Grid::new(10, 10);
953    /// let cell = Cell::new(7, 7);
954    /// let next = cell.saturating_down(grid, 2);
955    /// assert_eq!(next, Cell::new(7, 9));
956    /// let next = cell.saturating_down(grid, 5);
957    /// assert_eq!(next, Cell::new(7, 9));
958    /// ```
959    pub fn saturating_down(self, grid: Grid, step: u8) -> Cell {
960        let next_depth = if self.will_overflow_depth(grid, step) {
961            grid.end.global_depth
962        } else {
963            self.global_depth + step
964        };
965        Cell {
966            global_width: self.global_width,
967            global_depth: next_depth,
968        }
969    }
970
971    /// Moves current `Cell` to the left by `step` relative to the given `Grid`
972    ///
973    /// This operation does not mutate current `Cell` fields,
974    /// instead it calculates new position and returns new `Cell`
975    ///
976    /// If this operation will cross `Grid` left border,
977    /// returns `Cell` with `width` = `Grid` left width limit
978    ///
979    /// # Panics
980    /// Panics if the `Cell` is not within the given `Grid`
981    ///
982    /// # Examples
983    ///
984    /// ```
985    /// use grid_math::{Cell, Grid};
986    ///
987    /// let grid = Grid::new(10, 10);
988    /// let cell = Cell::new(2, 2);
989    /// let next = cell.saturating_left(grid, 2);
990    /// assert_eq!(next, Cell::new(0, 2));
991    /// let next = cell.saturating_left(grid, 5);
992    /// assert_eq!(next, Cell::new(0, 2));
993    /// ```
994    pub fn saturating_left(self, grid: Grid, step: u8) -> Cell {
995        let next_width = if self.will_underflow_width(grid, step) {
996            grid.start.global_width
997        } else {
998            self.global_width - step
999        };
1000        Cell {
1001            global_width: next_width,
1002            global_depth: self.global_depth,
1003        }
1004    }
1005
1006    /// Moves current `Cell` to the right by `step` relative to the given `Grid`
1007    ///
1008    /// This operation does not mutate current `Cell` fields,
1009    /// instead it calculates new position and returns new `Cell`
1010    ///
1011    /// If this operation will cross `Grid` right border,
1012    /// returns `Cell` with `width` = `Grid` right width limit
1013    ///
1014    /// # Panics
1015    /// Panics if the `Cell` is not within the given `Grid`
1016    ///
1017    /// # Examples
1018    ///
1019    /// ```
1020    /// use grid_math::{Cell, Grid};
1021    ///
1022    /// let grid = Grid::new(10, 10);
1023    /// let cell = Cell::new(7, 7);
1024    /// let next = cell.saturating_right(grid, 2);
1025    /// assert_eq!(next, Cell::new(9, 7));
1026    /// let next = cell.saturating_right(grid, 5);
1027    /// assert_eq!(next, Cell::new(9, 7));
1028    /// ```
1029    pub fn saturating_right(self, grid: Grid, step: u8) -> Cell {
1030        let next_width = if self.will_overflow_width(grid, step) {
1031            grid.end.global_width
1032        } else {
1033            self.global_width + step
1034        };
1035        Cell {
1036            global_width: next_width,
1037            global_depth: self.global_depth,
1038        }
1039    }
1040
1041    /// Moves current `Cell` upwards by `step` relative to the given `Grid`
1042    ///
1043    /// This operation does not mutate current `Cell` fields,
1044    /// instead it calculates new position and returns new `Cell` and `bool`
1045    ///
1046    /// This operation is similar to the overflowing operations on integer types
1047    /// It returns new `Cell` and 'bool' signaling that overflow happened
1048    ///
1049    /// # Panics
1050    /// Panics if the `Cell` is not within the given `Grid`
1051    ///
1052    /// # Examples
1053    ///
1054    /// ```
1055    /// use grid_math::{Cell, Grid};
1056    ///
1057    /// let grid = Grid::new(10, 10);
1058    /// let cell = Cell::new(2, 2);
1059    /// let (next, overflowed) = cell.overflowing_up(grid, 2);
1060    /// assert_eq!((next, overflowed), (Cell::new(2, 0), false));
1061    /// let (next, overflowed) = cell.overflowing_up(grid, 5);
1062    /// assert_eq!((next, overflowed), (Cell::new(2, 7), true));
1063    /// ```
1064    pub fn overflowing_up(self, grid: Grid, step: u8) -> (Cell, bool) {
1065        let underflowed = self.will_underflow_depth(grid, step);
1066        let next_depth = if underflowed {
1067            grid.end.global_depth - ((step - self.depth(grid) - 1) % grid.depth())
1068        } else {
1069            self.global_depth - step
1070        };
1071        (
1072            Cell {
1073                global_width: self.global_width,
1074                global_depth: next_depth,
1075            },
1076            underflowed,
1077        )
1078    }
1079
1080    /// Moves current `Cell` downwards by `step` relative to the given `Grid`
1081    ///
1082    /// This operation does not mutate current `Cell` fields,
1083    /// instead it calculates new position and returns new `Cell` and `bool`
1084    ///
1085    /// This operation is similar to the overflowing operations on integer types
1086    /// It returns new `Cell` and 'bool' signaling that overflow happened
1087    ///
1088    /// # Panics
1089    /// Panics if the `Cell` is not within the given `Grid`
1090    ///
1091    /// # Examples
1092    ///
1093    /// ```
1094    /// use grid_math::{Cell, Grid};
1095    ///
1096    /// let grid = Grid::new(10, 10);
1097    /// let cell = Cell::new(7, 7);
1098    /// let (next, overflowed) = cell.overflowing_down(grid, 2);
1099    /// assert_eq!((next, overflowed), (Cell::new(7, 9), false));
1100    /// let (next, overflowed) = cell.overflowing_down(grid, 5);
1101    /// assert_eq!((next, overflowed), (Cell::new(7, 2), true));
1102    /// ```
1103    pub fn overflowing_down(self, grid: Grid, step: u8) -> (Cell, bool) {
1104        let overflowed = self.will_overflow_depth(grid, step);
1105        let next_depth = if overflowed {
1106            grid.start.global_depth + ((step - self.depth_gap(grid) - 1) % grid.depth())
1107        } else {
1108            self.global_depth + step
1109        };
1110        (
1111            Cell {
1112                global_width: self.global_width,
1113                global_depth: next_depth,
1114            },
1115            overflowed,
1116        )
1117    }
1118
1119    /// Moves current `Cell` to the left by `step` relative to the given `Grid`
1120    ///
1121    /// This operation does not mutate current `Cell` fields,
1122    /// instead it calculates new position and returns new `Cell` and `bool`
1123    ///
1124    /// This operation is similar to the overflowing operations on integer types
1125    /// It returns new `Cell` and 'bool' signaling that overflow happened
1126    ///
1127    /// # Panics
1128    /// Panics if the `Cell` is not within the given `Grid`
1129    ///
1130    /// # Examples
1131    ///
1132    /// ```
1133    /// use grid_math::{Cell, Grid};
1134    ///
1135    /// let grid = Grid::new(10, 10);
1136    /// let cell = Cell::new(2, 2);
1137    /// let (next, overflowed) = cell.overflowing_left(grid, 2);
1138    /// assert_eq!((next, overflowed), (Cell::new(0, 2), false));
1139    /// let (next, overflowed) = cell.overflowing_left(grid, 5);
1140    /// assert_eq!((next, overflowed), (Cell::new(7, 2), true));
1141    /// ```
1142    pub fn overflowing_left(self, grid: Grid, step: u8) -> (Cell, bool) {
1143        let underflowed = self.will_underflow_width(grid, step);
1144        let next_width = if underflowed {
1145            grid.end.global_width - ((step - self.width(grid) - 1) % grid.width())
1146        } else {
1147            self.global_width - step
1148        };
1149        (
1150            Cell {
1151                global_width: next_width,
1152                global_depth: self.global_depth,
1153            },
1154            underflowed,
1155        )
1156    }
1157
1158    /// Moves current `Cell` to the right by `step` relative to the given `Grid`
1159    ///
1160    /// This operation does not mutate current `Cell` fields,
1161    /// instead it calculates new position and returns new `Cell` and `bool`
1162    ///
1163    /// This operation is similar to the overflowing operations on integer types
1164    /// It returns new `Cell` and 'bool' signaling that overflow happened
1165    ///
1166    /// # Panics
1167    /// Panics if the `Cell` is not within the given `Grid`
1168    ///
1169    /// # Examples
1170    ///
1171    /// ```
1172    /// use grid_math::{Cell, Grid};
1173    ///
1174    /// let grid = Grid::new(10, 10);
1175    /// let cell = Cell::new(7, 7);
1176    /// let (next, overflowed) = cell.overflowing_right(grid, 2);
1177    /// assert_eq!((next, overflowed), (Cell::new(9, 7), false));
1178    /// let (next, overflowed) = cell.overflowing_right(grid, 5);
1179    /// assert_eq!((next, overflowed), (Cell::new(2, 7), true));
1180    /// ```
1181    pub fn overflowing_right(self, grid: Grid, step: u8) -> (Cell, bool) {
1182        let overflowed = self.will_overflow_width(grid, step);
1183        let next_width = if overflowed {
1184            grid.start.global_width + ((step - self.width_gap(grid) - 1) % grid.width())
1185        } else {
1186            self.global_width + step
1187        };
1188        (
1189            Cell {
1190                global_width: next_width,
1191                global_depth: self.global_depth,
1192            },
1193            overflowed,
1194        )
1195    }
1196
1197    /// Moves current `Cell` upwards by `step` relative to the given `Grid`
1198    ///
1199    /// This operation is a wrapper around the `overflowing_up()` method,
1200    /// and returns only new `Cell`, without `bool`
1201    ///
1202    /// # Panics
1203    /// Panics if the `Cell` is not within the given `Grid`
1204    ///
1205    /// # Examples
1206    ///
1207    /// ```
1208    /// use grid_math::{Cell, Grid};
1209    ///
1210    /// let grid = Grid::new(10, 10);
1211    /// let cell = Cell::new(2, 2);
1212    /// let next = cell.wrapping_up(grid, 2);
1213    /// assert_eq!(next, Cell::new(2, 0));
1214    /// let next = cell.wrapping_up(grid, 5);
1215    /// assert_eq!(next, Cell::new(2, 7));
1216    /// ```
1217    pub fn wrapping_up(self, grid: Grid, step: u8) -> Cell {
1218        self.overflowing_up(grid, step).0
1219    }
1220
1221    /// Moves current `Cell` downwards by `step` relative to the given `Grid`
1222    ///
1223    /// This operation is a wrapper around the `overflowing_down()` method,
1224    /// and returns only new `Cell`, without `bool`
1225    ///
1226    /// # Panics
1227    /// Panics if the `Cell` is not within the given `Grid`
1228    ///
1229    /// # Examples
1230    ///
1231    /// ```
1232    /// use grid_math::{Cell, Grid};
1233    ///
1234    /// let grid = Grid::new(10, 10);
1235    /// let cell = Cell::new(7, 7);
1236    /// let next = cell.wrapping_down(grid, 2);
1237    /// assert_eq!(next, Cell::new(7, 9));
1238    /// let next = cell.wrapping_down(grid, 5);
1239    /// assert_eq!(next, Cell::new(7, 2));
1240    /// ```
1241    pub fn wrapping_down(self, grid: Grid, step: u8) -> Cell {
1242        self.overflowing_down(grid, step).0
1243    }
1244
1245    /// Moves current `Cell` to the left by `step` relative to the given `Grid`
1246    ///
1247    /// This operation is a wrapper around the `overflowing_left()` method,
1248    /// and returns only new `Cell`, without `bool`
1249    ///
1250    /// # Panics
1251    /// Panics if the `Cell` is not within the given `Grid`
1252    ///
1253    /// # Examples
1254    ///
1255    /// ```
1256    /// use grid_math::{Cell, Grid};
1257    ///
1258    /// let grid = Grid::new(10, 10);
1259    /// let cell = Cell::new(2, 2);
1260    /// let next = cell.wrapping_left(grid, 2);
1261    /// assert_eq!(next, Cell::new(0, 2));
1262    /// let next = cell.wrapping_left(grid, 5);
1263    /// assert_eq!(next, Cell::new(7, 2));
1264    /// ```
1265    pub fn wrapping_left(self, grid: Grid, step: u8) -> Cell {
1266        self.overflowing_left(grid, step).0
1267    }
1268
1269    /// Moves current `Cell` to the right by `step` relative to the given `Grid`
1270    ///
1271    /// This operation is a wrapper around the `overflowing_right()` method,
1272    /// and returns only new `Cell`, without `bool`
1273    ///
1274    /// # Panics
1275    /// Panics if the `Cell` is not within the given `Grid`
1276    ///
1277    /// # Examples
1278    ///
1279    /// ```
1280    /// use grid_math::{Cell, Grid};
1281    ///
1282    /// let grid = Grid::new(10, 10);
1283    /// let cell = Cell::new(7, 7);
1284    /// let next = cell.wrapping_right(grid, 2);
1285    /// assert_eq!(next, Cell::new(9, 7));
1286    /// let next = cell.wrapping_right(grid, 5);
1287    /// assert_eq!(next, Cell::new(2, 7));
1288    /// ```
1289    pub fn wrapping_right(self, grid: Grid, step: u8) -> Cell {
1290        self.overflowing_right(grid, step).0
1291    }
1292
1293    /// Projects current `Cell` onto the top side of the given `Grid`
1294    ///
1295    /// This operation does not mutate current `Cell` fields,
1296    /// instead it calculates new position and returns new `Cell`
1297    ///
1298    /// # Panics
1299    /// Panics if the `Cell` is not within the given `Grid`
1300    ///
1301    /// # Examples
1302    ///
1303    /// ```
1304    /// use grid_math::{Cell, Grid};
1305    ///
1306    /// let grid = Grid::new(10, 10);
1307    /// let cell = Cell::new(2, 2);
1308    /// let next = cell.project_up(grid);
1309    /// assert_eq!(next, Cell::new(2, 0));
1310    /// ```
1311    pub fn project_up(self, grid: Grid) -> Cell {
1312        self.saturating_up(grid, u8::MAX)
1313    }
1314
1315    /// Projects current `Cell` onto the bottom side of the given `Grid`
1316    ///
1317    /// This operation does not mutate current `Cell` fields,
1318    /// instead it calculates new position and returns new `Cell`
1319    ///
1320    /// # Panics
1321    /// Panics if the `Cell` is not within the given `Grid`
1322    ///
1323    /// # Examples
1324    ///
1325    /// ```
1326    /// use grid_math::{Cell, Grid};
1327    ///
1328    /// let grid = Grid::new(10, 10);
1329    /// let cell = Cell::new(7, 7);
1330    /// let next = cell.project_down(grid);
1331    /// assert_eq!(next, Cell::new(7, 9));
1332    /// ```
1333    pub fn project_down(self, grid: Grid) -> Cell {
1334        self.saturating_down(grid, u8::MAX)
1335    }
1336
1337    /// Projects current `Cell` onto the left side of the given `Grid`
1338    ///
1339    /// This operation does not mutate current `Cell` fields,
1340    /// instead it calculates new position and returns new `Cell`
1341    ///
1342    /// # Panics
1343    /// Panics if the `Cell` is not within the given `Grid`
1344    ///
1345    /// # Examples
1346    ///
1347    /// ```
1348    /// use grid_math::{Cell, Grid};
1349    ///
1350    /// let grid = Grid::new(10, 10);
1351    /// let cell = Cell::new(2, 2);
1352    /// let next = cell.project_left(grid);
1353    /// assert_eq!(next, Cell::new(0, 2));
1354    /// ```
1355    pub fn project_left(self, grid: Grid) -> Cell {
1356        self.saturating_left(grid, u8::MAX)
1357    }
1358
1359    /// Projects current `Cell` onto the right side of the given `Grid`
1360    ///
1361    /// This operation does not mutate current `Cell` fields,
1362    /// instead it calculates new position and returns new `Cell`
1363    ///
1364    /// # Panics
1365    /// Panics if the `Cell` is not within the given `Grid`
1366    ///
1367    /// # Examples
1368    ///
1369    /// ```
1370    /// use grid_math::{Cell, Grid};
1371    ///
1372    /// let grid = Grid::new(10, 10);
1373    /// let cell = Cell::new(7, 7);
1374    /// let next = cell.project_right(grid);
1375    /// assert_eq!(next, Cell::new(9, 7));
1376    /// ```
1377    pub fn project_right(self, grid: Grid) -> Cell {
1378        self.saturating_right(grid, u8::MAX)
1379    }
1380
1381    /// Checks if the `Cell` is on the edge of the given `Grid`
1382    ///
1383    /// # Examples
1384    ///
1385    /// ```
1386    /// use grid_math::{Cell, Grid};
1387    ///
1388    /// let grid = Grid::new(10, 10);
1389    /// let cell = Cell::new(7, 9);
1390    /// assert!(cell.on_the_edge(grid));
1391    /// let cell = Cell::new(4, 3);
1392    /// assert!(!cell.on_the_edge(grid));
1393    /// ```
1394    pub fn on_the_edge(self, grid: Grid) -> bool {
1395        self.global_width == grid.start.global_width
1396            || self.global_width == grid.end.global_width
1397            || self.global_depth == grid.start.global_depth
1398            || self.global_depth == grid.end.global_depth
1399    }
1400}
1401
1402impl fmt::Display for Cell {
1403    /// implements display for `Cell`
1404    ///
1405    /// # Examples
1406    ///
1407    /// ```
1408    /// use grid_math::Cell;
1409    ///
1410    /// let cell = Cell::new(5, 6);
1411    /// assert_eq!(format!("{cell}"), "(5, 6)");
1412    /// ```
1413    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1414        write!(
1415            f,
1416            "({w}, {d})",
1417            w = self.global_width,
1418            d = self.global_depth
1419        )
1420    }
1421}
1422
1423impl From<(u8, u8)> for Cell {
1424    /// implements constructor for `Cell` from (u8, u8)
1425    ///
1426    /// # Examples
1427    ///
1428    /// ```
1429    /// use grid_math::Cell;
1430    ///
1431    /// let pos = (5, 6);
1432    /// let cell = Cell::from(pos);
1433    /// assert_eq!((pos.0, pos.1), (cell.global_width(), cell.global_depth()));
1434    /// ```
1435    fn from(value: (u8, u8)) -> Self {
1436        Self {
1437            global_width: value.0,
1438            global_depth: value.1,
1439        }
1440    }
1441}
1442
1443#[allow(clippy::from_over_into)]
1444impl Into<(u8, u8)> for Cell {
1445    /// implements conversion from `Cell` into (u8, u8)
1446    ///
1447    /// # Examples
1448    ///
1449    /// ```
1450    /// use grid_math::Cell;
1451    ///
1452    /// let cell = Cell::new(5, 6);
1453    /// let pos: (u8, u8) = cell.into();
1454    /// assert_eq!((pos.0, pos.1), (cell.global_width(), cell.global_depth()));
1455    /// ```
1456    fn into(self) -> (u8, u8) {
1457        (self.global_width, self.global_depth)
1458    }
1459}
1460
1461impl Grid {
1462    /// Creates new `Grid` with specified `width: u8` and `depth: u8`, starting at (0,0)
1463    ///
1464    /// # Panics
1465    /// Panics if `width` or `depth` parameters < 1
1466    ///
1467    /// # Examples
1468    ///
1469    /// ```
1470    /// use grid_math::Grid;
1471    ///
1472    /// let grid = Grid::new(10, 10);
1473    /// assert_eq!(format!("{grid}"), "[(0, 0):(9, 9)]");
1474    /// ```
1475    pub fn new(width: u8, depth: u8) -> Self {
1476        if width < 1 || depth < 1 {
1477            panic!("can't create grid with width < 0 or depth < 0!")
1478        }
1479        Self {
1480            start: Cell {
1481                global_width: 0,
1482                global_depth: 0,
1483            },
1484            end: Cell {
1485                global_width: width - 1,
1486                global_depth: depth - 1,
1487            },
1488        }
1489    }
1490
1491    /// Creates new `Grid` with specified `width: u8` and `depth: u8`, starting at indent
1492    ///
1493    /// # Panics
1494    /// Panics if `width` or `depth` parameters < 1
1495    ///
1496    /// # Examples
1497    ///
1498    /// ```
1499    /// use grid_math::{Grid, Cell};
1500    ///
1501    /// let grid = Grid::indented(5, 5, (2, 2));
1502    /// assert_eq!(format!("{grid}"), "[(2, 2):(6, 6)]");
1503    ///
1504    /// // use `Cell` as indent:
1505    /// let cell = Cell::new(2, 2);
1506    /// let grid = Grid::indented(5, 5, cell.into());
1507    /// assert_eq!(format!("{grid}"), "[(2, 2):(6, 6)]");
1508    /// ```
1509    pub fn indented(width: u8, depth: u8, indent: (u8, u8)) -> Self {
1510        if width < 1 || depth < 1 {
1511            panic!("can't create grid with width < 0 or depth < 0!")
1512        }
1513        Self {
1514            start: Cell {
1515                global_width: indent.0,
1516                global_depth: indent.1,
1517            },
1518            end: Cell {
1519                global_width: indent.0 + width - 1,
1520                global_depth: indent.1 + depth - 1,
1521            },
1522        }
1523    }
1524
1525    /// Checks if the `Grid` is within the another `Grid`
1526    ///
1527    /// # Examples
1528    ///
1529    /// ```
1530    /// use grid_math::Grid;
1531    ///
1532    /// let grid = Grid::new(10, 10);
1533    /// let subgrid = grid.area(5, 5);
1534    /// assert!(subgrid.within(grid));
1535    ///
1536    /// let subgrid = Grid::new(10, 12);
1537    /// assert!(!subgrid.within(grid));
1538    /// ```
1539    pub fn within(self, grid: Grid) -> bool {
1540        self.start.within(grid) && self.end.within(grid)
1541    }
1542
1543    /// Checks if the `Grid` is within the another `Grid`
1544    ///
1545    /// # Panics
1546    /// Panics if the `Grid` is not within the another `Grid`
1547    ///
1548    /// # Examples
1549    ///
1550    /// ```should_panic
1551    /// use grid_math::Grid;
1552    ///
1553    /// let grid = Grid::new(10, 10);
1554    /// let subgrid = Grid::new(10, 12);
1555    /// subgrid.within_panic(grid);
1556    /// ```
1557    pub fn within_panic(self, grid: Grid) {
1558        if !self.within(grid) {
1559            panic!("subgrid is not within given grid! subgrid:{self}, grid:{grid}")
1560        }
1561    }
1562
1563    /// Returns new `Cell` by `width: u8` and `depth: u8` relative to the current `Grid`
1564    ///
1565    /// # Panics
1566    /// Panics if `width` or `depth` of the requested member exceeds borders of the current `Grid`
1567    ///
1568    /// # Examples
1569    ///
1570    /// ```
1571    /// use grid_math::{Grid, Cell};
1572    ///
1573    /// let grid = Grid::indented(5, 5, (2, 2)); // 5x5 grid, starting at (2,2)
1574    /// let member = grid.member(4, 4);
1575    /// assert_eq!(member, Cell::new(6, 6));
1576    /// ```
1577    pub fn member(self, width: u8, depth: u8) -> Cell {
1578        self.start
1579            .strict_right(self, width)
1580            .strict_down(self, depth)
1581    }
1582
1583    /// Returns new `Grid` with `width: u8` and `depth: u8`, which is a subgrid
1584    /// of current `Grid`, starting at current `Grid` start
1585    ///
1586    /// # Panics
1587    /// Panics if `width` or `depth` parameters < 1
1588    /// Panics if `width` or `depth` of the requested area exceeds borders of the current `Grid`
1589    ///
1590    /// # Examples
1591    ///
1592    /// ```
1593    /// use grid_math::{Grid, Cell};
1594    ///
1595    /// let grid = Grid::indented(5, 5, (2, 2)); // 5x5 grid, starting at (2,2)
1596    /// let area = grid.area(3, 3);
1597    /// assert_eq!(format!("{area}"), "[(2, 2):(4, 4)]");
1598    /// ```
1599    pub fn area(self, width: u8, depth: u8) -> Grid {
1600        if width < 1 || depth < 1 {
1601            panic!("can't create grid with width < 0 or depth < 0!")
1602        }
1603        Grid {
1604            start: self.start,
1605            end: self
1606                .start
1607                .strict_right(self, width - 1)
1608                .strict_down(self, depth - 1),
1609        }
1610    }
1611
1612    /// Returns new `Grid` with `width: u8` and `depth: u8`, which is a subgrid
1613    /// of current `Grid`, starting at current `Grid` start + indent
1614    ///
1615    /// # Panics
1616    /// Panics if `width` or `depth` parameters < 1
1617    /// Panics if `width` or `depth` of the requested slice exceeds borders of the current `Grid`
1618    /// Panics if `indent` of the requested slice exceeds borders of the current `Grid`
1619    ///
1620    /// # Examples
1621    ///
1622    /// ```
1623    /// use grid_math::{Grid, Cell};
1624    ///
1625    /// let grid = Grid::new(10, 10);
1626    /// let slice = grid.slice(3, 3, (2, 2));
1627    /// assert_eq!(format!("{slice}"), "[(2, 2):(4, 4)]");
1628    ///
1629    /// // use `Cell` as indent:
1630    /// let cell = Cell::new(2, 2);
1631    /// let slice = grid.slice(3, 3, cell.into());
1632    /// assert_eq!(format!("{slice}"), "[(2, 2):(4, 4)]");
1633    /// ```
1634    pub fn slice(self, width: u8, depth: u8, indent: (u8, u8)) -> Grid {
1635        if width < 1 || depth < 1 {
1636            panic!("can't create grid with width < 0 or depth < 0!")
1637        }
1638        Grid {
1639            start: self
1640                .start
1641                .strict_right(self, indent.0)
1642                .strict_down(self, indent.1),
1643            end: self
1644                .start
1645                .strict_right(self, indent.0 + width - 1)
1646                .strict_down(self, indent.1 + depth - 1),
1647        }
1648    }
1649
1650    /// Returns `start` cell of `Grid`
1651    ///
1652    /// # Examples
1653    ///
1654    /// ```
1655    /// use grid_math::{Grid, Cell};
1656    ///
1657    /// let grid = Grid::new(10, 10);
1658    /// let start = grid.start();
1659    /// assert_eq!(start, Cell::new(0, 0));
1660    /// ```
1661    pub fn start(self) -> Cell {
1662        self.start
1663    }
1664
1665    /// Returns `end` cell of `Grid`
1666    ///
1667    /// # Examples
1668    ///
1669    /// ```
1670    /// use grid_math::{Grid, Cell};
1671    ///
1672    /// let grid = Grid::new(10, 10);
1673    /// let end = grid.end();
1674    /// assert_eq!(end, Cell::new(9, 9));
1675    /// ```
1676    pub fn end(self) -> Cell {
1677        self.end
1678    }
1679
1680    /// Calculates `width` of `Grid`
1681    ///
1682    /// # Examples
1683    ///
1684    /// ```
1685    /// use grid_math::Grid;
1686    ///
1687    /// let grid = Grid::new(10, 10);
1688    /// let width = grid.width();
1689    /// assert_eq!(width, 10);
1690    /// ```
1691    pub fn width(self) -> u8 {
1692        self.end.global_width - self.start.global_width + 1
1693    }
1694
1695    /// Calculates `depth` of `Grid`
1696    ///
1697    /// # Examples
1698    ///
1699    /// ```
1700    /// use grid_math::Grid;
1701    ///
1702    /// let grid = Grid::new(10, 10);
1703    /// let depth = grid.depth();
1704    /// assert_eq!(depth, 10);
1705    /// ```
1706    pub fn depth(self) -> u8 {
1707        self.end.global_depth - self.start.global_depth + 1
1708    }
1709
1710    /// Calculates `size: u16` of `Grid`
1711    ///
1712    /// # Examples
1713    ///
1714    /// ```
1715    /// use grid_math::Grid;
1716    ///
1717    /// let grid = Grid::new(10, 10);
1718    /// let size = grid.size();
1719    /// assert_eq!(size, 100);
1720    /// ```
1721    pub fn size(self) -> u16 {
1722        self.width() as u16 * self.depth() as u16
1723    }
1724
1725    /// Returns `Cells`, which is an iterator over every cell of the `Grid`
1726    ///
1727    /// # Examples
1728    ///
1729    /// Get every `Cell` on `width` and `depth` axis:
1730    /// ```
1731    /// use grid_math::{Cell, Grid};
1732    ///
1733    /// let grid = Grid::new(3, 3);
1734    ///
1735    /// let axis_cells: Vec<Cell> = grid
1736    ///     .cells()
1737    ///     .filter(|cell| {
1738    ///         cell.global_width() == grid.start().global_width() || cell.global_depth() == grid.start().global_depth()
1739    ///     })
1740    ///     .collect();
1741    /// assert_eq!(axis_cells, vec![
1742    ///     Cell::new(0, 0),
1743    ///     Cell::new(1, 0),
1744    ///     Cell::new(2, 0),
1745    ///     Cell::new(0, 1),
1746    ///     Cell::new(0, 2),
1747    /// ]);
1748    /// ```
1749    pub fn cells(self) -> Cells {
1750        Cells::from(self)
1751    }
1752
1753    /// Returns `Rows`, which is an iterator over every row of the `Grid`
1754    ///
1755    /// # Examples
1756    ///
1757    /// Print out `Grid` in custom format:
1758    /// ```
1759    /// use grid_math::{Cell, Grid};
1760    ///
1761    /// let grid = Grid::new(3, 3);
1762    /// let grid_string = grid
1763    ///     .rows()
1764    ///     .map(|row| {
1765    ///         row.cells().map(|_| " [#]")
1766    ///             .chain(std::iter::once("\n\n"))
1767    ///             .collect::<String>()
1768    ///     })
1769    ///     .collect::<String>();
1770    /// assert_eq!(grid_string,
1771    /// " \
1772    ///  [#] [#] [#]
1773    ///
1774    ///  [#] [#] [#]
1775    ///
1776    ///  [#] [#] [#]
1777    ///
1778    /// "
1779    /// );
1780    /// ```
1781    pub fn rows(self) -> Rows {
1782        Rows::from(self)
1783    }
1784
1785    /// Returns `Columns`, which is an iterator over every column of the `Grid`
1786    ///
1787    /// # Examples
1788    ///
1789    /// Get every `Cell` on the first column of `Grid`:
1790    /// ```
1791    /// use grid_math::{Cell, Grid};
1792    ///
1793    /// let grid = Grid::new(3, 3);
1794    ///
1795    /// let first_column_cells: Vec<Cell> = grid
1796    ///     .columns()
1797    ///     .next()
1798    ///     .unwrap()
1799    ///     .cells()
1800    ///     .collect();
1801    ///
1802    /// assert_eq!(first_column_cells, vec![
1803    ///     Cell::new(0, 0),
1804    ///     Cell::new(0, 1),
1805    ///     Cell::new(0, 2),
1806    /// ]);
1807    /// ```
1808    pub fn columns(self) -> Columns {
1809        Columns::from(self)
1810    }
1811}
1812
1813impl From<(Cell, Cell)> for Grid {
1814    /// implements constructor for `Grid` from (Cell, Cell)
1815    ///
1816    /// # Examples
1817    ///
1818    /// ```
1819    /// use grid_math::{Cell, Grid};
1820    ///
1821    /// let cells = (Cell::new(2, 2), Cell::new(5, 5));
1822    /// let grid = Grid::from(cells);
1823    /// assert_eq!((cells.0, cells.1), (grid.start(), grid.end()));
1824    /// ```
1825    fn from(value: (Cell, Cell)) -> Self {
1826        let (start, end) = value;
1827        if start.global_width > end.global_width || start.global_depth > end.global_depth {
1828            panic!("start cell overflows end cell! start:{start}, end:{end}")
1829        }
1830        Self { start, end }
1831    }
1832}
1833
1834#[allow(clippy::from_over_into)]
1835impl Into<(Cell, Cell)> for Grid {
1836    /// implements conversion from `Grid` into (Cell, Cell)
1837    ///
1838    /// # Examples
1839    ///
1840    /// ```
1841    /// use grid_math::{Cell, Grid};
1842    ///
1843    /// let grid = Grid::new(5, 5);
1844    /// let cells: (Cell, Cell) = grid.into();
1845    /// assert_eq!((cells.0, cells.1), (grid.start(), grid.end()));
1846    /// ```
1847    fn into(self) -> (Cell, Cell) {
1848        (self.start, self.end)
1849    }
1850}
1851
1852impl From<((u8, u8), (u8, u8))> for Grid {
1853    /// implements constructor for `Grid` from ((u8, u8), (u8, u8))
1854    ///
1855    /// # Examples
1856    ///
1857    /// ```
1858    /// use grid_math::{Cell, Grid};
1859    ///
1860    /// let vals = ((2, 2), (5, 5));
1861    /// let grid = Grid::from(vals);
1862    /// assert_eq!((Cell::from(vals.0), Cell::from(vals.1)), (grid.start(), grid.end()));
1863    /// ```
1864    fn from(value: ((u8, u8), (u8, u8))) -> Self {
1865        let (start, end): (Cell, Cell) = (value.0.into(), value.1.into());
1866        if start.global_width > end.global_width || start.global_depth > end.global_depth {
1867            panic!("start cell overflows end cell! start:{start}, end:{end}")
1868        }
1869        Self { start, end }
1870    }
1871}
1872
1873#[allow(clippy::from_over_into)]
1874impl Into<((u8, u8), (u8, u8))> for Grid {
1875    /// implements conversion from `Grid` into ((u8, u8), (u8, u8))
1876    ///
1877    /// # Examples
1878    ///
1879    /// ```
1880    /// use grid_math::{Cell, Grid};
1881    ///
1882    /// let grid = Grid::new(5, 5);
1883    /// let vals: ((u8, u8), (u8, u8)) = grid.into();
1884    /// assert_eq!((Cell::from(vals.0), Cell::from(vals.1)), (grid.start(), grid.end()));
1885    /// ```
1886    fn into(self) -> ((u8, u8), (u8, u8)) {
1887        (self.start.into(), self.end.into())
1888    }
1889}
1890
1891impl fmt::Display for Grid {
1892    /// implements display for `Grid`
1893    ///
1894    /// # Examples
1895    ///
1896    /// ```
1897    /// use grid_math::Grid;
1898    ///
1899    /// let grid = Grid::new(5, 6);
1900    /// assert_eq!(format!("{grid}"), "[(0, 0):(4, 5)]");
1901    /// ```
1902    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1903        write!(f, "[{start}:{end}]", start = self.start, end = self.end)
1904    }
1905}
1906
1907impl From<Grid> for Cells {
1908    /// Creates new iterator over every `Cell` on the `Grid`
1909    ///
1910    /// # Examples:
1911    ///
1912    /// ```
1913    /// use grid_math::{Grid, Cells};
1914    ///
1915    /// let grid = Grid::new(5, 5);
1916    /// let cells = Cells::from(grid);
1917    /// ```
1918    fn from(grid: Grid) -> Self {
1919        Self {
1920            grid,
1921            current: grid.start,
1922            consumed: false,
1923        }
1924    }
1925}
1926
1927impl From<Grid> for Columns {
1928    /// Creates new iterator over every column on the `Grid`
1929    ///
1930    /// # Examples:
1931    ///
1932    /// ```
1933    /// use grid_math::{Grid, Columns};
1934    ///
1935    /// let grid = Grid::new(5, 5);
1936    /// let columns = Columns::from(grid);
1937    /// ```
1938    fn from(grid: Grid) -> Self {
1939        Self {
1940            grid,
1941            current: Grid {
1942                start: grid.start,
1943                end: grid.start.project_down(grid),
1944            },
1945            consumed: false,
1946        }
1947    }
1948}
1949
1950impl From<Grid> for Rows {
1951    /// Creates new iterator over every row on the `Grid`
1952    ///
1953    /// # Examples:
1954    ///
1955    /// ```
1956    /// use grid_math::{Grid, Rows};
1957    ///
1958    /// let grid = Grid::new(5, 5);
1959    /// let rows = Rows::from(grid);
1960    /// ```
1961    fn from(grid: Grid) -> Self {
1962        Self {
1963            grid,
1964            current: Grid {
1965                start: grid.start,
1966                end: grid.start.project_right(grid),
1967            },
1968            consumed: false,
1969        }
1970    }
1971}
1972
1973impl Iterator for Cells {
1974    type Item = Cell;
1975    fn next(&mut self) -> Option<Self::Item> {
1976        if self.consumed {
1977            return None;
1978        }
1979        if self.current == self.grid.end {
1980            self.consumed = true;
1981            return Some(self.current);
1982        }
1983        let previous = self.current;
1984        match self.current.overflowing_right(self.grid, 1) {
1985            (next, true) => self.current = next.wrapping_down(self.grid, 1),
1986            (next, false) => self.current = next,
1987        }
1988        Some(previous)
1989    }
1990}
1991
1992impl Iterator for Columns {
1993    type Item = Grid;
1994    fn next(&mut self) -> Option<Self::Item> {
1995        if self.consumed {
1996            return None;
1997        }
1998        if self.current.end == self.grid.end {
1999            self.consumed = true;
2000            return Some(self.current);
2001        }
2002        let previous = self.current;
2003        self.current = Grid {
2004            start: self.current.start.saturating_right(self.grid, 1),
2005            end: self.current.end.saturating_right(self.grid, 1),
2006        };
2007        Some(previous)
2008    }
2009}
2010
2011impl Iterator for Rows {
2012    type Item = Grid;
2013    fn next(&mut self) -> Option<Self::Item> {
2014        if self.consumed {
2015            return None;
2016        }
2017        if self.current.end == self.grid.end {
2018            self.consumed = true;
2019            return Some(self.current);
2020        }
2021        let previous = self.current;
2022        self.current = Grid {
2023            start: self.current.start.saturating_down(self.grid, 1),
2024            end: self.current.end.saturating_down(self.grid, 1),
2025        };
2026        Some(previous)
2027    }
2028}
2029
2030impl<V> From<Grid> for GridMap<V> {
2031    /// Creates new `GridMap` from the given `Grid` with empty `HashMap<Cell, V>`
2032    ///
2033    /// # Examples:
2034    ///
2035    /// ```
2036    /// use grid_math::{Grid, GridMap};
2037    ///
2038    /// let grid = Grid::new(5, 5);
2039    /// let map: GridMap<char> = GridMap::from(grid);
2040    /// ```
2041    fn from(grid: Grid) -> Self {
2042        Self {
2043            grid,
2044            hashmap: HashMap::new(),
2045        }
2046    }
2047}
2048
2049impl<V> From<(Grid, HashMap<Cell, V>)> for GridMap<V> {
2050    /// Creates new `GridMap` from the existing `HashMap<Cell, V>` and the given `Grid`
2051    ///
2052    /// # Panics
2053    /// Panics if the given `HashMap<Cell, V>` contains `Cell`s that are not within the given `Grid`
2054    ///
2055    /// # Examples:
2056    ///
2057    /// ```
2058    /// use grid_math::{Cell, Grid, GridMap};
2059    /// use std::collections::HashMap;
2060    ///
2061    /// let grid = Grid::new(5, 5);
2062    /// let mut hashmap: HashMap<Cell, char> = HashMap::new();
2063    /// let target = Cell::new(1, 2);
2064    /// hashmap.insert(target, '#');
2065    /// let map: GridMap<char> = GridMap::from((grid, hashmap));
2066    /// assert_eq!(map.get(&target), Some(&'#'));
2067    /// ```
2068    ///
2069    /// ```should_panic
2070    /// use grid_math::{Cell, Grid, GridMap};
2071    /// use std::collections::HashMap;
2072    ///
2073    /// let grid = Grid::new(5, 5);
2074    /// let mut hashmap: HashMap<Cell, char> = HashMap::new();
2075    /// let target = Cell::new(6, 2);
2076    /// hashmap.insert(target, '#');
2077    /// let map: GridMap<char> = GridMap::from((grid, hashmap)); // panic!
2078    /// ```
2079    fn from(data: (Grid, HashMap<Cell, V>)) -> Self {
2080        data.1.keys().for_each(|cell| cell.within_panic(data.0));
2081        Self {
2082            grid: data.0,
2083            hashmap: data.1,
2084        }
2085    }
2086}
2087
2088impl<V> GridMap<V> {
2089    /// Creates new `GridMap` with `Grid` of specified sizes, and with empty `HashMap<Cell, V>`
2090    ///
2091    /// # Examples:
2092    ///
2093    /// ```
2094    /// use grid_math::{Grid, GridMap};
2095    ///
2096    /// let map: GridMap<char> = GridMap::new(5, 5);
2097    ///
2098    /// assert_eq!(map.grid(), Grid::new(5, 5));
2099    /// ```
2100    pub fn new(width: u8, depth: u8) -> Self {
2101        Self {
2102            grid: Grid::new(width, depth),
2103            hashmap: HashMap::new(),
2104        }
2105    }
2106
2107    /// Shadows `insert` method from the `HashMap`, and reimplements it
2108    /// so it checks first if the key (`Cell`) is within the `Grid`, and then inserts it into the `HashMap`.
2109    /// This method currently has bad error handling, but this may change in the future
2110    ///
2111    /// # Panics
2112    /// Panics, if the key (`Cell`) is not within the inner `Grid`
2113    ///
2114    /// # Examples:
2115    ///
2116    /// ```
2117    /// use grid_math::{Grid, GridMap};
2118    ///
2119    /// let grid = Grid::new(5, 5);
2120    /// let mut map: GridMap<char> = GridMap::from(grid);
2121    /// map.insert(map.grid().start(), '#');
2122    /// map.insert(map.grid().end(), '@');
2123    /// assert_eq!(map.len(), 2);
2124    /// ```
2125    ///
2126    /// ```should_panic
2127    /// use grid_math::{Cell, Grid, GridMap};
2128    ///
2129    /// let grid = Grid::new(5, 5);
2130    /// let cell = Cell::new(6, 6);
2131    /// let mut map: GridMap<char> = GridMap::from(grid);
2132    /// map.insert(cell, '#'); // panic!
2133    /// ```
2134    pub fn insert(&mut self, cell: Cell, value: V) -> Option<V> {
2135        cell.within_panic(self.grid);
2136        self.hashmap.insert(cell, value)
2137    }
2138
2139    /// Returns the inner `Grid`
2140    ///
2141    /// # Examples:
2142    ///
2143    /// ```
2144    /// use grid_math::{Grid, GridMap};
2145    ///
2146    /// let grid = Grid::new(5, 5);
2147    /// let map: GridMap<char> = GridMap::from(grid);
2148    ///
2149    /// assert_eq!(grid, map.grid());
2150    /// ```
2151    pub fn grid(&self) -> Grid {
2152        self.grid
2153    }
2154
2155    /// Checks if the `Cell` is occupied. This is an alias for `contains_key` method
2156    ///
2157    /// # Panics
2158    /// Panics, if the given `Cell` is not within the inner `Grid`
2159    ///
2160    /// # Examples:
2161    ///
2162    /// ```
2163    /// use grid_math::{Cell, Grid, GridMap};
2164    ///
2165    /// let grid = Grid::new(5, 5);
2166    /// let cell = Cell::new(2, 3);
2167    /// let mut map: GridMap<char> = GridMap::from(grid);
2168    /// map.insert(cell, '#');
2169    ///
2170    /// assert!(map.occupied(cell));
2171    /// assert!(!map.occupied(map.grid().start()));
2172    /// ```
2173    pub fn occupied(&self, cell: Cell) -> bool {
2174        cell.within_panic(self.grid);
2175        self.contains_key(&cell)
2176    }
2177
2178    /// Checks if the `Cell` is free
2179    ///
2180    /// # Panics
2181    /// Panics, if the given `Cell` is not within the inner `Grid`
2182    ///
2183    /// # Examples:
2184    ///
2185    /// ```
2186    /// use grid_math::{Cell, Grid, GridMap};
2187    ///
2188    /// let grid = Grid::new(5, 5);
2189    /// let cell = Cell::new(2, 3);
2190    /// let mut map: GridMap<char> = GridMap::from(grid);
2191    /// map.insert(cell, '#');
2192    ///
2193    /// assert!(!map.vacant(cell));
2194    /// assert!(map.vacant(map.grid().start()));
2195    /// ```
2196    pub fn vacant(&self, cell: Cell) -> bool {
2197        cell.within_panic(self.grid);
2198        !self.contains_key(&cell)
2199    }
2200
2201    /// Returns count of occupied `Cell`s
2202    ///
2203    /// # Examples:
2204    ///
2205    /// ```
2206    /// use grid_math::{Cell, Grid, GridMap};
2207    ///
2208    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2209    /// map.insert(Cell::new(2, 3), '#');
2210    /// map.insert(Cell::new(4, 1), '@');
2211    ///
2212    /// assert_eq!(map.occupied_count(), 2);
2213    /// ```
2214    pub fn occupied_count(&self) -> u16 {
2215        self.len() as u16
2216    }
2217
2218    /// Returns count of vacant `Cell`s
2219    ///
2220    /// # Examples:
2221    ///
2222    /// ```
2223    /// use grid_math::{Cell, Grid, GridMap};
2224    ///
2225    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2226    /// map.insert(Cell::new(2, 3), '#');
2227    /// map.insert(Cell::new(4, 1), '@');
2228    ///
2229    /// assert_eq!(map.vacant_count(), 23);
2230    /// ```
2231    pub fn vacant_count(&self) -> u16 {
2232        self.grid.size() - self.occupied_count()
2233    }
2234
2235    /// Returns an iterator over every occupied `Cell`
2236    ///
2237    /// # Examples:
2238    ///
2239    /// ```
2240    /// use grid_math::{Cell, Grid, GridMap};
2241    ///
2242    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2243    /// map.insert(Cell::new(2, 3), '#');
2244    /// map.insert(Cell::new(4, 1), '@');
2245    ///
2246    /// assert_eq!(map.all_occupied().count(), 2);
2247    /// ```
2248    pub fn all_occupied(&self) -> Filter<Cells, impl FnMut(&Cell) -> bool> {
2249        self.grid.cells().filter(|&cell| self.occupied(cell))
2250    }
2251
2252    /// Returns an iterator over every vacant `Cell`
2253    ///
2254    /// # Examples:
2255    ///
2256    /// ```
2257    /// use grid_math::{Cell, Grid, GridMap};
2258    ///
2259    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2260    /// map.insert(Cell::new(2, 3), '#');
2261    /// map.insert(Cell::new(4, 1), '@');
2262    ///
2263    /// assert_eq!(map.all_vacant().count(), 23);
2264    /// ```
2265    pub fn all_vacant(&self) -> Filter<Cells, impl FnMut(&Cell) -> bool> {
2266        self.grid.cells().filter(|&cell| self.vacant(cell))
2267    }
2268
2269    /// Returns first occupied `Cell`
2270    ///
2271    /// # Note
2272    /// This returns first `Cell` in `Grid` order, so (2, 3) will go after (4, 1)
2273    ///
2274    /// # Examples:
2275    ///
2276    /// ```
2277    /// use grid_math::{Cell, Grid, GridMap};
2278    ///
2279    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2280    /// map.insert(Cell::new(2, 3), '#');
2281    /// map.insert(Cell::new(4, 1), '@');
2282    ///
2283    /// assert_eq!(map.first_occupied(), Some(Cell::new(4, 1)));
2284    /// ```
2285    pub fn first_occupied(&self) -> Option<Cell> {
2286        self.all_occupied().next()
2287    }
2288
2289    /// Returns first vacant `Cell`
2290    ///
2291    /// # Note
2292    /// This returns first `Cell` in `Grid` order
2293    ///
2294    /// # Examples:
2295    ///
2296    /// ```
2297    /// use grid_math::{Cell, Grid, GridMap};
2298    ///
2299    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2300    /// map.insert(Cell::new(2, 3), '#');
2301    /// map.insert(Cell::new(4, 1), '@');
2302    ///
2303    /// assert_eq!(map.first_vacant(), Some(Cell::new(0, 0)));
2304    /// ```
2305    pub fn first_vacant(&self) -> Option<Cell> {
2306        self.all_vacant().next()
2307    }
2308
2309    /// Returns random occupied `Cell`
2310    ///
2311    /// # Examples:
2312    ///
2313    /// ```
2314    /// use grid_math::{Cell, Grid, GridMap};
2315    ///
2316    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2317    /// map.insert(Cell::new(2, 3), '#');
2318    /// map.insert(Cell::new(4, 1), '@');
2319    ///
2320    /// assert_ne!(map.get(&map.random_occupied().unwrap()), None);
2321    /// assert_ne!(map.get(&map.random_occupied().unwrap()), None);
2322    /// assert_ne!(map.get(&map.random_occupied().unwrap()), None);
2323    /// ```
2324    pub fn random_occupied(&self) -> Option<Cell> {
2325        self.all_occupied().choose(&mut rand::rng())
2326    }
2327
2328    /// Returns random vacant `Cell`
2329    ///
2330    /// # Examples:
2331    ///
2332    /// ```
2333    /// use grid_math::{Cell, Grid, GridMap};
2334    ///
2335    /// let mut map: GridMap<char> = GridMap::new(5, 5);
2336    /// map.insert(Cell::new(2, 3), '#');
2337    /// map.insert(Cell::new(4, 1), '@');
2338    ///
2339    /// assert_eq!(map.get(&map.random_vacant().unwrap()), None);
2340    /// assert_eq!(map.get(&map.random_vacant().unwrap()), None);
2341    /// assert_eq!(map.get(&map.random_vacant().unwrap()), None);
2342    /// ```
2343    pub fn random_vacant(&self) -> Option<Cell> {
2344        self.all_vacant().choose(&mut rand::rng())
2345    }
2346}
2347
2348/// Implements `Deref` trait for GridMap, to return ref to the inner `HashMap`,
2349/// so we can call methods from `HashMap` directly on the `GridMap`
2350///
2351/// # Examples:
2352///
2353/// ```
2354/// use grid_math::{Grid, GridMap};
2355///
2356/// let grid = Grid::new(5, 5);
2357/// let mut map: GridMap<char> = GridMap::from(grid);
2358/// map.insert(map.grid().start(), '#');
2359///
2360/// assert_eq!(map.len(), 1);
2361/// ```
2362impl<V> Deref for GridMap<V> {
2363    type Target = HashMap<Cell, V>;
2364    fn deref(&self) -> &Self::Target {
2365        &self.hashmap
2366    }
2367}
2368
2369/// Implements `DerefMut` trait for GridMap, to return mut ref to the inner `HashMap`,
2370/// so we can call methods from `HashMap` directly on the `GridMap`
2371///
2372/// # Examples:
2373///
2374/// ```
2375/// use grid_math::{Grid, GridMap};
2376///
2377/// let grid = Grid::new(5, 5);
2378/// let mut map: GridMap<char> = GridMap::from(grid);
2379/// map.insert(map.grid().start(), '#');
2380///
2381/// assert_eq!(map.len(), 1);
2382/// ```
2383impl<V> DerefMut for GridMap<V> {
2384    fn deref_mut(&mut self) -> &mut Self::Target {
2385        &mut self.hashmap
2386    }
2387}
2388
2389// 🦀!⭐!!!