#[cfg(feature = "nightly")]
use std::alloc::Global;
use std::borrow::{Borrow, BorrowMut};
use std::fmt::{Debug, Formatter, Result};
use std::hash::{Hash, Hasher};
use std::ops::{Deref, DerefMut};
use std::ops::{Index, IndexMut};
#[cfg(not(feature = "nightly"))]
use crate::alloc::Global;
use crate::buffer::{Buffer, BufferMut, SizedBuffer, SizedBufferMut};
use crate::buffer::{GridBuffer, SpanBuffer, ViewBuffer, ViewBufferMut};
use crate::dim::Dim;
use crate::expr::{Expr, ExprMut};
use crate::expression::Expression;
use crate::index::SpanIndex;
use crate::iter::Iter;
use crate::layout::Dense;
use crate::traits::{Apply, IntoExpression};
#[repr(transparent)]
pub struct Array<B: ?Sized> {
pub(crate) buffer: B,
}
pub(crate) type GridArray<T, D, A = Global> = Array<GridBuffer<T, D, A>>;
pub(crate) type SpanArray<T, D, L> = Array<SpanBuffer<T, D, L>>;
pub(crate) type ViewArray<'a, T, D, L> = Array<ViewBuffer<'a, T, D, L>>;
pub(crate) type ViewArrayMut<'a, T, D, L> = Array<ViewBufferMut<'a, T, D, L>>;
impl<B: Buffer + ?Sized> Array<B> {
pub fn as_span(&self) -> &SpanArray<B::Item, B::Dim, B::Layout> {
self.buffer.as_span()
}
}
impl<B: BufferMut + ?Sized> Array<B> {
pub fn as_mut_span(&mut self) -> &mut SpanArray<B::Item, B::Dim, B::Layout> {
self.buffer.as_mut_span()
}
}
impl<'a, T, B: Buffer + ?Sized> Apply<T> for &'a Array<B> {
type Output = GridArray<T, B::Dim>;
type ZippedWith<I: IntoExpression> = GridArray<T, <B::Dim as Dim>::Max<I::Dim>>;
fn apply<F: FnMut(Self::Item) -> T>(self, f: F) -> Self::Output {
self.as_span().expr().map(f).eval()
}
fn zip_with<I: IntoExpression, F>(self, expr: I, mut f: F) -> Self::ZippedWith<I>
where
F: FnMut(Self::Item, I::Item) -> T,
{
self.as_span().expr().zip(expr).map(|(x, y)| f(x, y)).eval()
}
}
impl<'a, T, B: BufferMut + ?Sized> Apply<T> for &'a mut Array<B> {
type Output = GridArray<T, B::Dim>;
type ZippedWith<I: IntoExpression> = GridArray<T, <B::Dim as Dim>::Max<I::Dim>>;
fn apply<F: FnMut(Self::Item) -> T>(self, f: F) -> Self::Output {
self.as_mut_span().expr_mut().map(f).eval()
}
fn zip_with<I: IntoExpression, F>(self, expr: I, mut f: F) -> Self::ZippedWith<I>
where
F: FnMut(Self::Item, I::Item) -> T,
{
self.as_mut_span().expr_mut().zip(expr).map(|(x, y)| f(x, y)).eval()
}
}
impl<B: BufferMut<Layout = Dense> + ?Sized> AsMut<[B::Item]> for Array<B> {
fn as_mut(&mut self) -> &mut [B::Item] {
self.as_mut_span().as_mut_slice()
}
}
impl<B: BufferMut + ?Sized> AsMut<SpanArray<B::Item, B::Dim, B::Layout>> for Array<B> {
fn as_mut(&mut self) -> &mut SpanArray<B::Item, B::Dim, B::Layout> {
self.as_mut_span()
}
}
impl<B: Buffer<Layout = Dense> + ?Sized> AsRef<[B::Item]> for Array<B> {
fn as_ref(&self) -> &[B::Item] {
self.as_span().as_slice()
}
}
impl<B: Buffer + ?Sized> AsRef<SpanArray<B::Item, B::Dim, B::Layout>> for Array<B> {
fn as_ref(&self) -> &SpanArray<B::Item, B::Dim, B::Layout> {
self.as_span()
}
}
impl<B: SizedBuffer> Borrow<SpanArray<B::Item, B::Dim, B::Layout>> for Array<B> {
fn borrow(&self) -> &SpanArray<B::Item, B::Dim, B::Layout> {
self.as_span()
}
}
impl<B: SizedBufferMut> BorrowMut<SpanArray<B::Item, B::Dim, B::Layout>> for Array<B> {
fn borrow_mut(&mut self) -> &mut SpanArray<B::Item, B::Dim, B::Layout> {
self.as_mut_span()
}
}
impl<B: SizedBuffer + Clone> Clone for Array<B> {
fn clone(&self) -> Self {
Self { buffer: self.buffer.clone() }
}
fn clone_from(&mut self, source: &Self) {
self.buffer.clone_from(&source.buffer);
}
}
impl<B: SizedBuffer + Copy> Copy for Array<B> {}
impl<T: Debug, B: Buffer<Item = T> + ?Sized> Debug for Array<B> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
if B::Dim::RANK == 0 {
self.as_span()[<B::Dim as Dim>::Shape::default()].fmt(f)
} else {
let mut list = f.debug_list();
if !self.as_span().is_empty() {
_ = list.entries(self.as_span().outer_expr());
}
list.finish()
}
}
}
impl<B: SizedBuffer> Deref for Array<B> {
type Target = SpanArray<B::Item, B::Dim, B::Layout>;
fn deref(&self) -> &Self::Target {
self.as_span()
}
}
impl<B: SizedBufferMut> DerefMut for Array<B> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_span()
}
}
impl<T: Hash, B: Buffer<Item = T> + ?Sized> Hash for Array<B> {
fn hash<H: Hasher>(&self, state: &mut H) {
for i in 0..B::Dim::RANK {
#[cfg(not(feature = "nightly"))]
state.write_usize(self.as_span().size(i));
#[cfg(feature = "nightly")]
state.write_length_prefix(self.as_span().size(i));
}
self.as_span().expr().for_each(|x| x.hash(state));
}
}
impl<B: Buffer + ?Sized, I: SpanIndex<B::Item, B::Dim, B::Layout>> Index<I> for Array<B> {
type Output = I::Output;
fn index(&self, index: I) -> &I::Output {
index.index(self.as_span())
}
}
impl<B: BufferMut + ?Sized, I: SpanIndex<B::Item, B::Dim, B::Layout>> IndexMut<I> for Array<B> {
fn index_mut(&mut self, index: I) -> &mut I::Output {
index.index_mut(self.as_mut_span())
}
}
impl<'a, B: Buffer + ?Sized> IntoExpression for &'a Array<B> {
type Item = &'a B::Item;
type Dim = B::Dim;
type Producer = Expr<'a, B::Item, B::Dim, B::Layout>;
fn into_expr(self) -> Expression<Self::Producer> {
self.as_span().expr()
}
}
impl<'a, B: BufferMut + ?Sized> IntoExpression for &'a mut Array<B> {
type Item = &'a mut B::Item;
type Dim = B::Dim;
type Producer = ExprMut<'a, B::Item, B::Dim, B::Layout>;
fn into_expr(self) -> Expression<Self::Producer> {
self.as_mut_span().expr_mut()
}
}
impl<'a, B: Buffer + ?Sized> IntoIterator for &'a Array<B> {
type Item = &'a B::Item;
type IntoIter = Iter<Expr<'a, B::Item, B::Dim, B::Layout>>;
fn into_iter(self) -> Self::IntoIter {
self.as_span().iter()
}
}
impl<'a, B: BufferMut + ?Sized> IntoIterator for &'a mut Array<B> {
type Item = &'a mut B::Item;
type IntoIter = Iter<ExprMut<'a, B::Item, B::Dim, B::Layout>>;
fn into_iter(self) -> Self::IntoIter {
self.as_mut_span().iter_mut()
}
}