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<T>`] type, representing a wrapper around the [`HashMap<Cell, T>`]
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 may change in the future.
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, T>`
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`. Also It reimplements `insert` method and adds aditional conditions
466/// to check if the target `key: Cell` is within the inner `Grid` bounds.
467///
468/// `GridMap` currently has rather stupid error handling inside the `insert` method, but this may change in the future
469///
470/// # Examples
471///
472/// ```
473/// use grid_math::{Cell, Grid, GridMap};
474///
475/// let grid = Grid::new(5, 5);
476/// let mut map: GridMap<char> = GridMap::from(grid);
477/// map.insert(map.grid().start(), '#');
478/// map.insert(map.grid().end(), '@');
479/// assert_eq!(map.len(), 2);
480/// assert_eq!(map.get(&Cell::new(0, 0)).unwrap(), &'#');
481/// ```
482///
483/// ```should_panic
484/// use grid_math::{Cell, Grid, GridMap};
485///
486/// let grid = Grid::new(5, 5);
487/// let cell = Cell::new(6, 6);
488/// let mut map: GridMap<char> = GridMap::from(grid);
489/// map.insert(cell, '#'); // panic!
490/// ```
491#[derive(Debug, Clone)]
492pub struct GridMap<V> {
493 grid: Grid,
494 hashmap: HashMap<Cell, V>,
495}
496
497impl Cell {
498 /// Creates new `Cell` with specified `global_width: u8` and `global_depth: u8` global position
499 ///
500 /// # Examples
501 ///
502 /// ```
503 /// use grid_math::Cell;
504 ///
505 /// let cell = Cell::new(10, 15);
506 /// ```
507 pub fn new(global_width: u8, global_depth: u8) -> Self {
508 Self {
509 global_width,
510 global_depth,
511 }
512 }
513
514 /// Checks if the `Cell` is within the given `Grid`
515 ///
516 /// # Examples
517 ///
518 /// ```
519 /// use grid_math::{Cell, Grid};
520 ///
521 /// let grid = Grid::new(10, 10);
522 /// let cell = Cell::new(5, 5);
523 /// assert!(cell.within(grid));
524 ///
525 /// let cell = Cell::new(9, 15);
526 /// assert!(!cell.within(grid));
527 /// ```
528 pub fn within(self, grid: Grid) -> bool {
529 (grid.start.global_width..=grid.end.global_width).contains(&self.global_width)
530 && (grid.start.global_depth..=grid.end.global_depth).contains(&self.global_depth)
531 }
532
533 /// Checks if the `Cell` is within the given `Grid`
534 ///
535 /// # Panics
536 /// Panics if the `Cell` is not within the given `Grid`
537 ///
538 /// # Examples
539 ///
540 /// ```should_panic
541 /// use grid_math::{Cell, Grid};
542 ///
543 /// let grid = Grid::new(10, 10);
544 /// let cell = Cell::new(9, 15);
545 /// cell.within_panic(grid);
546 /// ```
547 pub fn within_panic(self, grid: Grid) {
548 if !self.within(grid) {
549 panic!("cell is not within given grid! cell:{self}, grid:{grid}")
550 }
551 }
552
553 /// Returns `global_width` field of `Cell`
554 ///
555 /// # Examples
556 ///
557 /// ```
558 /// use grid_math::Cell;
559 ///
560 /// let cell = Cell::new(8, 8);
561 /// let w = cell.global_width();
562 /// assert_eq!(w, 8);
563 /// ```
564 pub fn global_width(self) -> u8 {
565 self.global_width
566 }
567
568 /// Returns `global_depth` field of `Cell`
569 ///
570 /// # Examples
571 ///
572 /// ```
573 /// use grid_math::Cell;
574 ///
575 /// let cell = Cell::new(8, 8);
576 /// let d = cell.global_depth();
577 /// assert_eq!(d, 8);
578 /// ```
579 pub fn global_depth(self) -> u8 {
580 self.global_depth
581 }
582
583 /// Calculates the `width` of the `Cell` relative to the given `Grid`
584 /// `width` here means position / index / x of `Cell` on width axis
585 ///
586 /// # Panics
587 /// Panics if the `Cell` is not within the given `Grid`
588 ///
589 /// # Examples
590 ///
591 /// ```
592 /// use grid_math::{Cell, Grid};
593 ///
594 /// let cell = Cell::new(8, 8);
595 /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
596 /// let width = cell.width(grid); // width = 4
597 /// assert_eq!(width, 4);
598 /// ```
599 pub fn width(self, grid: Grid) -> u8 {
600 self.within_panic(grid);
601 self.global_width - grid.start.global_width
602 }
603
604 /// Calculates the gap between the `width` of `Cell` and the `width` of `Grid`
605 ///
606 /// # Panics
607 /// Panics if the `Cell` is not within the given `Grid`
608 ///
609 /// # Examples
610 ///
611 /// ```
612 /// use grid_math::{Cell, Grid};
613 ///
614 /// let cell = Cell::new(8, 8);
615 /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
616 /// let width_gap = cell.width_gap(grid); // width_gap = 2
617 /// assert_eq!(width_gap, 2);
618 /// ```
619 pub fn width_gap(self, grid: Grid) -> u8 {
620 self.within_panic(grid);
621 grid.end.global_width - self.global_width
622 }
623
624 /// Calculates the `depth` of `Cell` relative to the given `Grid`
625 /// `depth` here means position / index / y of `Cell` on depth axis
626 ///
627 /// # Panics
628 /// Panics if the `Cell` is not within the given `Grid`
629 ///
630 /// # Examples
631 ///
632 /// ```
633 /// use grid_math::{Cell, Grid};
634 ///
635 /// let cell = Cell::new(8, 8);
636 /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
637 /// let depth = cell.depth(grid); // depth = 4
638 /// assert_eq!(depth, 4);
639 /// ```
640 pub fn depth(self, grid: Grid) -> u8 {
641 self.within_panic(grid);
642 self.global_depth - grid.start.global_depth
643 }
644
645 /// Calculates the gap between the `depth` of `Cell` and the `depth` of `Grid`
646 ///
647 /// # Panics
648 /// Panics if the `Cell` is not within the given `Grid`
649 ///
650 /// # Examples
651 ///
652 /// ```
653 /// use grid_math::{Cell, Grid};
654 ///
655 /// let cell = Cell::new(8, 8);
656 /// let grid = Grid::indented(7, 7, (4, 4)); // 7x7 grid starting at (4,4)
657 /// let depth_gap = cell.depth_gap(grid); // depth_gap = 2
658 /// assert_eq!(depth_gap, 2);
659 /// ```
660 pub fn depth_gap(self, grid: Grid) -> u8 {
661 self.within_panic(grid);
662 grid.end.global_depth - self.global_depth
663 }
664
665 /// Checks if the `up` operation on `Cell` will violate the given `Grid` upper border
666 ///
667 /// # Panics
668 /// Panics if the `Cell` is not within the given `Grid`
669 ///
670 /// # Examples
671 ///
672 /// ```
673 /// use grid_math::{Cell, Grid};
674 ///
675 /// let grid = Grid::new(10, 10);
676 /// let cell = Cell::new(2, 2);
677 /// assert!(cell.will_underflow_depth(grid, 3));
678 /// assert!(!cell.will_underflow_depth(grid, 2));
679 /// ```
680 pub fn will_underflow_depth(self, grid: Grid, step: u8) -> bool {
681 self.within_panic(grid);
682 self.global_depth < step || self.global_depth - step < grid.start.global_depth
683 }
684
685 /// Checks if the `down` operation on `Cell` will violate the given `Grid` lower border
686 ///
687 /// # Panics
688 /// Panics if the `Cell` is not within the given `Grid`
689 ///
690 /// # Examples
691 ///
692 /// ```
693 /// use grid_math::{Cell, Grid};
694 ///
695 /// let grid = Grid::new(10, 10);
696 /// let cell = Cell::new(7, 7);
697 /// assert!(cell.will_overflow_depth(grid, 3));
698 /// assert!(!cell.will_overflow_depth(grid, 2));
699 /// ```
700 pub fn will_overflow_depth(self, grid: Grid, step: u8) -> bool {
701 self.within_panic(grid);
702 self.global_depth > u8::MAX - step || self.global_depth + step > grid.end.global_depth
703 }
704
705 /// Checks if the `left` operation on `Cell` will violate the given `Grid` left border
706 ///
707 /// # Panics
708 /// Panics if the `Cell` is not within the given `Grid`
709 ///
710 /// # Examples
711 ///
712 /// ```
713 /// use grid_math::{Cell, Grid};
714 ///
715 /// let grid = Grid::new(10, 10);
716 /// let cell = Cell::new(2, 2);
717 /// assert!(cell.will_underflow_width(grid, 3));
718 /// assert!(!cell.will_underflow_width(grid, 2));
719 /// ```
720 pub fn will_underflow_width(self, grid: Grid, step: u8) -> bool {
721 self.within_panic(grid);
722 self.global_width < step || self.global_width - step < grid.start.global_width
723 }
724
725 /// Checks if the `right` operation on `Cell` will violate the given `Grid` right border
726 ///
727 /// # Panics
728 /// Panics if the `Cell` is not within the given `Grid`
729 ///
730 /// # Examples
731 ///
732 /// ```
733 /// use grid_math::{Cell, Grid};
734 ///
735 /// let grid = Grid::new(10, 10);
736 /// let cell = Cell::new(7, 7);
737 /// assert!(cell.will_overflow_width(grid, 3));
738 /// assert!(!cell.will_overflow_width(grid, 2));
739 /// ```
740 pub fn will_overflow_width(self, grid: Grid, step: u8) -> bool {
741 self.within_panic(grid);
742 self.global_width > u8::MAX - step || self.global_width + step > grid.end.global_width
743 }
744
745 /// Moves current `Cell` upwards by `step` relative to the given `Grid`
746 /// This operation does not mutate current `Cell` fields,
747 /// instead it calculates new position and returns new `Cell`
748 ///
749 /// # Panics
750 /// Panics if the `Cell` is not within the given `Grid`
751 /// Panics if this operation will violate the given `Grid` upper border
752 ///
753 /// # Examples
754 ///
755 /// ```
756 /// use grid_math::{Cell, Grid};
757 ///
758 /// let grid = Grid::new(10, 10);
759 /// let cell = Cell::new(2, 2);
760 /// let next = cell.strict_up(grid, 2);
761 /// assert_eq!(next, Cell::new(2, 0));
762 /// ```
763 ///
764 /// ```should_panic
765 /// use grid_math::{Cell, Grid};
766 ///
767 /// let grid = Grid::new(10, 10);
768 /// let cell = Cell::new(2, 2);
769 /// let next = cell.strict_up(grid, 3); // panic!
770 /// ```
771 pub fn strict_up(self, grid: Grid, step: u8) -> Cell {
772 if self.will_underflow_depth(grid, step) {
773 panic!(
774 "this operation will violate grid upper bounds! cell:{self}, grid:{grid}, step:{step}"
775 );
776 }
777 Cell {
778 global_width: self.global_width,
779 global_depth: self.global_depth - step,
780 }
781 }
782
783 /// Moves current `Cell` downwards by `step` relative to the given `Grid`
784 /// This operation does not mutate current `Cell` fields,
785 /// instead it calculates new position and returns new `Cell`
786 ///
787 /// # Panics
788 /// Panics if the `Cell` is not within the given `Grid`
789 /// Panics if this operation will violate the given `Grid` lower border
790 ///
791 /// # Examples
792 ///
793 /// ```
794 /// use grid_math::{Cell, Grid};
795 ///
796 /// let grid = Grid::new(10, 10);
797 /// let cell = Cell::new(7, 7);
798 /// let next = cell.strict_down(grid, 2);
799 /// assert_eq!(next, Cell::new(7, 9));
800 /// ```
801 ///
802 /// ```should_panic
803 /// use grid_math::{Cell, Grid};
804 ///
805 /// let grid = Grid::new(10, 10);
806 /// let cell = Cell::new(7, 7);
807 /// let next = cell.strict_down(grid, 3); // panic!
808 /// ```
809 pub fn strict_down(self, grid: Grid, step: u8) -> Cell {
810 if self.will_overflow_depth(grid, step) {
811 panic!(
812 "this operation will violate grid lower bounds! cell:{self}, grid:{grid}, step:{step}"
813 );
814 }
815 Cell {
816 global_width: self.global_width,
817 global_depth: self.global_depth + step,
818 }
819 }
820
821 /// Moves current `Cell` to the left by `step` relative to the given `Grid`
822 /// This operation does not mutate current `Cell` fields,
823 /// instead it calculates new position and returns new `Cell`
824 ///
825 /// # Panics
826 /// Panics if the `Cell` is not within the given `Grid`
827 /// Panics if this operation will violate the given `Grid` left border
828 ///
829 /// # Examples
830 ///
831 /// ```
832 /// use grid_math::{Cell, Grid};
833 ///
834 /// let grid = Grid::new(10, 10);
835 /// let cell = Cell::new(2, 2);
836 /// let next = cell.strict_left(grid, 2);
837 /// assert_eq!(next, Cell::new(0, 2));
838 /// ```
839 ///
840 /// ```should_panic
841 /// use grid_math::{Cell, Grid};
842 ///
843 /// let grid = Grid::new(10, 10);
844 /// let cell = Cell::new(2, 2);
845 /// let next = cell.strict_left(grid, 3); // panic!
846 /// ```
847 pub fn strict_left(self, grid: Grid, step: u8) -> Cell {
848 if self.will_underflow_width(grid, step) {
849 panic!(
850 "this operation will violate grid left bounds! cell:{self}, grid:{grid}, step:{step}"
851 );
852 }
853 Cell {
854 global_width: self.global_width - step,
855 global_depth: self.global_depth,
856 }
857 }
858
859 /// Moves current `Cell` to the right by `step` relative to the given `Grid`
860 /// This operation does not mutate current `Cell` fields,
861 /// instead it calculates new position and returns new `Cell`
862 ///
863 /// # Panics
864 /// Panics if the `Cell` is not within the given `Grid`
865 /// Panics if this operation will violate the given `Grid` right border
866 ///
867 /// # Examples
868 ///
869 /// ```
870 /// use grid_math::{Cell, Grid};
871 ///
872 /// let grid = Grid::new(10, 10);
873 /// let cell = Cell::new(7, 7);
874 /// let next = cell.strict_right(grid, 2);
875 /// assert_eq!(next, Cell::new(9, 7));
876 /// ```
877 ///
878 /// ```should_panic
879 /// use grid_math::{Cell, Grid};
880 ///
881 /// let grid = Grid::new(10, 10);
882 /// let cell = Cell::new(7, 7);
883 /// let next = cell.strict_right(grid, 3); // panic!
884 /// ```
885 pub fn strict_right(self, grid: Grid, step: u8) -> Cell {
886 if self.will_overflow_width(grid, step) {
887 panic!(
888 "this operation will violate grid right bounds! cell:{self}, grid:{grid}, step:{step}"
889 );
890 }
891 Cell {
892 global_width: self.global_width + step,
893 global_depth: self.global_depth,
894 }
895 }
896
897 /// Moves current `Cell` upwards by `step` relative to the given `Grid`
898 ///
899 /// This operation does not mutate current `Cell` fields,
900 /// instead it calculates new position and returns new `Cell`
901 ///
902 /// If this operation will cross `Grid` upper border,
903 /// returns `Cell` with `depth` = `Grid` upper depth limit
904 ///
905 /// # Panics
906 /// Panics if the `Cell` is not within the given `Grid`
907 ///
908 /// # Examples
909 ///
910 /// ```
911 /// use grid_math::{Cell, Grid};
912 ///
913 /// let grid = Grid::new(10, 10);
914 /// let cell = Cell::new(2, 2);
915 /// let next = cell.saturating_up(grid, 2);
916 /// assert_eq!(next, Cell::new(2, 0));
917 /// let next = cell.saturating_up(grid, 5);
918 /// assert_eq!(next, Cell::new(2, 0));
919 /// ```
920 pub fn saturating_up(self, grid: Grid, step: u8) -> Cell {
921 let next_depth = if self.will_underflow_depth(grid, step) {
922 grid.start.global_depth
923 } else {
924 self.global_depth - step
925 };
926 Cell {
927 global_width: self.global_width,
928 global_depth: next_depth,
929 }
930 }
931
932 /// Moves current `Cell` downwards by `step` relative to the given `Grid`
933 ///
934 /// This operation does not mutate current `Cell` fields,
935 /// instead it calculates new position and returns new `Cell`
936 ///
937 /// If this operation will cross `Grid` lower border,
938 /// returns `Cell` with `depth` = `Grid` lower depth limit
939 ///
940 /// # Panics
941 /// Panics if the `Cell` is not within the given `Grid`
942 ///
943 /// # Examples
944 ///
945 /// ```
946 /// use grid_math::{Cell, Grid};
947 ///
948 /// let grid = Grid::new(10, 10);
949 /// let cell = Cell::new(7, 7);
950 /// let next = cell.saturating_down(grid, 2);
951 /// assert_eq!(next, Cell::new(7, 9));
952 /// let next = cell.saturating_down(grid, 5);
953 /// assert_eq!(next, Cell::new(7, 9));
954 /// ```
955 pub fn saturating_down(self, grid: Grid, step: u8) -> Cell {
956 let next_depth = if self.will_overflow_depth(grid, step) {
957 grid.end.global_depth
958 } else {
959 self.global_depth + step
960 };
961 Cell {
962 global_width: self.global_width,
963 global_depth: next_depth,
964 }
965 }
966
967 /// Moves current `Cell` to the left by `step` relative to the given `Grid`
968 ///
969 /// This operation does not mutate current `Cell` fields,
970 /// instead it calculates new position and returns new `Cell`
971 ///
972 /// If this operation will cross `Grid` left border,
973 /// returns `Cell` with `width` = `Grid` left width limit
974 ///
975 /// # Panics
976 /// Panics if the `Cell` is not within the given `Grid`
977 ///
978 /// # Examples
979 ///
980 /// ```
981 /// use grid_math::{Cell, Grid};
982 ///
983 /// let grid = Grid::new(10, 10);
984 /// let cell = Cell::new(2, 2);
985 /// let next = cell.saturating_left(grid, 2);
986 /// assert_eq!(next, Cell::new(0, 2));
987 /// let next = cell.saturating_left(grid, 5);
988 /// assert_eq!(next, Cell::new(0, 2));
989 /// ```
990 pub fn saturating_left(self, grid: Grid, step: u8) -> Cell {
991 let next_width = if self.will_underflow_width(grid, step) {
992 grid.start.global_width
993 } else {
994 self.global_width - step
995 };
996 Cell {
997 global_width: next_width,
998 global_depth: self.global_depth,
999 }
1000 }
1001
1002 /// Moves current `Cell` to the right by `step` relative to the given `Grid`
1003 ///
1004 /// This operation does not mutate current `Cell` fields,
1005 /// instead it calculates new position and returns new `Cell`
1006 ///
1007 /// If this operation will cross `Grid` right border,
1008 /// returns `Cell` with `width` = `Grid` right width limit
1009 ///
1010 /// # Panics
1011 /// Panics if the `Cell` is not within the given `Grid`
1012 ///
1013 /// # Examples
1014 ///
1015 /// ```
1016 /// use grid_math::{Cell, Grid};
1017 ///
1018 /// let grid = Grid::new(10, 10);
1019 /// let cell = Cell::new(7, 7);
1020 /// let next = cell.saturating_right(grid, 2);
1021 /// assert_eq!(next, Cell::new(9, 7));
1022 /// let next = cell.saturating_right(grid, 5);
1023 /// assert_eq!(next, Cell::new(9, 7));
1024 /// ```
1025 pub fn saturating_right(self, grid: Grid, step: u8) -> Cell {
1026 let next_width = if self.will_overflow_width(grid, step) {
1027 grid.end.global_width
1028 } else {
1029 self.global_width + step
1030 };
1031 Cell {
1032 global_width: next_width,
1033 global_depth: self.global_depth,
1034 }
1035 }
1036
1037 /// Moves current `Cell` upwards by `step` relative to the given `Grid`
1038 ///
1039 /// This operation does not mutate current `Cell` fields,
1040 /// instead it calculates new position and returns new `Cell` and `bool`
1041 ///
1042 /// This operation is similar to the overflowing operations on integer types
1043 /// It returns new `Cell` and 'bool' signaling that overflow happened
1044 ///
1045 /// # Panics
1046 /// Panics if the `Cell` is not within the given `Grid`
1047 ///
1048 /// # Examples
1049 ///
1050 /// ```
1051 /// use grid_math::{Cell, Grid};
1052 ///
1053 /// let grid = Grid::new(10, 10);
1054 /// let cell = Cell::new(2, 2);
1055 /// let (next, overflowed) = cell.overflowing_up(grid, 2);
1056 /// assert_eq!((next, overflowed), (Cell::new(2, 0), false));
1057 /// let (next, overflowed) = cell.overflowing_up(grid, 5);
1058 /// assert_eq!((next, overflowed), (Cell::new(2, 7), true));
1059 /// ```
1060 pub fn overflowing_up(self, grid: Grid, step: u8) -> (Cell, bool) {
1061 let underflowed = self.will_underflow_depth(grid, step);
1062 let next_depth = if underflowed {
1063 grid.end.global_depth - ((step - self.depth(grid) - 1) % grid.depth())
1064 } else {
1065 self.global_depth - step
1066 };
1067 (
1068 Cell {
1069 global_width: self.global_width,
1070 global_depth: next_depth,
1071 },
1072 underflowed,
1073 )
1074 }
1075
1076 /// Moves current `Cell` downwards by `step` relative to the given `Grid`
1077 ///
1078 /// This operation does not mutate current `Cell` fields,
1079 /// instead it calculates new position and returns new `Cell` and `bool`
1080 ///
1081 /// This operation is similar to the overflowing operations on integer types
1082 /// It returns new `Cell` and 'bool' signaling that overflow happened
1083 ///
1084 /// # Panics
1085 /// Panics if the `Cell` is not within the given `Grid`
1086 ///
1087 /// # Examples
1088 ///
1089 /// ```
1090 /// use grid_math::{Cell, Grid};
1091 ///
1092 /// let grid = Grid::new(10, 10);
1093 /// let cell = Cell::new(7, 7);
1094 /// let (next, overflowed) = cell.overflowing_down(grid, 2);
1095 /// assert_eq!((next, overflowed), (Cell::new(7, 9), false));
1096 /// let (next, overflowed) = cell.overflowing_down(grid, 5);
1097 /// assert_eq!((next, overflowed), (Cell::new(7, 2), true));
1098 /// ```
1099 pub fn overflowing_down(self, grid: Grid, step: u8) -> (Cell, bool) {
1100 let overflowed = self.will_overflow_depth(grid, step);
1101 let next_depth = if overflowed {
1102 grid.start.global_depth + ((step - self.depth_gap(grid) - 1) % grid.depth())
1103 } else {
1104 self.global_depth + step
1105 };
1106 (
1107 Cell {
1108 global_width: self.global_width,
1109 global_depth: next_depth,
1110 },
1111 overflowed,
1112 )
1113 }
1114
1115 /// Moves current `Cell` to the left by `step` relative to the given `Grid`
1116 ///
1117 /// This operation does not mutate current `Cell` fields,
1118 /// instead it calculates new position and returns new `Cell` and `bool`
1119 ///
1120 /// This operation is similar to the overflowing operations on integer types
1121 /// It returns new `Cell` and 'bool' signaling that overflow happened
1122 ///
1123 /// # Panics
1124 /// Panics if the `Cell` is not within the given `Grid`
1125 ///
1126 /// # Examples
1127 ///
1128 /// ```
1129 /// use grid_math::{Cell, Grid};
1130 ///
1131 /// let grid = Grid::new(10, 10);
1132 /// let cell = Cell::new(2, 2);
1133 /// let (next, overflowed) = cell.overflowing_left(grid, 2);
1134 /// assert_eq!((next, overflowed), (Cell::new(0, 2), false));
1135 /// let (next, overflowed) = cell.overflowing_left(grid, 5);
1136 /// assert_eq!((next, overflowed), (Cell::new(7, 2), true));
1137 /// ```
1138 pub fn overflowing_left(self, grid: Grid, step: u8) -> (Cell, bool) {
1139 let underflowed = self.will_underflow_width(grid, step);
1140 let next_width = if underflowed {
1141 grid.end.global_width - ((step - self.width(grid) - 1) % grid.width())
1142 } else {
1143 self.global_width - step
1144 };
1145 (
1146 Cell {
1147 global_width: next_width,
1148 global_depth: self.global_depth,
1149 },
1150 underflowed,
1151 )
1152 }
1153
1154 /// Moves current `Cell` to the right by `step` relative to the given `Grid`
1155 ///
1156 /// This operation does not mutate current `Cell` fields,
1157 /// instead it calculates new position and returns new `Cell` and `bool`
1158 ///
1159 /// This operation is similar to the overflowing operations on integer types
1160 /// It returns new `Cell` and 'bool' signaling that overflow happened
1161 ///
1162 /// # Panics
1163 /// Panics if the `Cell` is not within the given `Grid`
1164 ///
1165 /// # Examples
1166 ///
1167 /// ```
1168 /// use grid_math::{Cell, Grid};
1169 ///
1170 /// let grid = Grid::new(10, 10);
1171 /// let cell = Cell::new(7, 7);
1172 /// let (next, overflowed) = cell.overflowing_right(grid, 2);
1173 /// assert_eq!((next, overflowed), (Cell::new(9, 7), false));
1174 /// let (next, overflowed) = cell.overflowing_right(grid, 5);
1175 /// assert_eq!((next, overflowed), (Cell::new(2, 7), true));
1176 /// ```
1177 pub fn overflowing_right(self, grid: Grid, step: u8) -> (Cell, bool) {
1178 let overflowed = self.will_overflow_width(grid, step);
1179 let next_width = if overflowed {
1180 grid.start.global_width + ((step - self.width_gap(grid) - 1) % grid.width())
1181 } else {
1182 self.global_width + step
1183 };
1184 (
1185 Cell {
1186 global_width: next_width,
1187 global_depth: self.global_depth,
1188 },
1189 overflowed,
1190 )
1191 }
1192
1193 /// Moves current `Cell` upwards by `step` relative to the given `Grid`
1194 ///
1195 /// This operation is a wrapper around the `overflowing_up()` method,
1196 /// and returns only new `Cell`, without `bool`
1197 ///
1198 /// # Panics
1199 /// Panics if the `Cell` is not within the given `Grid`
1200 ///
1201 /// # Examples
1202 ///
1203 /// ```
1204 /// use grid_math::{Cell, Grid};
1205 ///
1206 /// let grid = Grid::new(10, 10);
1207 /// let cell = Cell::new(2, 2);
1208 /// let next = cell.wrapping_up(grid, 2);
1209 /// assert_eq!(next, Cell::new(2, 0));
1210 /// let next = cell.wrapping_up(grid, 5);
1211 /// assert_eq!(next, Cell::new(2, 7));
1212 /// ```
1213 pub fn wrapping_up(self, grid: Grid, step: u8) -> Cell {
1214 self.overflowing_up(grid, step).0
1215 }
1216
1217 /// Moves current `Cell` downwards by `step` relative to the given `Grid`
1218 ///
1219 /// This operation is a wrapper around the `overflowing_down()` method,
1220 /// and returns only new `Cell`, without `bool`
1221 ///
1222 /// # Panics
1223 /// Panics if the `Cell` is not within the given `Grid`
1224 ///
1225 /// # Examples
1226 ///
1227 /// ```
1228 /// use grid_math::{Cell, Grid};
1229 ///
1230 /// let grid = Grid::new(10, 10);
1231 /// let cell = Cell::new(7, 7);
1232 /// let next = cell.wrapping_down(grid, 2);
1233 /// assert_eq!(next, Cell::new(7, 9));
1234 /// let next = cell.wrapping_down(grid, 5);
1235 /// assert_eq!(next, Cell::new(7, 2));
1236 /// ```
1237 pub fn wrapping_down(self, grid: Grid, step: u8) -> Cell {
1238 self.overflowing_down(grid, step).0
1239 }
1240
1241 /// Moves current `Cell` to the left by `step` relative to the given `Grid`
1242 ///
1243 /// This operation is a wrapper around the `overflowing_left()` method,
1244 /// and returns only new `Cell`, without `bool`
1245 ///
1246 /// # Panics
1247 /// Panics if the `Cell` is not within the given `Grid`
1248 ///
1249 /// # Examples
1250 ///
1251 /// ```
1252 /// use grid_math::{Cell, Grid};
1253 ///
1254 /// let grid = Grid::new(10, 10);
1255 /// let cell = Cell::new(2, 2);
1256 /// let next = cell.wrapping_left(grid, 2);
1257 /// assert_eq!(next, Cell::new(0, 2));
1258 /// let next = cell.wrapping_left(grid, 5);
1259 /// assert_eq!(next, Cell::new(7, 2));
1260 /// ```
1261 pub fn wrapping_left(self, grid: Grid, step: u8) -> Cell {
1262 self.overflowing_left(grid, step).0
1263 }
1264
1265 /// Moves current `Cell` to the right by `step` relative to the given `Grid`
1266 ///
1267 /// This operation is a wrapper around the `overflowing_right()` method,
1268 /// and returns only new `Cell`, without `bool`
1269 ///
1270 /// # Panics
1271 /// Panics if the `Cell` is not within the given `Grid`
1272 ///
1273 /// # Examples
1274 ///
1275 /// ```
1276 /// use grid_math::{Cell, Grid};
1277 ///
1278 /// let grid = Grid::new(10, 10);
1279 /// let cell = Cell::new(7, 7);
1280 /// let next = cell.wrapping_right(grid, 2);
1281 /// assert_eq!(next, Cell::new(9, 7));
1282 /// let next = cell.wrapping_right(grid, 5);
1283 /// assert_eq!(next, Cell::new(2, 7));
1284 /// ```
1285 pub fn wrapping_right(self, grid: Grid, step: u8) -> Cell {
1286 self.overflowing_right(grid, step).0
1287 }
1288
1289 /// Projects current `Cell` onto the top side of the given `Grid`
1290 ///
1291 /// This operation does not mutate current `Cell` fields,
1292 /// instead it calculates new position and returns new `Cell`
1293 ///
1294 /// # Panics
1295 /// Panics if the `Cell` is not within the given `Grid`
1296 ///
1297 /// # Examples
1298 ///
1299 /// ```
1300 /// use grid_math::{Cell, Grid};
1301 ///
1302 /// let grid = Grid::new(10, 10);
1303 /// let cell = Cell::new(2, 2);
1304 /// let next = cell.project_up(grid);
1305 /// assert_eq!(next, Cell::new(2, 0));
1306 /// ```
1307 pub fn project_up(self, grid: Grid) -> Cell {
1308 self.saturating_up(grid, u8::MAX)
1309 }
1310
1311 /// Projects current `Cell` onto the bottom side of the given `Grid`
1312 ///
1313 /// This operation does not mutate current `Cell` fields,
1314 /// instead it calculates new position and returns new `Cell`
1315 ///
1316 /// # Panics
1317 /// Panics if the `Cell` is not within the given `Grid`
1318 ///
1319 /// # Examples
1320 ///
1321 /// ```
1322 /// use grid_math::{Cell, Grid};
1323 ///
1324 /// let grid = Grid::new(10, 10);
1325 /// let cell = Cell::new(7, 7);
1326 /// let next = cell.project_down(grid);
1327 /// assert_eq!(next, Cell::new(7, 9));
1328 /// ```
1329 pub fn project_down(self, grid: Grid) -> Cell {
1330 self.saturating_down(grid, u8::MAX)
1331 }
1332
1333 /// Projects current `Cell` onto the left side of the given `Grid`
1334 ///
1335 /// This operation does not mutate current `Cell` fields,
1336 /// instead it calculates new position and returns new `Cell`
1337 ///
1338 /// # Panics
1339 /// Panics if the `Cell` is not within the given `Grid`
1340 ///
1341 /// # Examples
1342 ///
1343 /// ```
1344 /// use grid_math::{Cell, Grid};
1345 ///
1346 /// let grid = Grid::new(10, 10);
1347 /// let cell = Cell::new(2, 2);
1348 /// let next = cell.project_left(grid);
1349 /// assert_eq!(next, Cell::new(0, 2));
1350 /// ```
1351 pub fn project_left(self, grid: Grid) -> Cell {
1352 self.saturating_left(grid, u8::MAX)
1353 }
1354
1355 /// Projects current `Cell` onto the right side of the given `Grid`
1356 ///
1357 /// This operation does not mutate current `Cell` fields,
1358 /// instead it calculates new position and returns new `Cell`
1359 ///
1360 /// # Panics
1361 /// Panics if the `Cell` is not within the given `Grid`
1362 ///
1363 /// # Examples
1364 ///
1365 /// ```
1366 /// use grid_math::{Cell, Grid};
1367 ///
1368 /// let grid = Grid::new(10, 10);
1369 /// let cell = Cell::new(7, 7);
1370 /// let next = cell.project_right(grid);
1371 /// assert_eq!(next, Cell::new(9, 7));
1372 /// ```
1373 pub fn project_right(self, grid: Grid) -> Cell {
1374 self.saturating_right(grid, u8::MAX)
1375 }
1376}
1377
1378impl fmt::Display for Cell {
1379 /// implements display for `Cell`
1380 ///
1381 /// # Examples
1382 ///
1383 /// ```
1384 /// use grid_math::Cell;
1385 ///
1386 /// let cell = Cell::new(5, 6);
1387 /// assert_eq!(format!("{cell}"), "(5, 6)");
1388 /// ```
1389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1390 write!(
1391 f,
1392 "({w}, {d})",
1393 w = self.global_width,
1394 d = self.global_depth
1395 )
1396 }
1397}
1398
1399impl From<(u8, u8)> for Cell {
1400 /// implements constructor for `Cell` from (u8, u8)
1401 ///
1402 /// # Examples
1403 ///
1404 /// ```
1405 /// use grid_math::Cell;
1406 ///
1407 /// let pos = (5, 6);
1408 /// let cell = Cell::from(pos);
1409 /// assert_eq!((pos.0, pos.1), (cell.global_width(), cell.global_depth()));
1410 /// ```
1411 fn from(value: (u8, u8)) -> Self {
1412 Self {
1413 global_width: value.0,
1414 global_depth: value.1,
1415 }
1416 }
1417}
1418
1419#[allow(clippy::from_over_into)]
1420impl Into<(u8, u8)> for Cell {
1421 /// implements conversion from `Cell` into (u8, u8)
1422 ///
1423 /// # Examples
1424 ///
1425 /// ```
1426 /// use grid_math::Cell;
1427 ///
1428 /// let cell = Cell::new(5, 6);
1429 /// let pos: (u8, u8) = cell.into();
1430 /// assert_eq!((pos.0, pos.1), (cell.global_width(), cell.global_depth()));
1431 /// ```
1432 fn into(self) -> (u8, u8) {
1433 (self.global_width, self.global_depth)
1434 }
1435}
1436
1437impl Grid {
1438 /// Creates new `Grid` with specified `width: u8` and `depth: u8`, starting at (0,0)
1439 ///
1440 /// # Panics
1441 /// Panics if `width` or `depth` parameters < 1
1442 ///
1443 /// # Examples
1444 ///
1445 /// ```
1446 /// use grid_math::Grid;
1447 ///
1448 /// let grid = Grid::new(10, 10);
1449 /// assert_eq!(format!("{grid}"), "[(0, 0):(9, 9)]");
1450 /// ```
1451 pub fn new(width: u8, depth: u8) -> Self {
1452 if width < 1 || depth < 1 {
1453 panic!("can't create grid with width < 0 or depth < 0!")
1454 }
1455 Self {
1456 start: Cell {
1457 global_width: 0,
1458 global_depth: 0,
1459 },
1460 end: Cell {
1461 global_width: width - 1,
1462 global_depth: depth - 1,
1463 },
1464 }
1465 }
1466
1467 /// Creates new `Grid` with specified `width: u8` and `depth: u8`, starting at indent
1468 ///
1469 /// # Panics
1470 /// Panics if `width` or `depth` parameters < 1
1471 ///
1472 /// # Examples
1473 ///
1474 /// ```
1475 /// use grid_math::{Grid, Cell};
1476 ///
1477 /// let grid = Grid::indented(5, 5, (2, 2));
1478 /// assert_eq!(format!("{grid}"), "[(2, 2):(6, 6)]");
1479 ///
1480 /// // use `Cell` as indent:
1481 /// let cell = Cell::new(2, 2);
1482 /// let grid = Grid::indented(5, 5, cell.into());
1483 /// assert_eq!(format!("{grid}"), "[(2, 2):(6, 6)]");
1484 /// ```
1485 pub fn indented(width: u8, depth: u8, indent: (u8, u8)) -> Self {
1486 if width < 1 || depth < 1 {
1487 panic!("can't create grid with width < 0 or depth < 0!")
1488 }
1489 Self {
1490 start: Cell {
1491 global_width: indent.0,
1492 global_depth: indent.1,
1493 },
1494 end: Cell {
1495 global_width: indent.0 + width - 1,
1496 global_depth: indent.1 + depth - 1,
1497 },
1498 }
1499 }
1500
1501 /// Checks if the `Grid` is within the another `Grid`
1502 ///
1503 /// # Examples
1504 ///
1505 /// ```
1506 /// use grid_math::Grid;
1507 ///
1508 /// let grid = Grid::new(10, 10);
1509 /// let subgrid = grid.area(5, 5);
1510 /// assert!(subgrid.within(grid));
1511 ///
1512 /// let subgrid = Grid::new(10, 12);
1513 /// assert!(!subgrid.within(grid));
1514 /// ```
1515 pub fn within(self, grid: Grid) -> bool {
1516 self.start.within(grid) && self.end.within(grid)
1517 }
1518
1519 /// Checks if the `Grid` is within the another `Grid`
1520 ///
1521 /// # Panics
1522 /// Panics if the `Grid` is not within the another `Grid`
1523 ///
1524 /// # Examples
1525 ///
1526 /// ```should_panic
1527 /// use grid_math::Grid;
1528 ///
1529 /// let grid = Grid::new(10, 10);
1530 /// let subgrid = Grid::new(10, 12);
1531 /// subgrid.within_panic(grid);
1532 /// ```
1533 pub fn within_panic(self, grid: Grid) {
1534 if !self.within(grid) {
1535 panic!("subgrid is not within given grid! subgrid:{self}, grid:{grid}")
1536 }
1537 }
1538
1539 /// Returns new `Cell` by `width: u8` and `depth: u8` relative to the current `Grid`
1540 ///
1541 /// # Panics
1542 /// Panics if `width` or `depth` of the requested member exceeds borders of the current `Grid`
1543 ///
1544 /// # Examples
1545 ///
1546 /// ```
1547 /// use grid_math::{Grid, Cell};
1548 ///
1549 /// let grid = Grid::indented(5, 5, (2, 2)); // 5x5 grid, starting at (2,2)
1550 /// let member = grid.member(4, 4);
1551 /// assert_eq!(member, Cell::new(6, 6));
1552 /// ```
1553 pub fn member(self, width: u8, depth: u8) -> Cell {
1554 self.start
1555 .strict_right(self, width)
1556 .strict_down(self, depth)
1557 }
1558
1559 /// Returns new `Grid` with `width: u8` and `depth: u8`, which is a subgrid
1560 /// of current `Grid`, starting at current `Grid` start
1561 ///
1562 /// # Panics
1563 /// Panics if `width` or `depth` parameters < 1
1564 /// Panics if `width` or `depth` of the requested area exceeds borders of the current `Grid`
1565 ///
1566 /// # Examples
1567 ///
1568 /// ```
1569 /// use grid_math::{Grid, Cell};
1570 ///
1571 /// let grid = Grid::indented(5, 5, (2, 2)); // 5x5 grid, starting at (2,2)
1572 /// let area = grid.area(3, 3);
1573 /// assert_eq!(format!("{area}"), "[(2, 2):(4, 4)]");
1574 /// ```
1575 pub fn area(self, width: u8, depth: u8) -> Grid {
1576 if width < 1 || depth < 1 {
1577 panic!("can't create grid with width < 0 or depth < 0!")
1578 }
1579 Grid {
1580 start: self.start,
1581 end: self
1582 .start
1583 .strict_right(self, width - 1)
1584 .strict_down(self, depth - 1),
1585 }
1586 }
1587
1588 /// Returns new `Grid` with `width: u8` and `depth: u8`, which is a subgrid
1589 /// of current `Grid`, starting at current `Grid` start + indent
1590 ///
1591 /// # Panics
1592 /// Panics if `width` or `depth` parameters < 1
1593 /// Panics if `width` or `depth` of the requested slice exceeds borders of the current `Grid`
1594 /// Panics if `indent` of the requested slice exceeds borders of the current `Grid`
1595 ///
1596 /// # Examples
1597 ///
1598 /// ```
1599 /// use grid_math::{Grid, Cell};
1600 ///
1601 /// let grid = Grid::new(10, 10);
1602 /// let slice = grid.slice(3, 3, (2, 2));
1603 /// assert_eq!(format!("{slice}"), "[(2, 2):(4, 4)]");
1604 ///
1605 /// // use `Cell` as indent:
1606 /// let cell = Cell::new(2, 2);
1607 /// let slice = grid.slice(3, 3, cell.into());
1608 /// assert_eq!(format!("{slice}"), "[(2, 2):(4, 4)]");
1609 /// ```
1610 pub fn slice(self, width: u8, depth: u8, indent: (u8, u8)) -> Grid {
1611 if width < 1 || depth < 1 {
1612 panic!("can't create grid with width < 0 or depth < 0!")
1613 }
1614 Grid {
1615 start: self
1616 .start
1617 .strict_right(self, indent.0)
1618 .strict_down(self, indent.1),
1619 end: self
1620 .start
1621 .strict_right(self, indent.0 + width - 1)
1622 .strict_down(self, indent.1 + depth - 1),
1623 }
1624 }
1625
1626 /// Returns `start` cell of `Grid`
1627 ///
1628 /// # Examples
1629 ///
1630 /// ```
1631 /// use grid_math::{Grid, Cell};
1632 ///
1633 /// let grid = Grid::new(10, 10);
1634 /// let start = grid.start();
1635 /// assert_eq!(start, Cell::new(0, 0));
1636 /// ```
1637 pub fn start(self) -> Cell {
1638 self.start
1639 }
1640
1641 /// Returns `end` cell of `Grid`
1642 ///
1643 /// # Examples
1644 ///
1645 /// ```
1646 /// use grid_math::{Grid, Cell};
1647 ///
1648 /// let grid = Grid::new(10, 10);
1649 /// let end = grid.end();
1650 /// assert_eq!(end, Cell::new(9, 9));
1651 /// ```
1652 pub fn end(self) -> Cell {
1653 self.end
1654 }
1655
1656 /// Calculates `width` of `Grid`
1657 ///
1658 /// # Examples
1659 ///
1660 /// ```
1661 /// use grid_math::Grid;
1662 ///
1663 /// let grid = Grid::new(10, 10);
1664 /// let width = grid.width();
1665 /// assert_eq!(width, 10);
1666 /// ```
1667 pub fn width(self) -> u8 {
1668 self.end.global_width - self.start.global_width + 1
1669 }
1670
1671 /// Calculates `depth` of `Grid`
1672 ///
1673 /// # Examples
1674 ///
1675 /// ```
1676 /// use grid_math::Grid;
1677 ///
1678 /// let grid = Grid::new(10, 10);
1679 /// let depth = grid.depth();
1680 /// assert_eq!(depth, 10);
1681 /// ```
1682 pub fn depth(self) -> u8 {
1683 self.end.global_depth - self.start.global_depth + 1
1684 }
1685
1686 /// Calculates `size: u16` of `Grid`
1687 ///
1688 /// # Examples
1689 ///
1690 /// ```
1691 /// use grid_math::Grid;
1692 ///
1693 /// let grid = Grid::new(10, 10);
1694 /// let size = grid.size();
1695 /// assert_eq!(size, 100);
1696 /// ```
1697 pub fn size(self) -> u16 {
1698 self.width() as u16 * self.depth() as u16
1699 }
1700
1701 /// Returns `Cells`, which is an iterator over every cell of the `Grid`
1702 ///
1703 /// # Examples
1704 ///
1705 /// Get every `Cell` on `width` and `depth` axis:
1706 /// ```
1707 /// use grid_math::{Cell, Grid};
1708 ///
1709 /// let grid = Grid::new(3, 3);
1710 ///
1711 /// let axis_cells: Vec<Cell> = grid
1712 /// .cells()
1713 /// .filter(|cell| {
1714 /// cell.global_width() == grid.start().global_width() || cell.global_depth() == grid.start().global_depth()
1715 /// })
1716 /// .collect();
1717 /// assert_eq!(axis_cells, vec![
1718 /// Cell::new(0, 0),
1719 /// Cell::new(1, 0),
1720 /// Cell::new(2, 0),
1721 /// Cell::new(0, 1),
1722 /// Cell::new(0, 2),
1723 /// ]);
1724 /// ```
1725 pub fn cells(self) -> Cells {
1726 Cells::from(self)
1727 }
1728
1729 /// Returns `Rows`, which is an iterator over every row of the `Grid`
1730 ///
1731 /// # Examples
1732 ///
1733 /// Print out `Grid` in custom format:
1734 /// ```
1735 /// use grid_math::{Cell, Grid};
1736 ///
1737 /// let grid = Grid::new(3, 3);
1738 /// let grid_string = grid
1739 /// .rows()
1740 /// .map(|row| {
1741 /// row.cells().map(|_| " [#]")
1742 /// .chain(std::iter::once("\n\n"))
1743 /// .collect::<String>()
1744 /// })
1745 /// .collect::<String>();
1746 /// assert_eq!(grid_string,
1747 /// " \
1748 /// [#] [#] [#]
1749 ///
1750 /// [#] [#] [#]
1751 ///
1752 /// [#] [#] [#]
1753 ///
1754 /// "
1755 /// );
1756 /// ```
1757 pub fn rows(self) -> Rows {
1758 Rows::from(self)
1759 }
1760
1761 /// Returns `Columns`, which is an iterator over every column of the `Grid`
1762 ///
1763 /// # Examples
1764 ///
1765 /// Get every `Cell` on the first column of `Grid`:
1766 /// ```
1767 /// use grid_math::{Cell, Grid};
1768 ///
1769 /// let grid = Grid::new(3, 3);
1770 ///
1771 /// let first_column_cells: Vec<Cell> = grid
1772 /// .columns()
1773 /// .next()
1774 /// .unwrap()
1775 /// .cells()
1776 /// .collect();
1777 ///
1778 /// assert_eq!(first_column_cells, vec![
1779 /// Cell::new(0, 0),
1780 /// Cell::new(0, 1),
1781 /// Cell::new(0, 2),
1782 /// ]);
1783 /// ```
1784 pub fn columns(self) -> Columns {
1785 Columns::from(self)
1786 }
1787}
1788
1789impl From<(Cell, Cell)> for Grid {
1790 /// implements constructor for `Grid` from (Cell, Cell)
1791 ///
1792 /// # Examples
1793 ///
1794 /// ```
1795 /// use grid_math::{Cell, Grid};
1796 ///
1797 /// let cells = (Cell::new(2, 2), Cell::new(5, 5));
1798 /// let grid = Grid::from(cells);
1799 /// assert_eq!((cells.0, cells.1), (grid.start(), grid.end()));
1800 /// ```
1801 fn from(value: (Cell, Cell)) -> Self {
1802 let (start, end) = value;
1803 if start.global_width > end.global_width || start.global_depth > end.global_depth {
1804 panic!("start cell overflows end cell! start:{start}, end:{end}")
1805 }
1806 Self { start, end }
1807 }
1808}
1809
1810#[allow(clippy::from_over_into)]
1811impl Into<(Cell, Cell)> for Grid {
1812 /// implements conversion from `Grid` into (Cell, Cell)
1813 ///
1814 /// # Examples
1815 ///
1816 /// ```
1817 /// use grid_math::{Cell, Grid};
1818 ///
1819 /// let grid = Grid::new(5, 5);
1820 /// let cells: (Cell, Cell) = grid.into();
1821 /// assert_eq!((cells.0, cells.1), (grid.start(), grid.end()));
1822 /// ```
1823 fn into(self) -> (Cell, Cell) {
1824 (self.start, self.end)
1825 }
1826}
1827
1828impl From<((u8, u8), (u8, u8))> for Grid {
1829 /// implements constructor for `Grid` from ((u8, u8), (u8, u8))
1830 ///
1831 /// # Examples
1832 ///
1833 /// ```
1834 /// use grid_math::{Cell, Grid};
1835 ///
1836 /// let vals = ((2, 2), (5, 5));
1837 /// let grid = Grid::from(vals);
1838 /// assert_eq!((Cell::from(vals.0), Cell::from(vals.1)), (grid.start(), grid.end()));
1839 /// ```
1840 fn from(value: ((u8, u8), (u8, u8))) -> Self {
1841 let (start, end): (Cell, Cell) = (value.0.into(), value.1.into());
1842 if start.global_width > end.global_width || start.global_depth > end.global_depth {
1843 panic!("start cell overflows end cell! start:{start}, end:{end}")
1844 }
1845 Self { start, end }
1846 }
1847}
1848
1849#[allow(clippy::from_over_into)]
1850impl Into<((u8, u8), (u8, u8))> for Grid {
1851 /// implements conversion from `Grid` into ((u8, u8), (u8, u8))
1852 ///
1853 /// # Examples
1854 ///
1855 /// ```
1856 /// use grid_math::{Cell, Grid};
1857 ///
1858 /// let grid = Grid::new(5, 5);
1859 /// let vals: ((u8, u8), (u8, u8)) = grid.into();
1860 /// assert_eq!((Cell::from(vals.0), Cell::from(vals.1)), (grid.start(), grid.end()));
1861 /// ```
1862 fn into(self) -> ((u8, u8), (u8, u8)) {
1863 (self.start.into(), self.end.into())
1864 }
1865}
1866
1867impl fmt::Display for Grid {
1868 /// implements display for `Grid`
1869 ///
1870 /// # Examples
1871 ///
1872 /// ```
1873 /// use grid_math::Grid;
1874 ///
1875 /// let grid = Grid::new(5, 6);
1876 /// assert_eq!(format!("{grid}"), "[(0, 0):(4, 5)]");
1877 /// ```
1878 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1879 write!(f, "[{start}:{end}]", start = self.start, end = self.end)
1880 }
1881}
1882
1883impl From<Grid> for Cells {
1884 /// Creates new iterator over every `Cell` on the `Grid`
1885 ///
1886 /// # Examples:
1887 ///
1888 /// ```
1889 /// use grid_math::{Grid, Cells};
1890 ///
1891 /// let grid = Grid::new(5, 5);
1892 /// let cells = Cells::from(grid);
1893 /// ```
1894 fn from(grid: Grid) -> Self {
1895 Self {
1896 grid,
1897 current: grid.start,
1898 consumed: false,
1899 }
1900 }
1901}
1902
1903impl From<Grid> for Columns {
1904 /// Creates new iterator over every column on the `Grid`
1905 ///
1906 /// # Examples:
1907 ///
1908 /// ```
1909 /// use grid_math::{Grid, Columns};
1910 ///
1911 /// let grid = Grid::new(5, 5);
1912 /// let columns = Columns::from(grid);
1913 /// ```
1914 fn from(grid: Grid) -> Self {
1915 Self {
1916 grid,
1917 current: Grid {
1918 start: grid.start,
1919 end: grid.start.project_down(grid),
1920 },
1921 consumed: false,
1922 }
1923 }
1924}
1925
1926impl From<Grid> for Rows {
1927 /// Creates new iterator over every row on the `Grid`
1928 ///
1929 /// # Examples:
1930 ///
1931 /// ```
1932 /// use grid_math::{Grid, Rows};
1933 ///
1934 /// let grid = Grid::new(5, 5);
1935 /// let rows = Rows::from(grid);
1936 /// ```
1937 fn from(grid: Grid) -> Self {
1938 Self {
1939 grid,
1940 current: Grid {
1941 start: grid.start,
1942 end: grid.start.project_right(grid),
1943 },
1944 consumed: false,
1945 }
1946 }
1947}
1948
1949impl Iterator for Cells {
1950 type Item = Cell;
1951 fn next(&mut self) -> Option<Self::Item> {
1952 if self.consumed {
1953 return None;
1954 }
1955 if self.current == self.grid.end {
1956 self.consumed = true;
1957 return Some(self.current);
1958 }
1959 let previous = self.current;
1960 match self.current.overflowing_right(self.grid, 1) {
1961 (next, true) => self.current = next.wrapping_down(self.grid, 1),
1962 (next, false) => self.current = next,
1963 }
1964 Some(previous)
1965 }
1966}
1967
1968impl Iterator for Columns {
1969 type Item = Grid;
1970 fn next(&mut self) -> Option<Self::Item> {
1971 if self.consumed {
1972 return None;
1973 }
1974 if self.current.end == self.grid.end {
1975 self.consumed = true;
1976 return Some(self.current);
1977 }
1978 let previous = self.current;
1979 self.current = Grid {
1980 start: self.current.start.saturating_right(self.grid, 1),
1981 end: self.current.end.saturating_right(self.grid, 1),
1982 };
1983 Some(previous)
1984 }
1985}
1986
1987impl Iterator for Rows {
1988 type Item = Grid;
1989 fn next(&mut self) -> Option<Self::Item> {
1990 if self.consumed {
1991 return None;
1992 }
1993 if self.current.end == self.grid.end {
1994 self.consumed = true;
1995 return Some(self.current);
1996 }
1997 let previous = self.current;
1998 self.current = Grid {
1999 start: self.current.start.saturating_down(self.grid, 1),
2000 end: self.current.end.saturating_down(self.grid, 1),
2001 };
2002 Some(previous)
2003 }
2004}
2005
2006impl<V> From<Grid> for GridMap<V> {
2007 /// Creates new `GridMap` from the given `Grid` with empty `HashMap<Cell, T>`
2008 ///
2009 /// # Examples:
2010 ///
2011 /// ```
2012 /// use grid_math::{Grid, GridMap};
2013 ///
2014 /// let grid = Grid::new(5, 5);
2015 /// let map: GridMap<char> = GridMap::from(grid);
2016 /// ```
2017 fn from(grid: Grid) -> Self {
2018 Self {
2019 grid,
2020 hashmap: HashMap::new(),
2021 }
2022 }
2023}
2024
2025impl<V> GridMap<V> {
2026 /// Shadows `insert` method from the `HashMap`, and reimplements it
2027 /// so it checks first if the key (`Cell`) is within the `Grid`, and then inserts it into the `HashMap`.
2028 /// This method currently has bad error handling, but this may change in the future
2029 ///
2030 /// # Panics
2031 /// Panics, if the key (`Cell`) is not within the inner `Grid`
2032 ///
2033 /// # Examples:
2034 ///
2035 /// ```
2036 /// use grid_math::{Grid, GridMap};
2037 ///
2038 /// let grid = Grid::new(5, 5);
2039 /// let mut map: GridMap<char> = GridMap::from(grid);
2040 /// map.insert(map.grid().start(), '#');
2041 /// map.insert(map.grid().end(), '@');
2042 /// assert_eq!(map.len(), 2);
2043 /// ```
2044 ///
2045 /// ```should_panic
2046 /// use grid_math::{Cell, Grid, GridMap};
2047 ///
2048 /// let grid = Grid::new(5, 5);
2049 /// let cell = Cell::new(6, 6);
2050 /// let mut map: GridMap<char> = GridMap::from(grid);
2051 /// map.insert(cell, '#'); // panic!
2052 /// ```
2053 pub fn insert(&mut self, cell: Cell, value: V) -> Option<V> {
2054 cell.within_panic(self.grid);
2055 self.hashmap.insert(cell, value)
2056 }
2057
2058 /// Returns the inner `Grid`
2059 ///
2060 /// # Examples:
2061 ///
2062 /// ```
2063 /// use grid_math::{Grid, GridMap};
2064 ///
2065 /// let grid = Grid::new(5, 5);
2066 /// let map: GridMap<char> = GridMap::from(grid);
2067 ///
2068 /// assert_eq!(grid, map.grid());
2069 /// ```
2070 pub fn grid(&self) -> Grid {
2071 self.grid
2072 }
2073}
2074
2075/// Implements `Deref` trait for GridMap, to return ref to the inner `HashMap`,
2076/// so we can call methods from `HashMap` directly on the `GridMap`
2077///
2078/// # Examples:
2079///
2080/// ```
2081/// use grid_math::{Grid, GridMap};
2082///
2083/// let grid = Grid::new(5, 5);
2084/// let mut map: GridMap<char> = GridMap::from(grid);
2085/// map.insert(map.grid().start(), '#');
2086///
2087/// assert_eq!(map.len(), 1);
2088/// ```
2089impl<V> Deref for GridMap<V> {
2090 type Target = HashMap<Cell, V>;
2091 fn deref(&self) -> &Self::Target {
2092 &self.hashmap
2093 }
2094}
2095
2096/// Implements `DerefMut` trait for GridMap, to return mut ref to the inner `HashMap`,
2097/// so we can call methods from `HashMap` directly on the `GridMap`
2098///
2099/// # Examples:
2100///
2101/// ```
2102/// use grid_math::{Grid, GridMap};
2103///
2104/// let grid = Grid::new(5, 5);
2105/// let mut map: GridMap<char> = GridMap::from(grid);
2106/// map.insert(map.grid().start(), '#');
2107///
2108/// assert_eq!(map.len(), 1);
2109/// ```
2110impl<V> DerefMut for GridMap<V> {
2111 fn deref_mut(&mut self) -> &mut Self::Target {
2112 &mut self.hashmap
2113 }
2114}
2115
2116// 🦀!⭐!!!