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}