use std::fmt::{self, Debug, Formatter}; // use std::hash::{Hash, Hasher}; #[cfg(feature = "abomonation-serialize")] use std::io::{Result as IOResult, Write}; use std::ops::Mul; #[cfg(feature = "serde-serialize-no-std")] use serde::de::{Error, SeqAccess, Visitor}; #[cfg(feature = "serde-serialize-no-std")] use serde::ser::SerializeSeq; #[cfg(feature = "serde-serialize-no-std")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde-serialize-no-std")] use std::marker::PhantomData; #[cfg(feature = "serde-serialize-no-std")] use std::mem; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; use crate::base::allocator::Allocator; use crate::base::default_allocator::DefaultAllocator; use crate::base::dimension::{Const, ToTypenum}; use crate::base::storage::{ ContiguousStorage, ContiguousStorageMut, Owned, ReshapableStorage, Storage, StorageMut, }; use crate::base::Scalar; /* * * Static Storage. * */ /// A array-based statically sized matrix data storage. #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct ArrayStorage(pub [[T; R]; C]); // TODO: remove this once the stdlib implements Default for arrays. impl Default for ArrayStorage where [[T; R]; C]: Default, { #[inline] fn default() -> Self { Self(Default::default()) } } impl Debug for ArrayStorage { #[inline] fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.0.fmt(fmt) } } unsafe impl Storage, Const> for ArrayStorage where T: Scalar, DefaultAllocator: Allocator, Const, Buffer = Self>, { type RStride = Const<1>; type CStride = Const; #[inline] fn ptr(&self) -> *const T { self.0.as_ptr() as *const T } #[inline] fn shape(&self) -> (Const, Const) { (Const, Const) } #[inline] fn strides(&self) -> (Self::RStride, Self::CStride) { (Const, Const) } #[inline] fn is_contiguous(&self) -> bool { true } #[inline] fn into_owned(self) -> Owned, Const> where DefaultAllocator: Allocator, Const>, { self } #[inline] fn clone_owned(&self) -> Owned, Const> where DefaultAllocator: Allocator, Const>, { let it = self.as_slice().iter().cloned(); DefaultAllocator::allocate_from_iterator(self.shape().0, self.shape().1, it) } #[inline] fn as_slice(&self) -> &[T] { unsafe { std::slice::from_raw_parts(self.ptr(), R * C) } } } unsafe impl StorageMut, Const> for ArrayStorage where T: Scalar, DefaultAllocator: Allocator, Const, Buffer = Self>, { #[inline] fn ptr_mut(&mut self) -> *mut T { self.0.as_mut_ptr() as *mut T } #[inline] fn as_mut_slice(&mut self) -> &mut [T] { unsafe { std::slice::from_raw_parts_mut(self.ptr_mut(), R * C) } } } unsafe impl ContiguousStorage, Const> for ArrayStorage where T: Scalar, DefaultAllocator: Allocator, Const, Buffer = Self>, { } unsafe impl ContiguousStorageMut, Const> for ArrayStorage where T: Scalar, DefaultAllocator: Allocator, Const, Buffer = Self>, { } impl ReshapableStorage, Const, Const, Const> for ArrayStorage where T: Scalar, Const: ToTypenum, Const: ToTypenum, Const: ToTypenum, Const: ToTypenum, as ToTypenum>::Typenum: Mul< as ToTypenum>::Typenum>, as ToTypenum>::Typenum: Mul< as ToTypenum>::Typenum, Output = typenum::Prod< as ToTypenum>::Typenum, as ToTypenum>::Typenum, >, >, { type Output = ArrayStorage; fn reshape_generic(self, _: Const, _: Const) -> Self::Output { unsafe { let data: [[T; R2]; C2] = std::mem::transmute_copy(&self.0); std::mem::forget(self.0); ArrayStorage(data) } } } /* * * Serialization. * */ // XXX: open an issue for serde so that it allows the serialization/deserialization of all arrays? #[cfg(feature = "serde-serialize-no-std")] impl Serialize for ArrayStorage where T: Scalar + Serialize, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut serializer = serializer.serialize_seq(Some(R * C))?; for e in self.as_slice().iter() { serializer.serialize_element(e)?; } serializer.end() } } #[cfg(feature = "serde-serialize-no-std")] impl<'a, T, const R: usize, const C: usize> Deserialize<'a> for ArrayStorage where T: Scalar + Deserialize<'a>, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a>, { deserializer.deserialize_seq(ArrayStorageVisitor::new()) } } #[cfg(feature = "serde-serialize-no-std")] /// A visitor that produces a matrix array. struct ArrayStorageVisitor { marker: PhantomData, } #[cfg(feature = "serde-serialize-no-std")] impl ArrayStorageVisitor where T: Scalar, { /// Construct a new sequence visitor. pub fn new() -> Self { ArrayStorageVisitor { marker: PhantomData, } } } #[cfg(feature = "serde-serialize-no-std")] impl<'a, T, const R: usize, const C: usize> Visitor<'a> for ArrayStorageVisitor where T: Scalar + Deserialize<'a>, { type Value = ArrayStorage; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { formatter.write_str("a matrix array") } #[inline] fn visit_seq(self, mut visitor: V) -> Result, V::Error> where V: SeqAccess<'a>, { let mut out: Self::Value = unsafe { mem::MaybeUninit::uninit().assume_init() }; let mut curr = 0; while let Some(value) = visitor.next_element()? { *out.as_mut_slice() .get_mut(curr) .ok_or_else(|| V::Error::invalid_length(curr, &self))? = value; curr += 1; } if curr == R * C { Ok(out) } else { Err(V::Error::invalid_length(curr, &self)) } } } #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Zeroable for ArrayStorage { } #[cfg(feature = "bytemuck")] unsafe impl bytemuck::Pod for ArrayStorage { } #[cfg(feature = "abomonation-serialize")] impl Abomonation for ArrayStorage where T: Scalar + Abomonation, { unsafe fn entomb(&self, writer: &mut W) -> IOResult<()> { for element in self.as_slice() { element.entomb(writer)?; } Ok(()) } unsafe fn exhume<'a, 'b>(&'a mut self, mut bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { for element in self.as_mut_slice() { let temp = bytes; bytes = if let Some(remainder) = element.exhume(temp) { remainder } else { return None; } } Some(bytes) } fn extent(&self) -> usize { self.as_slice().iter().fold(0, |acc, e| acc + e.extent()) } }