pub mod adapters;
use core::fmt::Debug;
use core::iter::FusedIterator;
use core::marker::PhantomData;
use core::ops::Index;
use crate::location::component::{
ColumnRange, ColumnRangeError, Range as IndexRange, RangeError, RowRange, RowRangeError,
};
use crate::location::{Column, Component as LocComponent, Location, Range as LocRange, Row};
use crate::vector::{Columns, Component as VecComponent, Rows, Vector};
pub trait GridBounds {
fn dimensions(&self) -> Vector;
fn root(&self) -> Location {
Location::new(0, 0)
}
}
impl<'a, G: GridBounds + ?Sized> GridBounds for &'a G {
fn dimensions(&self) -> Vector {
(**self).dimensions()
}
fn root(&self) -> Location {
(**self).root()
}
}
impl<'a, G: GridBounds + ?Sized> GridBounds for &'a mut G {
fn dimensions(&self) -> Vector {
(**self).dimensions()
}
fn root(&self) -> Location {
(**self).root()
}
}
pub trait GridBoundsExt: GridBounds {
fn num_rows(&self) -> Rows {
self.dimensions().rows
}
fn num_columns(&self) -> Columns {
self.dimensions().columns
}
#[inline]
fn dimension<C: VecComponent>(&self) -> C {
self.dimensions().get_component()
}
fn root_row(&self) -> Row {
self.root().row
}
fn root_column(&self) -> Column {
self.root().column
}
#[inline]
fn root_component<C: LocComponent>(&self) -> C {
self.root().get_component()
}
#[inline]
fn range<C: LocComponent>(&self) -> IndexRange<C> {
IndexRange::span(self.root_component(), self.dimension())
}
#[inline]
fn row_range(&self) -> RowRange {
self.range()
}
#[inline]
fn column_range(&self) -> ColumnRange {
self.range()
}
#[inline]
fn check_component<C: LocComponent>(&self, c: C) -> Result<C, RangeError<C>> {
self.range().check(c)
}
#[inline]
fn component_in_bounds<C: LocComponent>(&self, c: C) -> bool {
self.range().in_bounds(c)
}
fn check_location(&self, loc: impl Into<Location>) -> Result<Location, LocationRangeError> {
let loc = loc.into();
self.check_component(loc.row)?;
self.check_component(loc.column)?;
Ok(loc)
}
fn location_in_bounds(&self, location: impl Into<Location>) -> bool {
self.check_location(location).is_ok()
}
}
impl<G: GridBounds> GridBoundsExt for G {}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum LocationRangeError {
Row(RowRangeError),
Column(ColumnRangeError),
}
impl From<RowRangeError> for LocationRangeError {
fn from(err: RowRangeError) -> Self {
LocationRangeError::Row(err)
}
}
impl From<ColumnRangeError> for LocationRangeError {
fn from(err: ColumnRangeError) -> Self {
LocationRangeError::Column(err)
}
}
pub trait BaseGrid: GridBoundsExt {
type Item;
unsafe fn get_unchecked(&self, loc: &Location) -> &Self::Item;
}
impl<'a, G: BaseGrid> BaseGrid for &'a G {
type Item = G::Item;
unsafe fn get_unchecked(&self, loc: &Location) -> &Self::Item {
(**self).get_unchecked(loc)
}
}
impl<'a, G: BaseGrid> BaseGrid for &'a mut G {
type Item = G::Item;
unsafe fn get_unchecked(&self, loc: &Location) -> &Self::Item {
(**self).get_unchecked(loc)
}
}
pub trait Grid: BaseGrid {
fn get(&self, location: impl Into<Location>) -> Result<&Self::Item, LocationRangeError> {
self.check_location(location)
.map(move |loc| unsafe { self.get_unchecked(&loc) })
}
fn view<T: LocComponent>(&self) -> View<Self, T> {
View::new(self)
}
fn rows(&self) -> RowsView<Self> {
self.view()
}
fn columns(&self) -> ColumnsView<Self> {
self.view()
}
unsafe fn single_view_unchecked<T: LocComponent>(&self, index: T) -> SingleView<Self, T> {
SingleView::new_unchecked(self, index)
}
unsafe fn row_unchecked(&self, row: impl Into<Row>) -> RowView<Self> {
self.single_view_unchecked(row.into())
}
unsafe fn column_unchecked(&self, column: impl Into<Column>) -> ColumnView<Self> {
self.single_view_unchecked(column.into())
}
fn single_view<T: LocComponent>(&self, index: T) -> Result<SingleView<Self, T>, RangeError<T>> {
SingleView::new(self, index)
}
fn row(&self, row: impl Into<Row>) -> Result<RowView<Self>, RowRangeError> {
self.single_view(row.into())
}
fn column(&self, column: impl Into<Column>) -> Result<ColumnView<Self>, ColumnRangeError> {
self.single_view(column.into())
}
}
impl<G: BaseGrid> Grid for G {}
pub struct View<'a, G: Grid + ?Sized, T: LocComponent> {
grid: &'a G,
index: PhantomData<T>,
}
impl<'a, G: Grid + ?Sized, T: LocComponent> View<'a, G, T> {
fn new(grid: &'a G) -> Self {
Self {
grid,
index: PhantomData,
}
}
pub unsafe fn get_unchecked(&self, index: T) -> SingleView<G, T> {
SingleView::new_unchecked(self.grid, index)
}
pub fn get(&self, index: impl Into<T>) -> Result<SingleView<G, T>, RangeError<T>> {
SingleView::new(self.grid, index.into())
}
pub fn range(&self) -> IndexRange<T> {
self.grid.range()
}
pub fn iter(
&self,
) -> impl Iterator<Item = SingleView<'a, G, T>>
+ DoubleEndedIterator
+ FusedIterator
+ ExactSizeIterator
+ Debug
+ Clone {
let grid = self.grid;
self.range()
.map(move |index| unsafe { SingleView::new_unchecked(grid, index) })
}
}
pub type RowsView<'a, G> = View<'a, G, Row>;
pub type ColumnsView<'a, G> = View<'a, G, Column>;
pub struct SingleView<'a, G: Grid + ?Sized, T: LocComponent> {
grid: &'a G,
index: T,
}
impl<'a, G: Grid + ?Sized, T: LocComponent> SingleView<'a, G, T> {
unsafe fn new_unchecked(grid: &'a G, index: T) -> Self {
Self { grid, index }
}
fn new(grid: &'a G, index: T) -> Result<Self, RangeError<T>> {
grid.check_component(index)
.map(move |index| unsafe { Self::new_unchecked(grid, index) })
}
pub fn index(&self) -> T {
self.index
}
pub unsafe fn get_unchecked(&self, cross: T::Converse) -> &'a G::Item {
self.grid.get_unchecked(&self.index.combine(cross))
}
pub fn get(
&self,
cross: impl Into<T::Converse>,
) -> Result<&'a G::Item, RangeError<T::Converse>> {
self.grid
.check_component(cross.into())
.map(move |cross| unsafe { self.get_unchecked(cross) })
}
pub fn range(&self) -> LocRange<T> {
LocRange::new(self.index, self.grid.range())
}
pub fn iter(
&self,
) -> impl Iterator<Item = &'a G::Item>
+ DoubleEndedIterator
+ FusedIterator
+ ExactSizeIterator
+ Debug
+ Clone {
let grid = self.grid;
self.range()
.map(move |loc| unsafe { grid.get_unchecked(&loc) })
}
pub fn with_locations(
&self,
) -> impl Iterator<Item = (Location, &'a G::Item)>
+ DoubleEndedIterator
+ FusedIterator
+ ExactSizeIterator
+ Debug
+ Clone {
let grid = self.grid;
self.range()
.map(move |loc| (loc, unsafe { grid.get_unchecked(&loc) }))
}
pub fn with_component(
&self,
) -> impl Iterator<Item = (T::Converse, &'a G::Item)>
+ DoubleEndedIterator
+ FusedIterator
+ ExactSizeIterator
+ Debug
+ Clone {
let grid = self.grid;
let index = self.index;
self.grid.range().map(move |cross: T::Converse| {
(cross, unsafe {
grid.get_unchecked(&(cross.combine(index)))
})
})
}
}
impl<'a, G: Grid + ?Sized, T: LocComponent> Index<T::Converse> for SingleView<'a, G, T> {
type Output = G::Item;
fn index(&self, idx: T::Converse) -> &G::Item {
self.get(idx)
.unwrap_or_else(|_err| panic!("{} out of range", T::name()))
}
}
pub type RowView<'a, G> = SingleView<'a, G, Row>;
pub type ColumnView<'a, G> = SingleView<'a, G, Column>;
pub trait BaseGridMut: BaseGrid {
unsafe fn get_unchecked_mut(&mut self, loc: &Location) -> &mut Self::Item;
unsafe fn set_unchecked(&mut self, loc: &Location, value: Self::Item) {
*self.get_unchecked_mut(loc) = value;
}
}
impl<'a, G: BaseGridMut> BaseGridMut for &'a mut G {
unsafe fn get_unchecked_mut(&mut self, loc: &Location) -> &mut Self::Item {
(**self).get_unchecked_mut(loc)
}
unsafe fn set_unchecked(&mut self, loc: &Location, value: Self::Item) {
(**self).set_unchecked(loc, value)
}
}
pub trait GridMut: BaseGridMut {
fn get_mut(
&mut self,
location: impl Into<Location>,
) -> Result<&mut Self::Item, LocationRangeError> {
self.check_location(location.into())
.map(move |loc| unsafe { self.get_unchecked_mut(&loc) })
}
fn set(
&mut self,
location: impl Into<Location>,
value: Self::Item,
) -> Result<(), LocationRangeError> {
self.check_location(location.into())
.map(move |loc| unsafe { self.set_unchecked(&loc, value) })
}
}
impl<G: BaseGridMut> GridMut for G {}