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