grid_math/
lib.rs

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