use std::fmt::{Debug, Formatter, Result};
use std::ops::{
Bound, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};
use crate::grid::Grid;
use crate::shape::Shape;
use crate::traits::FromExpression;
pub trait Dim: Copy + Debug + Default + Send + Sync {
type Merge<D: Dim>: Dim;
type FromExpr<T, S: Shape>: FromExpression<T, S::Prepend<Self>>;
const SIZE: Option<usize>;
fn from_size(size: usize) -> Self;
fn size(self) -> usize;
}
pub trait Dims:
Copy
+ Debug
+ Default
+ IndexMut<(Bound<usize>, Bound<usize>), Output = [usize]>
+ IndexMut<usize, Output = usize>
+ IndexMut<Range<usize>, Output = [usize]>
+ IndexMut<RangeFrom<usize>, Output = [usize]>
+ IndexMut<RangeFull, Output = [usize]>
+ IndexMut<RangeInclusive<usize>, Output = [usize]>
+ IndexMut<RangeTo<usize>, Output = [usize]>
+ IndexMut<RangeToInclusive<usize>, Output = [usize]>
+ Send
+ Sync
+ for<'a> TryFrom<&'a [usize], Error: Debug>
{
}
pub trait Strides:
Copy
+ Debug
+ Default
+ IndexMut<(Bound<usize>, Bound<usize>), Output = [isize]>
+ IndexMut<usize, Output = isize>
+ IndexMut<Range<usize>, Output = [isize]>
+ IndexMut<RangeFrom<usize>, Output = [isize]>
+ IndexMut<RangeFull, Output = [isize]>
+ IndexMut<RangeInclusive<usize>, Output = [isize]>
+ IndexMut<RangeTo<usize>, Output = [isize]>
+ IndexMut<RangeToInclusive<usize>, Output = [isize]>
+ Send
+ Sync
+ for<'a> TryFrom<&'a [isize], Error: Debug>
{
}
#[derive(Clone, Copy, Default)]
pub struct Const<const N: usize>;
#[derive(Clone, Copy, Debug, Default)]
pub struct Dyn(pub usize);
impl<const N: usize> Debug for Const<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.debug_tuple("Const").field(&N).finish()
}
}
impl<const N: usize> Dim for Const<N> {
type Merge<D: Dim> = Self;
type FromExpr<T, S: Shape> = <S::FromExpr<T> as FromExpression<T, S>>::WithConst<N>;
const SIZE: Option<usize> = Some(N);
fn from_size(size: usize) -> Self {
assert!(size == N, "invalid size");
Self
}
fn size(self) -> usize {
N
}
}
impl Dim for Dyn {
type Merge<D: Dim> = D;
type FromExpr<T, S: Shape> = Grid<T, S::Prepend<Self>>;
const SIZE: Option<usize> = None;
fn from_size(size: usize) -> Self {
Self(size)
}
fn size(self) -> usize {
self.0
}
}
macro_rules! impl_dims_strides {
($($n:tt),+) => {
$(
impl Dims for [usize; $n] {}
impl Strides for [isize; $n] {}
)+
};
}
impl_dims_strides!(0, 1, 2, 3, 4, 5, 6);