use std::mem::{self, size_of};
use std::rc::Rc;
use {
ArrayBase,
Dimension,
ViewRepr,
OwnedRepr,
OwnedRcRepr,
};
pub unsafe trait Data : Sized {
type Elem;
#[doc(hidden)]
fn _data_slice(&self) -> &[Self::Elem];
private_decl!{}
}
pub unsafe trait DataMut : Data {
#[doc(hidden)]
#[inline]
fn ensure_unique<D>(&mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{ }
#[doc(hidden)]
#[inline]
fn is_unique(&mut self) -> bool {
true
}
}
pub unsafe trait DataClone : Data {
#[doc(hidden)]
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
#[doc(hidden)]
unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem {
let (data, ptr) = other.clone_with_ptr(ptr);
*self = data;
ptr
}
}
unsafe impl<A> Data for OwnedRcRepr<A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&self.0
}
private_impl!{}
}
unsafe impl<A> DataMut for OwnedRcRepr<A>
where A: Clone
{
fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{
if Rc::get_mut(&mut self_.data.0).is_some() {
return;
}
if self_.dim.size() <= self_.data.0.len() / 2 {
unsafe {
*self_ = ArrayBase::from_shape_vec_unchecked(self_.dim.clone(),
self_.iter()
.cloned()
.collect());
}
return;
}
let rcvec = &mut self_.data.0;
let a_size = mem::size_of::<A>() as isize;
let our_off = if a_size != 0 {
(self_.ptr as isize - rcvec.as_ptr() as isize) / a_size
} else { 0 };
let rvec = Rc::make_mut(rcvec);
unsafe {
self_.ptr = rvec.as_mut_ptr().offset(our_off);
}
}
fn is_unique(&mut self) -> bool {
Rc::get_mut(&mut self.0).is_some()
}
}
unsafe impl<A> DataClone for OwnedRcRepr<A> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
(self.clone(), ptr)
}
}
unsafe impl<A> Data for OwnedRepr<A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&self.0
}
private_impl!{}
}
unsafe impl<A> DataMut for OwnedRepr<A> { }
unsafe impl<A> DataClone for OwnedRepr<A>
where A: Clone
{
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
let mut u = self.clone();
let mut new_ptr = u.0.as_mut_ptr();
if size_of::<A>() != 0 {
let our_off = (ptr as isize - self.0.as_ptr() as isize) /
mem::size_of::<A>() as isize;
new_ptr = new_ptr.offset(our_off);
}
(u, new_ptr)
}
unsafe fn clone_from_with_ptr(&mut self, other: &Self, ptr: *mut Self::Elem) -> *mut Self::Elem {
let our_off = if size_of::<A>() != 0 {
(ptr as isize - other.0.as_ptr() as isize) /
mem::size_of::<A>() as isize
} else {
0
};
self.0.clone_from(&other.0);
self.0.as_mut_ptr().offset(our_off)
}
}
unsafe impl<'a, A> Data for ViewRepr<&'a A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&[]
}
private_impl!{}
}
unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
(*self, ptr)
}
}
unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&[]
}
private_impl!{}
}
unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> { }
pub unsafe trait DataOwned : Data {
#[doc(hidden)]
fn new(elements: Vec<Self::Elem>) -> Self;
#[doc(hidden)]
fn into_shared(self) -> OwnedRcRepr<Self::Elem>;
}
pub unsafe trait DataShared : Clone + DataClone { }
unsafe impl<A> DataShared for OwnedRcRepr<A> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}
unsafe impl<A> DataOwned for OwnedRepr<A> {
fn new(elements: Vec<A>) -> Self {
OwnedRepr(elements)
}
fn into_shared(self) -> OwnedRcRepr<A> {
OwnedRcRepr(Rc::new(self.0))
}
}
unsafe impl<A> DataOwned for OwnedRcRepr<A> {
fn new(elements: Vec<A>) -> Self {
OwnedRcRepr(Rc::new(elements))
}
fn into_shared(self) -> OwnedRcRepr<A> {
self
}
}