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}