use std::ops::{Deref, DerefMut, Mul}; use std::fmt::{self, Debug, Formatter}; use std::hash::{Hash, Hasher}; #[cfg(feature = "serde-serialize")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; #[cfg(feature = "serde-serialize")] use serde::ser::SerializeSeq; #[cfg(feature = "serde-serialize")] use serde::de::{Error, SeqAccess, Visitor}; #[cfg(feature = "serde-serialize")] use std::mem; #[cfg(feature = "serde-serialize")] use std::marker::PhantomData; #[cfg(feature = "abomonation-serialize")] use abomonation::Abomonation; use typenum::Prod; use generic_array::{ArrayLength, GenericArray}; use base::Scalar; use base::dimension::{DimName, U1}; use base::storage::{ContiguousStorage, ContiguousStorageMut, Owned, Storage, StorageMut}; use base::allocator::Allocator; use base::default_allocator::DefaultAllocator; /* * * Static Storage. * */ /// A array-based statically sized matrix data storage. #[repr(C)] pub struct MatrixArray where R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { data: GenericArray>, } impl Hash for MatrixArray where N: Hash, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { fn hash(&self, state: &mut H) { self.data[..].hash(state) } } impl Deref for MatrixArray where R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { type Target = GenericArray>; #[inline] fn deref(&self) -> &Self::Target { &self.data } } impl DerefMut for MatrixArray where R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data } } impl Debug for MatrixArray where N: Debug, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { #[inline] fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.data.fmt(fmt) } } impl Copy for MatrixArray where N: Copy, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, GenericArray>: Copy, { } impl Clone for MatrixArray where N: Clone, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { #[inline] fn clone(&self) -> Self { MatrixArray { data: self.data.clone(), } } } impl Eq for MatrixArray where N: Eq, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { } impl PartialEq for MatrixArray where N: PartialEq, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { #[inline] fn eq(&self, right: &Self) -> bool { self.data == right.data } } unsafe impl Storage for MatrixArray where N: Scalar, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, DefaultAllocator: Allocator, { type RStride = U1; type CStride = R; #[inline] fn ptr(&self) -> *const N { self[..].as_ptr() } #[inline] fn shape(&self) -> (R, C) { (R::name(), C::name()) } #[inline] fn strides(&self) -> (Self::RStride, Self::CStride) { (Self::RStride::name(), Self::CStride::name()) } #[inline] fn is_contiguous(&self) -> bool { true } #[inline] fn into_owned(self) -> Owned where DefaultAllocator: Allocator, { self } #[inline] fn clone_owned(&self) -> Owned where DefaultAllocator: Allocator, { let it = self.iter().cloned(); DefaultAllocator::allocate_from_iterator(self.shape().0, self.shape().1, it) } #[inline] fn as_slice(&self) -> &[N] { &self[..] } } unsafe impl StorageMut for MatrixArray where N: Scalar, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, DefaultAllocator: Allocator, { #[inline] fn ptr_mut(&mut self) -> *mut N { self[..].as_mut_ptr() } #[inline] fn as_mut_slice(&mut self) -> &mut [N] { &mut self[..] } } unsafe impl ContiguousStorage for MatrixArray where N: Scalar, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, DefaultAllocator: Allocator, { } unsafe impl ContiguousStorageMut for MatrixArray where N: Scalar, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, DefaultAllocator: Allocator, { } /* * * Allocation-less serde impls. * */ // XXX: open an issue for GenericArray so that it implements serde traits? #[cfg(feature = "serde-serialize")] impl Serialize for MatrixArray where N: Scalar + Serialize, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { let mut serializer = serializer.serialize_seq(Some(R::dim() * C::dim()))?; for e in self.iter() { serializer.serialize_element(e)?; } serializer.end() } } #[cfg(feature = "serde-serialize")] impl<'a, N, R, C> Deserialize<'a> for MatrixArray where N: Scalar + Deserialize<'a>, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a>, { deserializer.deserialize_seq(MatrixArrayVisitor::new()) } } #[cfg(feature = "serde-serialize")] /// A visitor that produces a matrix array. struct MatrixArrayVisitor { marker: PhantomData<(N, R, C)>, } #[cfg(feature = "serde-serialize")] impl MatrixArrayVisitor where N: Scalar, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { /// Construct a new sequence visitor. pub fn new() -> Self { MatrixArrayVisitor { marker: PhantomData, } } } #[cfg(feature = "serde-serialize")] impl<'a, N, R, C> Visitor<'a> for MatrixArrayVisitor where N: Scalar + Deserialize<'a>, R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, { type Value = MatrixArray; 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::uninitialized() }; let mut curr = 0; while let Some(value) = try!(visitor.next_element()) { out[curr] = value; curr += 1; } if curr == R::dim() * C::dim() { Ok(out) } else { Err(V::Error::invalid_length(curr, &self)) } } } #[cfg(feature = "abomonation-serialize")] impl Abomonation for MatrixArray where R: DimName, C: DimName, R::Value: Mul, Prod: ArrayLength, N: Abomonation, { unsafe fn entomb(&self, writer: &mut Vec) { for element in self.data.as_slice() { element.entomb(writer); } } unsafe fn embalm(&mut self) { for element in self.data.as_mut_slice() { element.embalm(); } } unsafe fn exhume<'a, 'b>(&'a mut self, mut bytes: &'b mut [u8]) -> Option<&'b mut [u8]> { for element in self.data.as_mut_slice() { let temp = bytes; bytes = if let Some(remainder) = element.exhume(temp) { remainder } else { return None; } } Some(bytes) } }