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