ndarray/impl_views/
conversions.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
9use alloc::slice;
10use rawpointer::PointerExt;
11use std::mem::MaybeUninit;
12
13use crate::imp_prelude::*;
14
15use crate::{Baseiter, ElementsBase, ElementsBaseMut, Iter, IterMut};
16
17use crate::dimension::offset_from_low_addr_ptr_to_logical_ptr;
18use crate::iter::{self, AxisIter, AxisIterMut};
19use crate::math_cell::MathCell;
20use crate::IndexLonger;
21
22/// Methods for read-only array views.
23impl<'a, A, D> ArrayView<'a, A, D>
24where
25    D: Dimension,
26{
27    /// Convert the view into an `ArrayView<'b, A, D>` where `'b` is a lifetime
28    /// outlived by `'a'`.
29    pub fn reborrow<'b>(self) -> ArrayView<'b, A, D>
30    where
31        'a: 'b,
32    {
33        unsafe { ArrayView::new(self.ptr, self.dim, self.strides) }
34    }
35
36    /// Return the array’s data as a slice, if it is contiguous and in standard order.
37    /// Return `None` otherwise.
38    ///
39    /// Note that while the method is similar to [`ArrayBase::as_slice()`], this method transfers
40    /// the view's lifetime to the slice, so it is a bit more powerful.
41    pub fn to_slice(&self) -> Option<&'a [A]> {
42        if self.is_standard_layout() {
43            unsafe { Some(slice::from_raw_parts(self.ptr.as_ptr(), self.len())) }
44        } else {
45            None
46        }
47    }
48
49    /// Return the array’s data as a slice, if it is contiguous.
50    /// Return `None` otherwise.
51    ///
52    /// Note that while the method is similar to
53    /// [`ArrayBase::as_slice_memory_order()`], this method transfers the view's
54    /// lifetime to the slice, so it is a bit more powerful.
55    pub fn to_slice_memory_order(&self) -> Option<&'a [A]> {
56        if self.is_contiguous() {
57            let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides);
58            unsafe {
59                Some(slice::from_raw_parts(
60                    self.ptr.sub(offset).as_ptr(),
61                    self.len(),
62                ))
63            }
64        } else {
65            None
66        }
67    }
68
69    /// Converts to a raw array view.
70    pub(crate) fn into_raw_view(self) -> RawArrayView<A, D> {
71        unsafe { RawArrayView::new(self.ptr, self.dim, self.strides) }
72    }
73}
74
75/// Methods specific to `ArrayView0`.
76///
77/// ***See also all methods for [`ArrayView`] and [`ArrayBase`]***
78impl<'a, A> ArrayView<'a, A, Ix0> {
79    /// Consume the view and return a reference to the single element in the array.
80    ///
81    /// The lifetime of the returned reference matches the lifetime of the data
82    /// the array view was pointing to.
83    ///
84    /// ```
85    /// use ndarray::{arr0, Array0};
86    ///
87    /// // `Foo` doesn't implement `Clone`.
88    /// #[derive(Debug, Eq, PartialEq)]
89    /// struct Foo;
90    ///
91    /// let array: Array0<Foo> = arr0(Foo);
92    /// let view = array.view();
93    /// let scalar: &Foo = view.into_scalar();
94    /// assert_eq!(scalar, &Foo);
95    /// ```
96    pub fn into_scalar(self) -> &'a A {
97        self.index(Ix0())
98    }
99}
100
101/// Methods specific to `ArrayViewMut0`.
102///
103/// ***See also all methods for [`ArrayViewMut`] and [`ArrayBase`]***
104impl<'a, A> ArrayViewMut<'a, A, Ix0> {
105    /// Consume the mutable view and return a mutable reference to the single element in the array.
106    ///
107    /// The lifetime of the returned reference matches the lifetime of the data
108    /// the array view was pointing to.
109    ///
110    /// ```
111    /// use ndarray::{arr0, Array0};
112    ///
113    /// let mut array: Array0<f64> = arr0(5.);
114    /// let view = array.view_mut();
115    /// let scalar = view.into_scalar();
116    /// *scalar = 7.;
117    /// assert_eq!(scalar, &7.);
118    /// assert_eq!(array[()], 7.);
119    /// ```
120    pub fn into_scalar(self) -> &'a mut A {
121        self.index(Ix0())
122    }
123}
124
125/// Methods for read-write array views.
126impl<'a, A, D> ArrayViewMut<'a, A, D>
127where
128    D: Dimension,
129{
130    /// Return the array’s data as a slice, if it is contiguous and in standard order.
131    /// Return `None` otherwise.
132    ///
133    /// Note that while this is similar to [`ArrayBase::as_slice_mut()`], this method transfers the
134    /// view's lifetime to the slice.
135    pub fn into_slice(self) -> Option<&'a mut [A]> {
136        self.try_into_slice().ok()
137    }
138
139    /// Return the array’s data as a slice, if it is contiguous.
140    /// Return `None` otherwise.
141    ///
142    /// Note that while this is similar to
143    /// [`ArrayBase::as_slice_memory_order_mut()`], this method transfers the
144    /// view's lifetime to the slice.
145    pub fn into_slice_memory_order(self) -> Option<&'a mut [A]> {
146        self.try_into_slice_memory_order().ok()
147    }
148
149    /// Return a shared view of the array with elements as if they were embedded in cells.
150    ///
151    /// The cell view itself can be copied and accessed without exclusivity.
152    ///
153    /// The view acts "as if" the elements are temporarily in cells, and elements
154    /// can be changed through shared references using the regular cell methods.
155    pub fn into_cell_view(self) -> ArrayView<'a, MathCell<A>, D> {
156        // safety: valid because
157        // A and MathCell<A> have the same representation
158        // &'a mut T is interchangeable with &'a Cell<T> -- see method Cell::from_mut in std
159        unsafe {
160            self.into_raw_view_mut().cast::<MathCell<A>>().deref_into_view()
161        }
162    }
163
164    /// Return the array view as a view of `MaybeUninit<A>` elements
165    ///
166    /// This conversion leaves the elements as they were (presumably initialized), but
167    /// they are represented with the `MaybeUninit<A>` type. Effectively this means that
168    /// the elements can be overwritten without dropping the old element in its place.
169    /// (In some situations this is not what you want, while for `Copy` elements it makes
170    /// no difference at all.)
171    ///
172    /// # Safety
173    ///
174    /// This method allows writing uninitialized data into the view, which could leave any
175    /// original array that we borrow from in an inconsistent state. This is not allowed
176    /// when using the resulting array view.
177    pub(crate) unsafe fn into_maybe_uninit(self) -> ArrayViewMut<'a, MaybeUninit<A>, D> {
178        // Safe because: A and MaybeUninit<A> have the same representation;
179        // and we can go from initialized to (maybe) not unconditionally in terms of
180        // representation. However, the user must be careful to not write uninit elements
181        // through the view.
182        self.into_raw_view_mut().cast::<MaybeUninit<A>>().deref_into_view_mut()
183    }
184}
185
186/// Private array view methods
187impl<'a, A, D> ArrayView<'a, A, D>
188where
189    D: Dimension,
190{
191    #[inline]
192    pub(crate) fn into_base_iter(self) -> Baseiter<A, D> {
193        unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) }
194    }
195
196    #[inline]
197    pub(crate) fn into_elements_base(self) -> ElementsBase<'a, A, D> {
198        ElementsBase::new(self)
199    }
200
201    pub(crate) fn into_iter_(self) -> Iter<'a, A, D> {
202        Iter::new(self)
203    }
204
205    /// Return an outer iterator for this view.
206    #[doc(hidden)] // not official
207    #[deprecated(note = "This method will be replaced.")]
208    pub fn into_outer_iter(self) -> iter::AxisIter<'a, A, D::Smaller>
209    where
210        D: RemoveAxis,
211    {
212        AxisIter::new(self, Axis(0))
213    }
214}
215
216impl<'a, A, D> ArrayViewMut<'a, A, D>
217where
218    D: Dimension,
219{
220    // Convert into a read-only view
221    pub(crate) fn into_view(self) -> ArrayView<'a, A, D> {
222        unsafe { ArrayView::new(self.ptr, self.dim, self.strides) }
223    }
224
225    /// Converts to a mutable raw array view.
226    pub(crate) fn into_raw_view_mut(self) -> RawArrayViewMut<A, D> {
227        unsafe { RawArrayViewMut::new(self.ptr, self.dim, self.strides) }
228    }
229
230    #[inline]
231    pub(crate) fn into_base_iter(self) -> Baseiter<A, D> {
232        unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) }
233    }
234
235    #[inline]
236    pub(crate) fn into_elements_base(self) -> ElementsBaseMut<'a, A, D> {
237        ElementsBaseMut::new(self)
238    }
239
240    /// Return the array’s data as a slice, if it is contiguous and in standard order.
241    /// Otherwise return self in the Err branch of the result.
242    pub(crate) fn try_into_slice(self) -> Result<&'a mut [A], Self> {
243        if self.is_standard_layout() {
244            unsafe { Ok(slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len())) }
245        } else {
246            Err(self)
247        }
248    }
249
250    /// Return the array’s data as a slice, if it is contiguous.
251    /// Otherwise return self in the Err branch of the result.
252    fn try_into_slice_memory_order(self) -> Result<&'a mut [A], Self> {
253        if self.is_contiguous() {
254            let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides);
255            unsafe {
256                Ok(slice::from_raw_parts_mut(
257                    self.ptr.sub(offset).as_ptr(),
258                    self.len(),
259                ))
260            }
261        } else {
262            Err(self)
263        }
264    }
265
266    pub(crate) fn into_iter_(self) -> IterMut<'a, A, D> {
267        IterMut::new(self)
268    }
269
270    /// Return an outer iterator for this view.
271    #[doc(hidden)] // not official
272    #[deprecated(note = "This method will be replaced.")]
273    pub fn into_outer_iter(self) -> iter::AxisIterMut<'a, A, D::Smaller>
274    where
275        D: RemoveAxis,
276    {
277        AxisIterMut::new(self, Axis(0))
278    }
279}