ndarray/impl_views/
indexing.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 crate::arraytraits::array_out_of_bounds;
10use crate::imp_prelude::*;
11use crate::NdIndex;
12
13/// Extra indexing methods for array views
14///
15/// These methods are very similar to regular indexing or calling of the
16/// `get`/`get_mut` methods that we can use on any array or array view. The
17/// difference here is in the length of lifetime in the resulting reference.
18///
19/// **Note** that the `ArrayView` (read-only) and `ArrayViewMut` (read-write) differ
20/// in how they are allowed implement this trait -- `ArrayView`'s implementation
21/// is usual. If you put in a `ArrayView<'a, T, D>` here, you get references
22/// `&'a T` out.
23///
24/// For `ArrayViewMut` to obey the borrowing rules we have to consume the
25/// view if we call any of these methods. (The equivalent of reborrow is
26/// `.view_mut()` for read-write array views, but if you can use that,
27/// then the regular indexing / `get_mut` should suffice, too.)
28///
29/// ```
30/// use ndarray::IndexLonger;
31/// use ndarray::ArrayView;
32///
33/// let data = [0.; 256];
34/// let long_life_ref = {
35///     // make a 16 × 16 array view
36///     let view = ArrayView::from(&data[..]).into_shape((16, 16)).unwrap();
37///
38///     // index the view and with `IndexLonger`.
39///     // Note here that we get a reference with a life that is derived from
40///     // `data`, the base data, instead of being derived from the view
41///     IndexLonger::index(&view, [0, 1])
42/// };
43///
44/// // view goes out of scope
45///
46/// assert_eq!(long_life_ref, &0.);
47///
48/// ```
49pub trait IndexLonger<I> {
50    /// The type of the reference to the element that is produced, including
51    /// its lifetime.
52    type Output;
53    /// Get a reference of a element through the view.
54    ///
55    /// This method is like `Index::index` but with a longer lifetime (matching
56    /// the array view); which we can only do for the array view and not in the
57    /// `Index` trait.
58    ///
59    /// See also [the `get` method][1] which works for all arrays and array
60    /// views.
61    ///
62    /// [1]: ArrayBase::get
63    ///
64    /// **Panics** if index is out of bounds.
65    fn index(self, index: I) -> Self::Output;
66
67    /// Get a reference of a element through the view.
68    ///
69    /// This method is like `ArrayBase::get` but with a longer lifetime (matching
70    /// the array view); which we can only do for the array view and not in the
71    /// `Index` trait.
72    ///
73    /// See also [the `get` method][1] (and [`get_mut`][2]) which works for all arrays and array
74    /// views.
75    ///
76    /// [1]: ArrayBase::get
77    /// [2]: ArrayBase::get_mut
78    ///
79    /// **Panics** if index is out of bounds.
80    fn get(self, index: I) -> Option<Self::Output>;
81
82    /// Get a reference of a element through the view without boundary check
83    ///
84    /// This method is like `elem` with a longer lifetime (matching the array
85    /// view); which we can't do for general arrays.
86    ///
87    /// See also [the `uget` method][1] which works for all arrays and array
88    /// views.
89    ///
90    /// [1]: ArrayBase::uget
91    ///
92    /// **Note:** only unchecked for non-debug builds of ndarray.
93    ///
94    /// # Safety
95    ///
96    /// The caller must ensure that the index is in-bounds.
97    unsafe fn uget(self, index: I) -> Self::Output;
98}
99
100impl<'a, 'b, I, A, D> IndexLonger<I> for &'b ArrayView<'a, A, D>
101where
102    I: NdIndex<D>,
103    D: Dimension,
104{
105    type Output = &'a A;
106
107    /// Get a reference of a element through the view.
108    ///
109    /// This method is like `Index::index` but with a longer lifetime (matching
110    /// the array view); which we can only do for the array view and not in the
111    /// `Index` trait.
112    ///
113    /// See also [the `get` method][1] which works for all arrays and array
114    /// views.
115    ///
116    /// [1]: ArrayBase::get
117    ///
118    /// **Panics** if index is out of bounds.
119    fn index(self, index: I) -> &'a A {
120        debug_bounds_check!(self, index);
121        unsafe { &*self.get_ptr(index).unwrap_or_else(|| array_out_of_bounds()) }
122    }
123
124    fn get(self, index: I) -> Option<&'a A> {
125        unsafe { self.get_ptr(index).map(|ptr| &*ptr) }
126    }
127
128    /// Get a reference of a element through the view without boundary check
129    ///
130    /// This method is like `elem` with a longer lifetime (matching the array
131    /// view); which we can't do for general arrays.
132    ///
133    /// See also [the `uget` method][1] which works for all arrays and array
134    /// views.
135    ///
136    /// [1]: ArrayBase::uget
137    ///
138    /// **Note:** only unchecked for non-debug builds of ndarray.
139    unsafe fn uget(self, index: I) -> &'a A {
140        debug_bounds_check!(self, index);
141        &*self.as_ptr().offset(index.index_unchecked(&self.strides))
142    }
143}
144
145impl<'a, I, A, D> IndexLonger<I> for ArrayViewMut<'a, A, D>
146where
147    I: NdIndex<D>,
148    D: Dimension,
149{
150    type Output = &'a mut A;
151
152    /// Convert a mutable array view to a mutable reference of a element.
153    ///
154    /// This method is like `IndexMut::index_mut` but with a longer lifetime
155    /// (matching the array view); which we can only do for the array view and
156    /// not in the `Index` trait.
157    ///
158    /// See also [the `get_mut` method][1] which works for all arrays and array
159    /// views.
160    ///
161    /// [1]: ArrayBase::get_mut
162    ///
163    /// **Panics** if index is out of bounds.
164    fn index(mut self, index: I) -> &'a mut A {
165        debug_bounds_check!(self, index);
166        unsafe {
167            match self.get_mut_ptr(index) {
168                Some(ptr) => &mut *ptr,
169                None => array_out_of_bounds(),
170            }
171        }
172    }
173
174    /// Convert a mutable array view to a mutable reference of a element, with
175    /// checked access.
176    ///
177    /// See also [the `get_mut` method][1] which works for all arrays and array
178    /// views.
179    ///
180    /// [1]: ArrayBase::get_mut
181    ///
182    fn get(mut self, index: I) -> Option<&'a mut A> {
183        debug_bounds_check!(self, index);
184        unsafe {
185            match self.get_mut_ptr(index) {
186                Some(ptr) => Some(&mut *ptr),
187                None => None,
188            }
189        }
190    }
191
192    /// Convert a mutable array view to a mutable reference of a element without
193    /// boundary check.
194    ///
195    /// See also [the `uget_mut` method][1] which works for all arrays and array
196    /// views.
197    ///
198    /// [1]: ArrayBase::uget_mut
199    ///
200    /// **Note:** only unchecked for non-debug builds of ndarray.
201    unsafe fn uget(mut self, index: I) -> &'a mut A {
202        debug_bounds_check!(self, index);
203        &mut *self
204            .as_mut_ptr()
205            .offset(index.index_unchecked(&self.strides))
206    }
207}