Thanks to visit codestin.com
Credit goes to docs.rs

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