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