diff --git a/src/data_repr.rs b/src/data_repr.rs new file mode 100644 index 000000000..c7a8b96fa --- /dev/null +++ b/src/data_repr.rs @@ -0,0 +1,97 @@ + +use std::mem; +use std::ptr::NonNull; +use std::slice; +use crate::extension::nonnull; + +/// Array's representation. +/// +/// *Don’t use this type directly—use the type alias +/// [`Array`](type.Array.html) for the array type!* +// Like a Vec, but with non-unique ownership semantics +#[derive(Debug)] +pub struct OwnedRepr { + ptr: NonNull, + len: usize, + capacity: usize, +} + +impl OwnedRepr { + pub(crate) fn from(mut v: Vec) -> Self { + let len = v.len(); + let capacity = v.capacity(); + let ptr = nonnull::nonnull_from_vec_data(&mut v); + mem::forget(v); + Self { + ptr, + len, + capacity, + } + } + + pub(crate) fn into_vec(mut self) -> Vec { + let v = self.take_as_vec(); + mem::forget(self); + v + } + + pub(crate) fn as_slice(&self) -> &[A] { + unsafe { + slice::from_raw_parts(self.ptr.as_ptr(), self.len) + } + } + + pub(crate) fn len(&self) -> usize { self.len } + + pub(crate) fn as_ptr(&self) -> *const A { + self.ptr.as_ptr() + } + + pub(crate) fn as_nonnull_mut(&mut self) -> NonNull { + self.ptr + } + + fn take_as_vec(&mut self) -> Vec { + let capacity = self.capacity; + let len = self.len; + self.len = 0; + self.capacity = 0; + unsafe { + Vec::from_raw_parts(self.ptr.as_ptr(), len, capacity) + } + } +} + +impl Clone for OwnedRepr + where A: Clone +{ + fn clone(&self) -> Self { + Self::from(self.as_slice().to_owned()) + } + + fn clone_from(&mut self, other: &Self) { + let mut v = self.take_as_vec(); + let other = other.as_slice(); + + if v.len() > other.len() { + v.truncate(other.len()); + } + let (front, back) = other.split_at(v.len()); + v.clone_from_slice(front); + v.extend_from_slice(back); + *self = Self::from(v); + } +} + +impl Drop for OwnedRepr { + fn drop(&mut self) { + if self.capacity > 0 { + // drop as a Vec. + self.take_as_vec(); + } + } +} + +unsafe impl Sync for OwnedRepr where A: Sync { } +unsafe impl Send for OwnedRepr where A: Send { } + diff --git a/src/data_traits.rs b/src/data_traits.rs index b3f07959e..7e04561bc 100644 --- a/src/data_traits.rs +++ b/src/data_traits.rs @@ -8,7 +8,6 @@ //! The data (inner representation) traits for ndarray -use crate::extension::nonnull::nonnull_from_vec_data; use rawpointer::PointerExt; use std::mem::{self, size_of}; use std::ptr::NonNull; @@ -188,7 +187,7 @@ unsafe impl RawDataClone for RawViewRepr<*mut A> { unsafe impl RawData for OwnedArcRepr { type Elem = A; fn _data_slice(&self) -> Option<&[A]> { - Some(&self.0) + Some(self.0.as_slice()) } private_impl! {} } @@ -226,7 +225,7 @@ where }; let rvec = Arc::make_mut(rcvec); unsafe { - self_.ptr = nonnull_from_vec_data(rvec).offset(our_off); + self_.ptr = rvec.as_nonnull_mut().offset(our_off); } } @@ -242,7 +241,7 @@ unsafe impl Data for OwnedArcRepr { D: Dimension, { Self::ensure_unique(&mut self_); - let data = OwnedRepr(Arc::try_unwrap(self_.data.0).ok().unwrap()); + let data = Arc::try_unwrap(self_.data.0).ok().unwrap(); ArrayBase { data, ptr: self_.ptr, @@ -264,7 +263,7 @@ unsafe impl RawDataClone for OwnedArcRepr { unsafe impl RawData for OwnedRepr { type Elem = A; fn _data_slice(&self) -> Option<&[A]> { - Some(&self.0) + Some(self.as_slice()) } private_impl! {} } @@ -303,10 +302,10 @@ where { unsafe fn clone_with_ptr(&self, ptr: NonNull) -> (Self, NonNull) { let mut u = self.clone(); - let mut new_ptr = nonnull_from_vec_data(&mut u.0); + let mut new_ptr = u.as_nonnull_mut(); if size_of::() != 0 { let our_off = - (ptr.as_ptr() as isize - self.0.as_ptr() as isize) / mem::size_of::() as isize; + (ptr.as_ptr() as isize - self.as_ptr() as isize) / mem::size_of::() as isize; new_ptr = new_ptr.offset(our_off); } (u, new_ptr) @@ -318,12 +317,12 @@ where ptr: NonNull, ) -> NonNull { let our_off = if size_of::() != 0 { - (ptr.as_ptr() as isize - other.0.as_ptr() as isize) / mem::size_of::() as isize + (ptr.as_ptr() as isize - other.as_ptr() as isize) / mem::size_of::() as isize } else { 0 }; - self.0.clone_from(&other.0); - nonnull_from_vec_data(&mut self.0).offset(our_off) + self.clone_from(&other); + self.as_nonnull_mut().offset(our_off) } } @@ -413,16 +412,16 @@ unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {} unsafe impl DataOwned for OwnedRepr { fn new(elements: Vec) -> Self { - OwnedRepr(elements) + OwnedRepr::from(elements) } fn into_shared(self) -> OwnedRcRepr { - OwnedArcRepr(Arc::new(self.0)) + OwnedArcRepr(Arc::new(self)) } } unsafe impl DataOwned for OwnedArcRepr { fn new(elements: Vec) -> Self { - OwnedArcRepr(Arc::new(elements)) + OwnedArcRepr(Arc::new(OwnedRepr::from(elements))) } fn into_shared(self) -> OwnedRcRepr { diff --git a/src/impl_owned_array.rs b/src/impl_owned_array.rs index 96075593f..687452f9b 100644 --- a/src/impl_owned_array.rs +++ b/src/impl_owned_array.rs @@ -19,22 +19,22 @@ impl Array { /// let scalar: Foo = array.into_scalar(); /// assert_eq!(scalar, Foo); /// ``` - pub fn into_scalar(mut self) -> A { + pub fn into_scalar(self) -> A { let size = ::std::mem::size_of::(); if size == 0 { // Any index in the `Vec` is fine since all elements are identical. - self.data.0.remove(0) + self.data.into_vec().remove(0) } else { // Find the index in the `Vec` corresponding to `self.ptr`. // (This is necessary because the element in the array might not be // the first element in the `Vec`, such as if the array was created // by `array![1, 2, 3, 4].slice_move(s![2])`.) let first = self.ptr.as_ptr() as usize; - let base = self.data.0.as_ptr() as usize; + let base = self.data.as_ptr() as usize; let index = (first - base) / size; debug_assert_eq!((first - base) % size, 0); // Remove the element at the index and return it. - self.data.0.remove(index) + self.data.into_vec().remove(index) } } } @@ -54,6 +54,6 @@ where /// If the array is in standard memory layout, the logical element order /// of the array (`.iter()` order) and of the returned vector will be the same. pub fn into_raw_vec(self) -> Vec { - self.data.0 + self.data.into_vec() } } diff --git a/src/lib.rs b/src/lib.rs index f9a208df1..32830d3b3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,6 +150,7 @@ mod array_serde; mod arrayformat; mod arraytraits; mod data_traits; +mod data_repr; pub use crate::aliases::*; @@ -1386,12 +1387,8 @@ pub type RawArrayView = ArrayBase, D>; /// [`from_shape_ptr`](#method.from_shape_ptr) for details. pub type RawArrayViewMut = ArrayBase, D>; -/// Array's representation. -/// -/// *Don’t use this type directly—use the type alias -/// [`Array`](type.Array.html) for the array type!* -#[derive(Clone, Debug)] -pub struct OwnedRepr(Vec); +pub use data_repr::OwnedRepr; + /// RcArray's representation. /// @@ -1405,7 +1402,7 @@ pub use self::OwnedArcRepr as OwnedRcRepr; /// *Don’t use this type directly—use the type alias /// [`ArcArray`](type.ArcArray.html) for the array type!* #[derive(Debug)] -pub struct OwnedArcRepr(Arc>); +pub struct OwnedArcRepr(Arc>); impl Clone for OwnedArcRepr { fn clone(&self) -> Self {