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