Thanks to visit codestin.com
Credit goes to docs.rs

ndarray/
impl_ref_types.rs

1//! Implementations that connect arrays to their reference types.
2//!
3//! `ndarray` has four kinds of array types that users may interact with:
4//!     1. [`ArrayBase`], which represents arrays which own their layout (shape and strides)
5//!     2. [`ArrayRef`], which represents a read-safe, uniquely-owned look at an array
6//!     3. [`RawRef`], which represents a read-unsafe, possibly-shared look at an array
7//!     4. [`LayoutRef`], which represents a look at an array's underlying structure,
8//!         but does not allow data reading of any kind
9//!
10//! These types are connected through a number of `Deref` and `AsRef` implementations.
11//!     1. `ArrayBase<S, D>` dereferences to `ArrayRef` when `S: Data`
12//!     2. `ArrayBase<S, D>` mutably dereferences to `ArrayRef` when `S: DataMut`, and ensures uniqueness
13//!     3. `ArrayRef` mutably dereferences to `RawRef`
14//!     4. `RawRef` mutably dereferences to `LayoutRef`
15//! This chain works very well for arrays whose data is safe to read and is uniquely held.
16//! Because raw views do not meet `S: Data`, they cannot dereference to `ArrayRef`; furthermore,
17//! technical limitations of Rust's compiler means that `ArrayBase` cannot have multiple `Deref` implementations.
18//! In addition, shared-data arrays do not want to go down the `Deref` path to get to methods on `RawRef`
19//! or `LayoutRef`, since that would unecessarily ensure their uniqueness.
20//!
21//! To mitigate these problems, `ndarray` also provides `AsRef` and `AsMut` implementations as follows:
22//!     1. `ArrayBase` implements `AsRef` to `RawRef` and `LayoutRef` when `S: RawData`
23//!     2. `ArrayBase` implements `AsMut` to `RawRef` when `S: RawDataMut`
24//!     3. `ArrayBase` implements `AsRef` and `AsMut` to `LayoutRef` unconditionally
25//!     4. `ArrayRef` implements `AsRef` and `AsMut` to `RawRef` and `LayoutRef` unconditionally
26//!     5. `RawRef` implements `AsRef` and `AsMut` to `LayoutRef`
27//!     6. `RawRef` and `LayoutRef` implement `AsRef` and `AsMut` to themselves
28//!
29//! This allows users to write a single method or trait implementation that takes `T: AsRef<RawRef<A, D>>`
30//! or `T: AsRef<LayoutRef<A, D>>` and have that functionality work on any of the relevant array types.
31
32use alloc::borrow::ToOwned;
33use core::{
34    borrow::{Borrow, BorrowMut},
35    ops::{Deref, DerefMut},
36};
37
38use crate::{
39    Array,
40    ArrayBase,
41    ArrayPartsSized,
42    ArrayPartsUnsized,
43    ArrayRef,
44    Data,
45    DataMut,
46    Dimension,
47    LayoutRef,
48    RawData,
49    RawDataMut,
50    RawRef,
51};
52
53// D1: &ArrayBase -> &ArrayRef when data is safe to read
54impl<S, D> Deref for ArrayBase<S, D>
55where S: Data
56{
57    type Target = ArrayRef<S::Elem, D>;
58
59    fn deref(&self) -> &Self::Target
60    {
61        // SAFETY:
62        // - The pointer is aligned because neither type uses repr(align)
63        // - It is "dereferencable" because it comes from a reference
64        // - For the same reason, it is initialized
65        // - The cast is valid because ArrayRef uses #[repr(transparent)]
66        let parts: &ArrayPartsUnsized<S::Elem, D> = &self.parts;
67        let ptr = (parts as *const ArrayPartsUnsized<S::Elem, D>) as *const ArrayRef<S::Elem, D>;
68        unsafe { &*ptr }
69    }
70}
71
72// D2: &mut ArrayBase -> &mut ArrayRef when data is safe to read; ensure uniqueness
73impl<S, D> DerefMut for ArrayBase<S, D>
74where
75    S: DataMut,
76    D: Dimension,
77{
78    fn deref_mut(&mut self) -> &mut Self::Target
79    {
80        self.ensure_unique();
81        // SAFETY:
82        // - The pointer is aligned because neither type uses repr(align)
83        // - It is "dereferencable" because it comes from a reference
84        // - For the same reason, it is initialized
85        // - The cast is valid because ArrayRef uses #[repr(transparent)]
86        let parts: &mut ArrayPartsUnsized<S::Elem, D> = &mut self.parts;
87        let ptr = (parts as *mut ArrayPartsUnsized<S::Elem, D>) as *mut ArrayRef<S::Elem, D>;
88        unsafe { &mut *ptr }
89    }
90}
91
92// D3: &ArrayRef -> &RawRef
93impl<A, D> Deref for ArrayRef<A, D>
94{
95    type Target = RawRef<A, D>;
96
97    fn deref(&self) -> &Self::Target
98    {
99        // SAFETY:
100        // - The pointer is aligned because neither type uses repr(align)
101        // - It is "dereferencable" because it comes from a reference
102        // - For the same reason, it is initialized
103        // - The cast is valid because ArrayRef uses #[repr(transparent)]
104        unsafe { &*((self as *const ArrayRef<A, D>) as *const RawRef<A, D>) }
105    }
106}
107
108// D4: &mut ArrayRef -> &mut RawRef
109impl<A, D> DerefMut for ArrayRef<A, D>
110{
111    fn deref_mut(&mut self) -> &mut Self::Target
112    {
113        // SAFETY:
114        // - The pointer is aligned because neither type uses repr(align)
115        // - It is "dereferencable" because it comes from a reference
116        // - For the same reason, it is initialized
117        // - The cast is valid because ArrayRef uses #[repr(transparent)]
118        unsafe { &mut *((self as *mut ArrayRef<A, D>) as *mut RawRef<A, D>) }
119    }
120}
121
122// D5: &RawRef -> &LayoutRef
123impl<A, D> Deref for RawRef<A, D>
124{
125    type Target = LayoutRef<A, D>;
126
127    fn deref(&self) -> &Self::Target
128    {
129        &self.0
130    }
131}
132
133// D5: &mut RawRef -> &mut LayoutRef
134impl<A, D> DerefMut for RawRef<A, D>
135{
136    fn deref_mut(&mut self) -> &mut Self::Target
137    {
138        &mut self.0
139    }
140}
141
142// A1: &ArrayBase -AR-> &RawRef
143impl<A, S, D> AsRef<RawRef<A, D>> for ArrayBase<S, D>
144where S: RawData<Elem = A>
145{
146    fn as_ref(&self) -> &RawRef<A, D>
147    {
148        // SAFETY:
149        // - The pointer is aligned because neither type uses repr(align)
150        // - It is "dereferencable" because it comes from a reference
151        // - For the same reason, it is initialized
152        // - The cast is valid because ArrayRef uses #[repr(transparent)]
153        let parts: &ArrayPartsUnsized<S::Elem, D> = &self.parts;
154        let ptr = (parts as *const ArrayPartsUnsized<S::Elem, D>) as *const RawRef<S::Elem, D>;
155        unsafe { &*ptr }
156    }
157}
158
159// A2: &mut ArrayBase -AM-> &mut RawRef
160impl<A, S, D> AsMut<RawRef<A, D>> for ArrayBase<S, D>
161where S: RawDataMut<Elem = A>
162{
163    fn as_mut(&mut self) -> &mut RawRef<A, D>
164    {
165        // SAFETY:
166        // - The pointer is aligned because neither type uses repr(align)
167        // - It is "dereferencable" because it comes from a reference
168        // - For the same reason, it is initialized
169        // - The cast is valid because ArrayRef uses #[repr(transparent)]
170        let parts: &mut ArrayPartsUnsized<S::Elem, D> = &mut self.parts;
171        let ptr = (parts as *mut ArrayPartsUnsized<S::Elem, D>) as *mut RawRef<S::Elem, D>;
172        unsafe { &mut *ptr }
173    }
174}
175
176// A3: &ArrayBase -AR-> &LayoutRef
177impl<A, S, D> AsRef<LayoutRef<A, D>> for ArrayBase<S, D>
178where S: RawData<Elem = A>
179{
180    fn as_ref(&self) -> &LayoutRef<A, D>
181    {
182        let parts: &ArrayPartsUnsized<S::Elem, D> = &self.parts;
183        let ptr = (parts as *const ArrayPartsUnsized<S::Elem, D>) as *const LayoutRef<S::Elem, D>;
184        unsafe { &*ptr }
185    }
186}
187
188// A3: &mut ArrayBase -AM-> &mut LayoutRef
189impl<A, S, D> AsMut<LayoutRef<A, D>> for ArrayBase<S, D>
190where S: RawData<Elem = A>
191{
192    fn as_mut(&mut self) -> &mut LayoutRef<A, D>
193    {
194        let parts: &mut ArrayPartsUnsized<S::Elem, D> = &mut self.parts;
195        let ptr = (parts as *mut ArrayPartsUnsized<S::Elem, D>) as *mut LayoutRef<S::Elem, D>;
196        unsafe { &mut *ptr }
197    }
198}
199
200// A4: &ArrayRef -AR-> &RawRef
201impl<A, D> AsRef<RawRef<A, D>> for ArrayRef<A, D>
202{
203    fn as_ref(&self) -> &RawRef<A, D>
204    {
205        self
206    }
207}
208
209// A4: &mut ArrayRef -AM-> &mut RawRef
210impl<A, D> AsMut<RawRef<A, D>> for ArrayRef<A, D>
211{
212    fn as_mut(&mut self) -> &mut RawRef<A, D>
213    {
214        self
215    }
216}
217
218// A4: &ArrayRef -AR-> &LayoutRef
219impl<A, D> AsRef<LayoutRef<A, D>> for ArrayRef<A, D>
220{
221    fn as_ref(&self) -> &LayoutRef<A, D>
222    {
223        self
224    }
225}
226
227// A4: &mut ArrayRef -AM-> &mut LayoutRef
228impl<A, D> AsMut<LayoutRef<A, D>> for ArrayRef<A, D>
229{
230    fn as_mut(&mut self) -> &mut LayoutRef<A, D>
231    {
232        self
233    }
234}
235
236// A5: &RawRef -AR-> &LayoutRef
237impl<A, D> AsRef<LayoutRef<A, D>> for RawRef<A, D>
238{
239    fn as_ref(&self) -> &LayoutRef<A, D>
240    {
241        self
242    }
243}
244
245// A5: &mut RawRef -AM-> &mut LayoutRef
246impl<A, D> AsMut<LayoutRef<A, D>> for RawRef<A, D>
247{
248    fn as_mut(&mut self) -> &mut LayoutRef<A, D>
249    {
250        self
251    }
252}
253
254// A6: &RawRef -AR-> &RawRef
255impl<A, D> AsRef<RawRef<A, D>> for RawRef<A, D>
256{
257    fn as_ref(&self) -> &RawRef<A, D>
258    {
259        self
260    }
261}
262
263// A6: &mut RawRef -AM-> &mut RawRef
264impl<A, D> AsMut<RawRef<A, D>> for RawRef<A, D>
265{
266    fn as_mut(&mut self) -> &mut RawRef<A, D>
267    {
268        self
269    }
270}
271
272// A6: &LayoutRef -AR-> &LayoutRef
273impl<A, D> AsRef<LayoutRef<A, D>> for LayoutRef<A, D>
274{
275    fn as_ref(&self) -> &LayoutRef<A, D>
276    {
277        self
278    }
279}
280
281// A6: &mut LayoutRef -AR-> &mut LayoutRef
282impl<A, D> AsMut<LayoutRef<A, D>> for LayoutRef<A, D>
283{
284    fn as_mut(&mut self) -> &mut LayoutRef<A, D>
285    {
286        self
287    }
288}
289
290/// # Safety
291///
292/// Usually the pointer would be bad to just clone, as we'd have aliasing
293/// and completely separated references to the same data. However, it is
294/// impossible to read the data behind the pointer from a LayoutRef (this
295/// is a safety invariant that *must* be maintained), and therefore we can
296/// Clone and Copy as desired.
297impl<A, D: Clone> Clone for ArrayPartsSized<A, D>
298{
299    fn clone(&self) -> Self
300    {
301        Self {
302            dim: self.dim.clone(),
303            strides: self.strides.clone(),
304            ptr: self.ptr,
305            _dst_control: [0; 0],
306        }
307    }
308}
309
310impl<A, D: Clone + Copy> Copy for ArrayPartsSized<A, D> {}
311
312impl<S, D> Borrow<RawRef<S::Elem, D>> for ArrayBase<S, D>
313where S: RawData
314{
315    fn borrow(&self) -> &RawRef<S::Elem, D>
316    {
317        self.as_ref()
318    }
319}
320
321impl<S, D> BorrowMut<RawRef<S::Elem, D>> for ArrayBase<S, D>
322where S: RawDataMut
323{
324    fn borrow_mut(&mut self) -> &mut RawRef<S::Elem, D>
325    {
326        self.as_mut()
327    }
328}
329
330impl<S, D> Borrow<ArrayRef<S::Elem, D>> for ArrayBase<S, D>
331where S: Data
332{
333    fn borrow(&self) -> &ArrayRef<S::Elem, D>
334    {
335        self
336    }
337}
338
339impl<S, D> BorrowMut<ArrayRef<S::Elem, D>> for ArrayBase<S, D>
340where
341    S: DataMut,
342    D: Dimension,
343{
344    fn borrow_mut(&mut self) -> &mut ArrayRef<S::Elem, D>
345    {
346        self
347    }
348}
349
350impl<A, D> ToOwned for ArrayRef<A, D>
351where
352    A: Clone,
353    D: Dimension,
354{
355    type Owned = Array<A, D>;
356
357    fn to_owned(&self) -> Self::Owned
358    {
359        self.to_owned()
360    }
361
362    fn clone_into(&self, target: &mut Array<A, D>)
363    {
364        target.zip_mut_with(self, |tgt, src| tgt.clone_from(src));
365    }
366}
367
368/// Shortcuts for the various as_ref calls
369impl<A, S, D> ArrayBase<S, D>
370where S: RawData<Elem = A>
371{
372    /// Cheaply convert a reference to the array to an &LayoutRef
373    pub fn as_layout_ref(&self) -> &LayoutRef<A, D>
374    {
375        self.as_ref()
376    }
377
378    /// Cheaply and mutably convert a reference to the array to an &LayoutRef
379    pub fn as_layout_ref_mut(&mut self) -> &mut LayoutRef<A, D>
380    {
381        self.as_mut()
382    }
383
384    /// Cheaply convert a reference to the array to an &RawRef
385    pub fn as_raw_ref(&self) -> &RawRef<A, D>
386    {
387        self.as_ref()
388    }
389
390    /// Cheaply and mutably convert a reference to the array to an &RawRef
391    pub fn as_raw_ref_mut(&mut self) -> &mut RawRef<A, D>
392    where S: RawDataMut<Elem = A>
393    {
394        self.as_mut()
395    }
396}
397
398/// Tests that a mem::swap can't compile by putting it into a doctest
399///
400/// ```compile_fail
401/// let mut x = Array1::from_vec(vec![0, 1, 2]);
402/// {
403///     let mut y = Array1::from_vec(vec![4, 5, 6]);
404///     let x_ref = x.as_layout_ref_mut();
405///     let y_ref = y.as_layout_ref_mut();
406///     core::mem::swap(x_ref, y_ref);
407/// }
408/// ```
409#[allow(dead_code)]
410fn test_no_swap_via_doctests() {}