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