Skip to content

Commit

Permalink
Merge pull request #496 from jturner314/arrayptr
Browse files Browse the repository at this point in the history
Add raw array pointer types
  • Loading branch information
jturner314 committed Nov 29, 2018
2 parents 29617e9 + 218bb88 commit d8078f6
Show file tree
Hide file tree
Showing 10 changed files with 692 additions and 209 deletions.
257 changes: 198 additions & 59 deletions src/data_traits.rs
Expand Up @@ -14,6 +14,7 @@ use std::sync::Arc;
use {
ArrayBase,
Dimension,
RawViewRepr,
ViewRepr,
OwnedRepr,
OwnedRcRepr,
Expand All @@ -22,92 +23,177 @@ use {

/// Array representation trait.
///
/// ***Note:*** `Data` is not an extension interface at this point.
/// For an array that meets the invariants of the `ArrayBase` type. This trait
/// does not imply any ownership or lifetime; pointers to elements in the array
/// may not be safe to dereference.
///
/// ***Note:*** `RawData` is not an extension interface at this point.
/// Traits in Rust can serve many different roles. This trait is public because
/// it is used as a bound on public methods.
pub unsafe trait Data : Sized {
pub unsafe trait RawData : Sized {
/// The array element type.
type Elem;

#[doc(hidden)]
// This method is only used for debugging
fn _data_slice(&self) -> &[Self::Elem];
fn _data_slice(&self) -> Option<&[Self::Elem]>;

private_decl!{}
}

/// Array representation trait.
///
/// For an array with writable elements.
///
/// ***Internal trait, see `RawData`.***
pub unsafe trait RawDataMut : RawData {
/// If possible, ensures that the array has unique access to its data.
///
/// If `Self` provides safe mutable access to array elements, then it
/// **must** panic or ensure that the data is unique.
#[doc(hidden)]
fn try_ensure_unique<D>(&mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension;

/// If possible, returns whether the array has unique access to its data.
///
/// If `Self` provides safe mutable access to array elements, then it
/// **must** return `Some(_)`.
#[doc(hidden)]
fn try_is_unique(&mut self) -> Option<bool>;
}

/// Array representation trait.
///
/// An array representation that can be cloned.
///
/// ***Internal trait, see `RawData`.***
pub unsafe trait RawDataClone : RawData {
#[doc(hidden)]
/// Unsafe because, `ptr` must point inside the current storage.
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
}
}

/// Array representation trait.
///
/// For an array with elements that can be accessed with safe code.
///
/// ***Internal trait, see `RawData`.***
pub unsafe trait Data : RawData {
/// Converts the array to a uniquely owned array, cloning elements if necessary.
#[doc(hidden)]
fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
Self::Elem: Clone,
D: Dimension;

private_decl!{}
}

/// Array representation trait.
///
/// For an array with writable elements.
/// For an array with writable elements that can be accessed with safe code.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataMut : Data {
//
// # For implementers
//
// If you implement the `DataMut` trait, you are guaranteeing that the
// `RawDataMut::try_ensure_unique` implementation always panics or ensures that
// the data is unique. You are also guaranteeing that `try_is_unique` always
// returns `Some(_)`.
pub unsafe trait DataMut : Data + RawDataMut {
/// Ensures that the array has unique access to its data.
#[doc(hidden)]
#[inline]
fn ensure_unique<D>(&mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{ }
fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{
Self::try_ensure_unique(self_)
}

/// Returns whether the array has unique access to its data.
#[doc(hidden)]
#[inline]
fn is_unique(&mut self) -> bool {
true
self.try_is_unique().unwrap()
}
}

/// Array representation trait.
///
/// An array representation that can be cloned.
/// An array representation that can be cloned and allows elements to be
/// accessed with safe code.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataClone : Data {
#[doc(hidden)]
/// Unsafe because, `ptr` must point inside the current storage.
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
#[deprecated(note="use `Data + RawDataClone` instead", since="0.13")]
pub trait DataClone : Data + RawDataClone {}

#[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
#[allow(deprecated)]
impl<T> DataClone for T where T: Data + RawDataClone {}

unsafe impl<A> RawData for RawViewRepr<*const A> {
type Elem = A;
fn _data_slice(&self) -> Option<&[A]> {
None
}
private_impl!{}
}

unsafe impl<A> Data for OwnedArcRepr<A> {
unsafe impl<A> RawDataClone for RawViewRepr<*const A> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
(*self, ptr)
}
}

unsafe impl<A> RawData for RawViewRepr<*mut A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&self.0
fn _data_slice(&self) -> Option<&[A]> {
None
}
fn into_owned<D>(mut self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
A: Clone,
D: Dimension,
{
Self::ensure_unique(&mut self_);
let data = OwnedRepr(Arc::try_unwrap(self_.data.0).ok().unwrap());
ArrayBase {
data: data,
ptr: self_.ptr,
dim: self_.dim,
strides: self_.strides,
}
private_impl!{}
}

unsafe impl<A> RawDataMut for RawViewRepr<*mut A> {
#[inline]
fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{}

#[inline]
fn try_is_unique(&mut self) -> Option<bool> {
None
}
}

unsafe impl<A> RawDataClone for RawViewRepr<*mut A> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
(*self, ptr)
}
}

unsafe impl<A> RawData for OwnedArcRepr<A> {
type Elem = A;
fn _data_slice(&self) -> Option<&[A]> {
Some(&self.0)
}
private_impl!{}
}

// NOTE: Copy on write
unsafe impl<A> DataMut for OwnedArcRepr<A>
where A: Clone
unsafe impl<A> RawDataMut for OwnedArcRepr<A>
where
A: Clone,
{
fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
fn try_ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{
Expand Down Expand Up @@ -136,23 +222,59 @@ unsafe impl<A> DataMut for OwnedArcRepr<A>
}
}

fn is_unique(&mut self) -> bool {
Arc::get_mut(&mut self.0).is_some()
fn try_is_unique(&mut self) -> Option<bool> {
Some(Arc::get_mut(&mut self.0).is_some())
}
}

unsafe impl<A> DataClone for OwnedArcRepr<A> {
unsafe impl<A> Data for OwnedArcRepr<A> {
fn into_owned<D>(mut self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
A: Clone,
D: Dimension,
{
Self::ensure_unique(&mut self_);
let data = OwnedRepr(Arc::try_unwrap(self_.data.0).ok().unwrap());
ArrayBase {
data: data,
ptr: self_.ptr,
dim: self_.dim,
strides: self_.strides,
}
}
}

unsafe impl<A> DataMut for OwnedArcRepr<A> where A: Clone {}

unsafe impl<A> RawDataClone for OwnedArcRepr<A> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
// pointer is preserved
(self.clone(), ptr)
}
}

unsafe impl<A> Data for OwnedRepr<A> {
unsafe impl<A> RawData for OwnedRepr<A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&self.0
fn _data_slice(&self) -> Option<&[A]> {
Some(&self.0)
}
private_impl!{}
}

unsafe impl<A> RawDataMut for OwnedRepr<A> {
#[inline]
fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension
{}

#[inline]
fn try_is_unique(&mut self) -> Option<bool> {
Some(true)
}
}

unsafe impl<A> Data for OwnedRepr<A> {
#[inline]
fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
Expand All @@ -161,12 +283,11 @@ unsafe impl<A> Data for OwnedRepr<A> {
{
self_
}
private_impl!{}
}

unsafe impl<A> DataMut for OwnedRepr<A> { }

unsafe impl<A> DataClone for OwnedRepr<A>
unsafe impl<A> RawDataClone for OwnedRepr<A>
where A: Clone
{
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem) {
Expand All @@ -192,40 +313,58 @@ unsafe impl<A> DataClone for OwnedRepr<A>
}
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
unsafe impl<'a, A> RawData for ViewRepr<&'a A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&[]
fn _data_slice(&self) -> Option<&[A]> {
None
}
private_impl!{}
}

unsafe impl<'a, A> Data for ViewRepr<&'a A> {
fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
Self::Elem: Clone,
D: Dimension,
{
self_.to_owned()
}
private_impl!{}
}

unsafe impl<'a, A> DataClone for ViewRepr<&'a A> {
unsafe impl<'a, A> RawDataClone 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> {
unsafe impl<'a, A> RawData for ViewRepr<&'a mut A> {
type Elem = A;
fn _data_slice(&self) -> &[A] {
&[]
fn _data_slice(&self) -> Option<&[A]> {
None
}
private_impl!{}
}

unsafe impl<'a, A> RawDataMut for ViewRepr<&'a mut A> {
#[inline]
fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
where Self: Sized,
D: Dimension {}

#[inline]
fn try_is_unique(&mut self) -> Option<bool> {
Some(true)
}
}

unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
where
Self::Elem: Clone,
D: Dimension,
{
self_.to_owned()
}
private_impl!{}
}

unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> { }
Expand All @@ -250,7 +389,7 @@ pub unsafe trait DataOwned : Data {
/// A representation that is a lightweight view.
///
/// ***Internal trait, see `Data`.***
pub unsafe trait DataShared : Clone + DataClone { }
pub unsafe trait DataShared : Clone + Data + RawDataClone { }

unsafe impl<A> DataShared for OwnedRcRepr<A> {}
unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}
Expand Down

0 comments on commit d8078f6

Please sign in to comment.