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
11use crate::imp_prelude::*;
12
13use crate::{Baseiter, ElementsBase, ElementsBaseMut, Iter, IterMut};
14
15use crate::iter::{self, AxisIter, AxisIterMut};
16use crate::math_cell::MathCell;
17use crate::IndexLonger;
18
19/// Methods for read-only array views.
20impl<'a, A, D> ArrayView<'a, A, D>
21where
22    D: Dimension,
23{
24    /// Convert the view into an `ArrayView<'b, A, D>` where `'b` is a lifetime
25    /// outlived by `'a'`.
26    pub fn reborrow<'b>(self) -> ArrayView<'b, A, D>
27    where
28        'a: 'b,
29    {
30        unsafe { ArrayView::new(self.ptr, self.dim, self.strides) }
31    }
32
33    /// Return the array’s data as a slice, if it is contiguous and in standard order.
34    /// Return `None` otherwise.
35    ///
36    /// Note that while the method is similar to [`ArrayBase::as_slice()`], this method tranfers
37    /// the view's lifetime to the slice, so it is a bit more powerful.
38    pub fn to_slice(&self) -> Option<&'a [A]> {
39        if self.is_standard_layout() {
40            unsafe { Some(slice::from_raw_parts(self.ptr.as_ptr(), self.len())) }
41        } else {
42            None
43        }
44    }
45
46    /// Converts to a raw array view.
47    pub(crate) fn into_raw_view(self) -> RawArrayView<A, D> {
48        unsafe { RawArrayView::new(self.ptr, self.dim, self.strides) }
49    }
50}
51
52/// Methods specific to `ArrayView0`.
53///
54/// ***See also all methods for [`ArrayView`] and [`ArrayBase`]***
55///
56/// [`ArrayBase`]: struct.ArrayBase.html
57/// [`ArrayView`]: struct.ArrayView.html
58impl<'a, A> ArrayView<'a, A, Ix0> {
59    /// Consume the view and return a reference to the single element in the array.
60    ///
61    /// The lifetime of the returned reference matches the lifetime of the data
62    /// the array view was pointing to.
63    ///
64    /// ```
65    /// use ndarray::{arr0, Array0};
66    ///
67    /// // `Foo` doesn't implement `Clone`.
68    /// #[derive(Debug, Eq, PartialEq)]
69    /// struct Foo;
70    ///
71    /// let array: Array0<Foo> = arr0(Foo);
72    /// let view = array.view();
73    /// let scalar: &Foo = view.into_scalar();
74    /// assert_eq!(scalar, &Foo);
75    /// ```
76    pub fn into_scalar(self) -> &'a A {
77        self.index(Ix0())
78    }
79}
80
81/// Methods specific to `ArrayViewMut0`.
82///
83/// ***See also all methods for [`ArrayViewMut`] and [`ArrayBase`]***
84///
85/// [`ArrayBase`]: struct.ArrayBase.html
86/// [`ArrayViewMut`]: struct.ArrayViewMut.html
87impl<'a, A> ArrayViewMut<'a, A, Ix0> {
88    /// Consume the mutable view and return a mutable reference to the single element in the array.
89    ///
90    /// The lifetime of the returned reference matches the lifetime of the data
91    /// the array view was pointing to.
92    ///
93    /// ```
94    /// use ndarray::{arr0, Array0};
95    ///
96    /// let mut array: Array0<f64> = arr0(5.);
97    /// let view = array.view_mut();
98    /// let mut scalar = view.into_scalar();
99    /// *scalar = 7.;
100    /// assert_eq!(scalar, &7.);
101    /// assert_eq!(array[()], 7.);
102    /// ```
103    pub fn into_scalar(self) -> &'a mut A {
104        self.index(Ix0())
105    }
106}
107
108/// Methods for read-write array views.
109impl<'a, A, D> ArrayViewMut<'a, A, D>
110where
111    D: Dimension,
112{
113    /// Return the array’s data as a slice, if it is contiguous and in standard order.
114    /// Return `None` otherwise.
115    ///
116    /// Note that while this is similar to [`ArrayBase::as_slice_mut()`], this method tranfers the
117    /// view's lifetime to the slice.
118    pub fn into_slice(self) -> Option<&'a mut [A]> {
119        self.try_into_slice().ok()
120    }
121
122    /// Return a shared view of the array with elements as if they were embedded in cells.
123    ///
124    /// The cell view itself can be copied and accessed without exclusivity.
125    ///
126    /// The view acts "as if" the elements are temporarily in cells, and elements
127    /// can be changed through shared references using the regular cell methods.
128    pub fn into_cell_view(self) -> ArrayView<'a, MathCell<A>, D> {
129        // safety: valid because
130        // A and MathCell<A> have the same representation
131        // &'a mut T is interchangeable with &'a Cell<T> -- see method Cell::from_mut in std
132        unsafe {
133            self.into_raw_view_mut().cast::<MathCell<A>>().deref_into_view()
134        }
135    }
136}
137
138/// Private array view methods
139impl<'a, A, D> ArrayView<'a, A, D>
140where
141    D: Dimension,
142{
143    #[inline]
144    pub(crate) fn into_base_iter(self) -> Baseiter<A, D> {
145        unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) }
146    }
147
148    #[inline]
149    pub(crate) fn into_elements_base(self) -> ElementsBase<'a, A, D> {
150        ElementsBase::new(self)
151    }
152
153    pub(crate) fn into_iter_(self) -> Iter<'a, A, D> {
154        Iter::new(self)
155    }
156
157    /// Return an outer iterator for this view.
158    #[doc(hidden)] // not official
159    #[deprecated(note = "This method will be replaced.")]
160    pub fn into_outer_iter(self) -> iter::AxisIter<'a, A, D::Smaller>
161    where
162        D: RemoveAxis,
163    {
164        AxisIter::new(self, Axis(0))
165    }
166}
167
168impl<'a, A, D> ArrayViewMut<'a, A, D>
169where
170    D: Dimension,
171{
172    // Convert into a read-only view
173    pub(crate) fn into_view(self) -> ArrayView<'a, A, D> {
174        unsafe { ArrayView::new(self.ptr, self.dim, self.strides) }
175    }
176
177    /// Converts to a mutable raw array view.
178    pub(crate) fn into_raw_view_mut(self) -> RawArrayViewMut<A, D> {
179        unsafe { RawArrayViewMut::new(self.ptr, self.dim, self.strides) }
180    }
181
182    #[inline]
183    pub(crate) fn into_base_iter(self) -> Baseiter<A, D> {
184        unsafe { Baseiter::new(self.ptr.as_ptr(), self.dim, self.strides) }
185    }
186
187    #[inline]
188    pub(crate) fn into_elements_base(self) -> ElementsBaseMut<'a, A, D> {
189        ElementsBaseMut::new(self)
190    }
191
192    /// Return the array’s data as a slice, if it is contiguous and in standard order.
193    /// Otherwise return self in the Err branch of the result.
194    pub(crate) fn try_into_slice(self) -> Result<&'a mut [A], Self> {
195        if self.is_standard_layout() {
196            unsafe { Ok(slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len())) }
197        } else {
198            Err(self)
199        }
200    }
201
202    pub(crate) fn into_iter_(self) -> IterMut<'a, A, D> {
203        IterMut::new(self)
204    }
205
206    /// Return an outer iterator for this view.
207    #[doc(hidden)] // not official
208    #[deprecated(note = "This method will be replaced.")]
209    pub fn into_outer_iter(self) -> iter::AxisIterMut<'a, A, D::Smaller>
210    where
211        D: RemoveAxis,
212    {
213        AxisIterMut::new(self, Axis(0))
214    }
215}