ndarray/
data_traits.rs

1// Copyright 2014-2016 bluss and ndarray developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9//! The data (inner representation) traits for ndarray
10
11use rawpointer::PointerExt;
12
13use std::mem::{self, size_of};
14use std::mem::MaybeUninit;
15use std::ptr::NonNull;
16use alloc::sync::Arc;
17use alloc::vec::Vec;
18
19use crate::{ArrayBase, CowRepr, Dimension, OwnedArcRepr, OwnedRepr, RawViewRepr, ViewRepr};
20
21/// Array representation trait.
22///
23/// For an array that meets the invariants of the `ArrayBase` type. This trait
24/// does not imply any ownership or lifetime; pointers to elements in the array
25/// may not be safe to dereference.
26///
27/// ***Note:*** `RawData` is not an extension interface at this point.
28/// Traits in Rust can serve many different roles. This trait is public because
29/// it is used as a bound on public methods.
30pub unsafe trait RawData: Sized {
31    /// The array element type.
32    type Elem;
33
34    #[doc(hidden)]
35    // This method is only used for debugging
36    fn _data_slice(&self) -> Option<&[Self::Elem]>;
37
38    private_decl! {}
39}
40
41/// Array representation trait.
42///
43/// For an array with writable elements.
44///
45/// ***Internal trait, see `RawData`.***
46pub unsafe trait RawDataMut: RawData {
47    /// If possible, ensures that the array has unique access to its data.
48    ///
49    /// If `Self` provides safe mutable access to array elements, then it
50    /// **must** panic or ensure that the data is unique.
51    #[doc(hidden)]
52    fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
53    where
54        Self: Sized,
55        D: Dimension;
56
57    /// If possible, returns whether the array has unique access to its data.
58    ///
59    /// If `Self` provides safe mutable access to array elements, then it
60    /// **must** return `Some(_)`.
61    #[doc(hidden)]
62    fn try_is_unique(&mut self) -> Option<bool>;
63}
64
65/// Array representation trait.
66///
67/// An array representation that can be cloned.
68///
69/// ***Internal trait, see `RawData`.***
70pub unsafe trait RawDataClone: RawData {
71    #[doc(hidden)]
72    /// Unsafe because, `ptr` must point inside the current storage.
73    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>);
74
75    #[doc(hidden)]
76    unsafe fn clone_from_with_ptr(
77        &mut self,
78        other: &Self,
79        ptr: NonNull<Self::Elem>,
80    ) -> NonNull<Self::Elem> {
81        let (data, ptr) = other.clone_with_ptr(ptr);
82        *self = data;
83        ptr
84    }
85}
86
87/// Array representation trait.
88///
89/// For an array with elements that can be accessed with safe code.
90///
91/// ***Internal trait, see `RawData`.***
92pub unsafe trait Data: RawData {
93    /// Converts the array to a uniquely owned array, cloning elements if necessary.
94    #[doc(hidden)]
95    #[allow(clippy::wrong_self_convention)]
96    fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
97    where
98        Self::Elem: Clone,
99        D: Dimension;
100
101    /// Return a shared ownership (copy on write) array based on the existing one,
102    /// cloning elements if necessary.
103    #[doc(hidden)]
104    #[allow(clippy::wrong_self_convention)]
105    fn to_shared<D>(self_: &ArrayBase<Self, D>) -> ArrayBase<OwnedArcRepr<Self::Elem>, D>
106    where
107        Self::Elem: Clone,
108        D: Dimension,
109    {
110        // clone to shared
111        self_.to_owned().into_shared()
112    }
113}
114
115/// Array representation trait.
116///
117/// For an array with writable elements that can be accessed with safe code.
118///
119/// ***Internal trait, see `Data`.***
120//
121// # For implementers
122//
123// If you implement the `DataMut` trait, you are guaranteeing that the
124// `RawDataMut::try_ensure_unique` implementation always panics or ensures that
125// the data is unique. You are also guaranteeing that `try_is_unique` always
126// returns `Some(_)`.
127pub unsafe trait DataMut: Data + RawDataMut {
128    /// Ensures that the array has unique access to its data.
129    #[doc(hidden)]
130    #[inline]
131    fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
132    where
133        Self: Sized,
134        D: Dimension,
135    {
136        Self::try_ensure_unique(self_)
137    }
138
139    /// Returns whether the array has unique access to its data.
140    #[doc(hidden)]
141    #[inline]
142    fn is_unique(&mut self) -> bool {
143        self.try_is_unique().unwrap()
144    }
145}
146
147unsafe impl<A> RawData for RawViewRepr<*const A> {
148    type Elem = A;
149    fn _data_slice(&self) -> Option<&[A]> {
150        None
151    }
152    private_impl! {}
153}
154
155unsafe impl<A> RawDataClone for RawViewRepr<*const A> {
156    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>) {
157        (*self, ptr)
158    }
159}
160
161unsafe impl<A> RawData for RawViewRepr<*mut A> {
162    type Elem = A;
163    fn _data_slice(&self) -> Option<&[A]> {
164        None
165    }
166    private_impl! {}
167}
168
169unsafe impl<A> RawDataMut for RawViewRepr<*mut A> {
170    #[inline]
171    fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
172    where
173        Self: Sized,
174        D: Dimension,
175    {
176    }
177
178    #[inline]
179    fn try_is_unique(&mut self) -> Option<bool> {
180        None
181    }
182}
183
184unsafe impl<A> RawDataClone for RawViewRepr<*mut A> {
185    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>) {
186        (*self, ptr)
187    }
188}
189
190unsafe impl<A> RawData for OwnedArcRepr<A> {
191    type Elem = A;
192    fn _data_slice(&self) -> Option<&[A]> {
193        Some(self.0.as_slice())
194    }
195    private_impl! {}
196}
197
198// NOTE: Copy on write
199unsafe impl<A> RawDataMut for OwnedArcRepr<A>
200where
201    A: Clone,
202{
203    fn try_ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
204    where
205        Self: Sized,
206        D: Dimension,
207    {
208        if Arc::get_mut(&mut self_.data.0).is_some() {
209            return;
210        }
211        if self_.dim.size() <= self_.data.0.len() / 2 {
212            // Create a new vec if the current view is less than half of
213            // backing data.
214            unsafe {
215                *self_ = ArrayBase::from_shape_vec_unchecked(
216                    self_.dim.clone(),
217                    self_.iter().cloned().collect(),
218                );
219            }
220            return;
221        }
222        let rcvec = &mut self_.data.0;
223        let a_size = mem::size_of::<A>() as isize;
224        let our_off = if a_size != 0 {
225            (self_.ptr.as_ptr() as isize - rcvec.as_ptr() as isize) / a_size
226        } else {
227            0
228        };
229        let rvec = Arc::make_mut(rcvec);
230        unsafe {
231            self_.ptr = rvec.as_nonnull_mut().offset(our_off);
232        }
233    }
234
235    fn try_is_unique(&mut self) -> Option<bool> {
236        Some(Arc::get_mut(&mut self.0).is_some())
237    }
238}
239
240unsafe impl<A> Data for OwnedArcRepr<A> {
241    fn into_owned<D>(mut self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
242    where
243        A: Clone,
244        D: Dimension,
245    {
246        Self::ensure_unique(&mut self_);
247        let data = Arc::try_unwrap(self_.data.0).ok().unwrap();
248        // safe because data is equivalent
249        unsafe {
250            ArrayBase::from_data_ptr(data, self_.ptr)
251                .with_strides_dim(self_.strides, self_.dim)
252        }
253    }
254
255    fn to_shared<D>(self_: &ArrayBase<Self, D>) -> ArrayBase<OwnedArcRepr<Self::Elem>, D>
256    where
257        Self::Elem: Clone,
258        D: Dimension,
259    {
260        // to shared using clone of OwnedArcRepr without clone of raw data.
261        self_.clone()
262    }
263}
264
265unsafe impl<A> DataMut for OwnedArcRepr<A> where A: Clone {}
266
267unsafe impl<A> RawDataClone for OwnedArcRepr<A> {
268    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>) {
269        // pointer is preserved
270        (self.clone(), ptr)
271    }
272}
273
274unsafe impl<A> RawData for OwnedRepr<A> {
275    type Elem = A;
276    fn _data_slice(&self) -> Option<&[A]> {
277        Some(self.as_slice())
278    }
279    private_impl! {}
280}
281
282unsafe impl<A> RawDataMut for OwnedRepr<A> {
283    #[inline]
284    fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
285    where
286        Self: Sized,
287        D: Dimension,
288    {
289    }
290
291    #[inline]
292    fn try_is_unique(&mut self) -> Option<bool> {
293        Some(true)
294    }
295}
296
297unsafe impl<A> Data for OwnedRepr<A> {
298    #[inline]
299    fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
300    where
301        A: Clone,
302        D: Dimension,
303    {
304        self_
305    }
306}
307
308unsafe impl<A> DataMut for OwnedRepr<A> {}
309
310unsafe impl<A> RawDataClone for OwnedRepr<A>
311where
312    A: Clone,
313{
314    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>) {
315        let mut u = self.clone();
316        let mut new_ptr = u.as_nonnull_mut();
317        if size_of::<A>() != 0 {
318            let our_off =
319                (ptr.as_ptr() as isize - self.as_ptr() as isize) / mem::size_of::<A>() as isize;
320            new_ptr = new_ptr.offset(our_off);
321        }
322        (u, new_ptr)
323    }
324
325    unsafe fn clone_from_with_ptr(
326        &mut self,
327        other: &Self,
328        ptr: NonNull<Self::Elem>,
329    ) -> NonNull<Self::Elem> {
330        let our_off = if size_of::<A>() != 0 {
331            (ptr.as_ptr() as isize - other.as_ptr() as isize) / mem::size_of::<A>() as isize
332        } else {
333            0
334        };
335        self.clone_from(&other);
336        self.as_nonnull_mut().offset(our_off)
337    }
338}
339
340unsafe impl<'a, A> RawData for ViewRepr<&'a A> {
341    type Elem = A;
342    fn _data_slice(&self) -> Option<&[A]> {
343        None
344    }
345    private_impl! {}
346}
347
348unsafe impl<'a, A> Data for ViewRepr<&'a A> {
349    fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
350    where
351        Self::Elem: Clone,
352        D: Dimension,
353    {
354        self_.to_owned()
355    }
356}
357
358unsafe impl<'a, A> RawDataClone for ViewRepr<&'a A> {
359    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>) {
360        (*self, ptr)
361    }
362}
363
364unsafe impl<'a, A> RawData for ViewRepr<&'a mut A> {
365    type Elem = A;
366    fn _data_slice(&self) -> Option<&[A]> {
367        None
368    }
369    private_impl! {}
370}
371
372unsafe impl<'a, A> RawDataMut for ViewRepr<&'a mut A> {
373    #[inline]
374    fn try_ensure_unique<D>(_: &mut ArrayBase<Self, D>)
375    where
376        Self: Sized,
377        D: Dimension,
378    {
379    }
380
381    #[inline]
382    fn try_is_unique(&mut self) -> Option<bool> {
383        Some(true)
384    }
385}
386
387unsafe impl<'a, A> Data for ViewRepr<&'a mut A> {
388    fn into_owned<D>(self_: ArrayBase<Self, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
389    where
390        Self::Elem: Clone,
391        D: Dimension,
392    {
393        self_.to_owned()
394    }
395}
396
397unsafe impl<'a, A> DataMut for ViewRepr<&'a mut A> {}
398
399/// Array representation trait.
400///
401/// A representation that is a unique or shared owner of its data.
402///
403/// ***Internal trait, see `Data`.***
404// The owned storage represents the ownership and allocation of the array's elements.
405// The storage may be unique or shared ownership style; it must be an aliasable owner
406// (permit aliasing pointers, such as our separate array head pointer).
407//
408// The array storage must be initially mutable - copy on write arrays may require copying for
409// unsharing storage before mutating it. The initially allocated storage must be mutable so
410// that it can be mutated directly - through .raw_view_mut_unchecked() - for initialization.
411pub unsafe trait DataOwned: Data {
412    /// Corresponding owned data with MaybeUninit elements
413    type MaybeUninit: DataOwned<Elem = MaybeUninit<Self::Elem>>
414        + RawDataSubst<Self::Elem, Output=Self>;
415    #[doc(hidden)]
416    fn new(elements: Vec<Self::Elem>) -> Self;
417
418    /// Converts the data representation to a shared (copy on write)
419    /// representation, without any copying.
420    #[doc(hidden)]
421    fn into_shared(self) -> OwnedArcRepr<Self::Elem>;
422}
423
424/// Array representation trait.
425///
426/// A representation that is a lightweight view.
427///
428/// ***Internal trait, see `Data`.***
429pub unsafe trait DataShared: Clone + Data + RawDataClone {}
430
431unsafe impl<A> DataShared for OwnedArcRepr<A> {}
432unsafe impl<'a, A> DataShared for ViewRepr<&'a A> {}
433
434unsafe impl<A> DataOwned for OwnedRepr<A> {
435    type MaybeUninit = OwnedRepr<MaybeUninit<A>>;
436
437    fn new(elements: Vec<A>) -> Self {
438        OwnedRepr::from(elements)
439    }
440
441    fn into_shared(self) -> OwnedArcRepr<A> {
442        OwnedArcRepr(Arc::new(self))
443    }
444}
445
446unsafe impl<A> DataOwned for OwnedArcRepr<A> {
447    type MaybeUninit = OwnedArcRepr<MaybeUninit<A>>;
448
449    fn new(elements: Vec<A>) -> Self {
450        OwnedArcRepr(Arc::new(OwnedRepr::from(elements)))
451    }
452
453    fn into_shared(self) -> OwnedArcRepr<A> {
454        self
455    }
456}
457
458unsafe impl<'a, A> RawData for CowRepr<'a, A> {
459    type Elem = A;
460    fn _data_slice(&self) -> Option<&[A]> {
461        match self {
462            CowRepr::View(view) => view._data_slice(),
463            CowRepr::Owned(data) => data._data_slice(),
464        }
465    }
466    private_impl! {}
467}
468
469unsafe impl<'a, A> RawDataMut for CowRepr<'a, A>
470where
471    A: Clone,
472{
473    #[inline]
474    fn try_ensure_unique<D>(array: &mut ArrayBase<Self, D>)
475    where
476        Self: Sized,
477        D: Dimension,
478    {
479        match array.data {
480            CowRepr::View(_) => {
481                let owned = array.to_owned();
482                array.data = CowRepr::Owned(owned.data);
483                array.ptr = owned.ptr;
484                array.dim = owned.dim;
485                array.strides = owned.strides;
486            }
487            CowRepr::Owned(_) => {}
488        }
489    }
490
491    #[inline]
492    fn try_is_unique(&mut self) -> Option<bool> {
493        Some(self.is_owned())
494    }
495}
496
497unsafe impl<'a, A> RawDataClone for CowRepr<'a, A>
498where
499    A: Clone,
500{
501    unsafe fn clone_with_ptr(&self, ptr: NonNull<Self::Elem>) -> (Self, NonNull<Self::Elem>) {
502        match self {
503            CowRepr::View(view) => {
504                let (new_view, ptr) = view.clone_with_ptr(ptr);
505                (CowRepr::View(new_view), ptr)
506            }
507            CowRepr::Owned(data) => {
508                let (new_data, ptr) = data.clone_with_ptr(ptr);
509                (CowRepr::Owned(new_data), ptr)
510            }
511        }
512    }
513
514    #[doc(hidden)]
515    unsafe fn clone_from_with_ptr(
516        &mut self,
517        other: &Self,
518        ptr: NonNull<Self::Elem>,
519    ) -> NonNull<Self::Elem> {
520        match (&mut *self, other) {
521            (CowRepr::View(self_), CowRepr::View(other)) => self_.clone_from_with_ptr(other, ptr),
522            (CowRepr::Owned(self_), CowRepr::Owned(other)) => self_.clone_from_with_ptr(other, ptr),
523            (_, CowRepr::Owned(other)) => {
524                let (cloned, ptr) = other.clone_with_ptr(ptr);
525                *self = CowRepr::Owned(cloned);
526                ptr
527            }
528            (_, CowRepr::View(other)) => {
529                let (cloned, ptr) = other.clone_with_ptr(ptr);
530                *self = CowRepr::View(cloned);
531                ptr
532            }
533        }
534    }
535}
536
537unsafe impl<'a, A> Data for CowRepr<'a, A> {
538    #[inline]
539    fn into_owned<D>(self_: ArrayBase<CowRepr<'a, A>, D>) -> ArrayBase<OwnedRepr<Self::Elem>, D>
540    where
541        A: Clone,
542        D: Dimension,
543    {
544        match self_.data {
545            CowRepr::View(_) => self_.to_owned(),
546            CowRepr::Owned(data) => unsafe {
547                // safe because the data is equivalent so ptr, dims remain valid
548                ArrayBase::from_data_ptr(data, self_.ptr)
549                    .with_strides_dim(self_.strides, self_.dim)
550            },
551        }
552    }
553}
554
555unsafe impl<'a, A> DataMut for CowRepr<'a, A> where A: Clone {}
556
557/// Array representation trait.
558///
559/// The RawDataSubst trait maps the element type of array storage, while
560/// keeping the same kind of storage.
561///
562/// For example, `RawDataSubst<B>` can map the type `OwnedRepr<A>` to `OwnedRepr<B>`.
563pub trait RawDataSubst<A>: RawData {
564    /// The resulting array storage of the same kind but substituted element type
565    type Output: RawData<Elem = A>;
566
567    /// Unsafely translate the data representation from one element
568    /// representation to another.
569    ///
570    /// ## Safety
571    ///
572    /// Caller must ensure the two types have the same representation.
573    unsafe fn data_subst(self) -> Self::Output;
574}
575
576impl<A, B> RawDataSubst<B> for OwnedRepr<A> {
577    type Output = OwnedRepr<B>;
578
579    unsafe fn data_subst(self) -> Self::Output {
580        self.data_subst()
581    }
582}
583
584impl<A, B> RawDataSubst<B> for OwnedArcRepr<A> {
585    type Output = OwnedArcRepr<B>;
586
587    unsafe fn data_subst(self) -> Self::Output {
588        OwnedArcRepr(Arc::from_raw(Arc::into_raw(self.0) as *const OwnedRepr<B>))
589    }
590}
591
592impl<A, B> RawDataSubst<B> for RawViewRepr<*const A> {
593    type Output = RawViewRepr<*const B>;
594
595    unsafe fn data_subst(self) -> Self::Output {
596        RawViewRepr::new()
597    }
598}
599
600impl<A, B> RawDataSubst<B> for RawViewRepr<*mut A> {
601    type Output = RawViewRepr<*mut B>;
602
603    unsafe fn data_subst(self) -> Self::Output {
604        RawViewRepr::new()
605    }
606}
607
608impl<'a, A: 'a, B: 'a> RawDataSubst<B> for ViewRepr<&'a A> {
609    type Output = ViewRepr<&'a B>;
610
611    unsafe fn data_subst(self) -> Self::Output {
612        ViewRepr::new()
613    }
614}
615
616impl<'a, A: 'a, B: 'a> RawDataSubst<B> for ViewRepr<&'a mut A> {
617    type Output = ViewRepr<&'a mut B>;
618
619    unsafe fn data_subst(self) -> Self::Output {
620        ViewRepr::new()
621    }
622}
623