ndarray/iterators/
into_iter.rs

1// Copyright 2020-2021 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 std::mem;
10use std::ptr::NonNull;
11
12use crate::imp_prelude::*;
13use crate::OwnedRepr;
14
15use super::Baseiter;
16use crate::impl_owned_array::drop_unreachable_raw;
17
18
19/// By-value iterator for an array
20pub struct IntoIter<A, D>
21where
22    D: Dimension,
23{
24    array_data: OwnedRepr<A>,
25    inner: Baseiter<A, D>,
26    data_len: usize,
27    /// first memory address of an array element
28    array_head_ptr: NonNull<A>,
29    // if true, the array owns elements that are not reachable by indexing
30    // through all the indices of the dimension.
31    has_unreachable_elements: bool,
32}
33
34impl<A, D> IntoIter<A, D> 
35where
36    D: Dimension,
37{
38    /// Create a new by-value iterator that consumes `array`
39    pub(crate) fn new(mut array: Array<A, D>) -> Self {
40        unsafe {
41            let array_head_ptr = array.ptr;
42            let ptr = array.as_mut_ptr();
43            let mut array_data = array.data;
44            let data_len = array_data.release_all_elements();
45            debug_assert!(data_len >= array.dim.size());
46            let has_unreachable_elements = array.dim.size() != data_len;
47            let inner = Baseiter::new(ptr, array.dim, array.strides);
48
49            IntoIter {
50                array_data,
51                inner,
52                data_len,
53                array_head_ptr,
54                has_unreachable_elements,
55            }
56        }
57    }
58}
59
60impl<A, D: Dimension> Iterator for IntoIter<A, D> {
61    type Item = A;
62
63    #[inline]
64    fn next(&mut self) -> Option<A> {
65        self.inner.next().map(|p| unsafe { p.read() })
66    }
67
68    fn size_hint(&self) -> (usize, Option<usize>) {
69        self.inner.size_hint()
70    }
71}
72
73impl<A, D: Dimension> ExactSizeIterator for IntoIter<A, D> {
74    fn len(&self) -> usize { self.inner.len() }
75}
76
77impl<A, D> Drop for IntoIter<A, D>
78where
79    D: Dimension
80{
81    fn drop(&mut self) {
82        if !self.has_unreachable_elements || mem::size_of::<A>() == 0 || !mem::needs_drop::<A>() {
83            return;
84        }
85
86        // iterate til the end
87        while let Some(_) = self.next() { }
88
89        unsafe {
90            let data_ptr = self.array_data.as_ptr_mut();
91            let view = RawArrayViewMut::new(self.array_head_ptr, self.inner.dim.clone(),
92                                            self.inner.strides.clone());
93            debug_assert!(self.inner.dim.size() < self.data_len, "data_len {} and dim size {}",
94                          self.data_len, self.inner.dim.size());
95            drop_unreachable_raw(view, data_ptr, self.data_len);
96        }
97    }
98}
99
100impl<A, D> IntoIterator for Array<A, D>
101where
102    D: Dimension
103{
104    type Item = A;
105    type IntoIter = IntoIter<A, D>;
106
107    fn into_iter(self) -> Self::IntoIter {
108        IntoIter::new(self)
109    }
110}
111
112impl<A, D> IntoIterator for ArcArray<A, D>
113where
114    D: Dimension,
115    A: Clone,
116{
117    type Item = A;
118    type IntoIter = IntoIter<A, D>;
119
120    fn into_iter(self) -> Self::IntoIter {
121        IntoIter::new(self.into_owned())
122    }
123}
124
125impl<A, D> IntoIterator for CowArray<'_, A, D>
126where
127    D: Dimension,
128    A: Clone,
129{
130    type Item = A;
131    type IntoIter = IntoIter<A, D>;
132
133    fn into_iter(self) -> Self::IntoIter {
134        IntoIter::new(self.into_owned())
135    }
136}