Coverage Report

Created: 2025-06-04 06:23

/rust/registry/src/index.crates.io-6f17d22bba15001f/generic-array-0.14.7/src/iter.rs
Line
Count
Source (jump to first uncovered line)
1
//! `GenericArray` iterator implementation.
2
3
use super::{ArrayLength, GenericArray};
4
use core::iter::FusedIterator;
5
use core::mem::ManuallyDrop;
6
use core::{cmp, fmt, mem, ptr};
7
8
/// An iterator that moves out of a `GenericArray`
9
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
10
    // Invariants: index <= index_back <= N
11
    // Only values in array[index..index_back] are alive at any given time.
12
    // Values from array[..index] and array[index_back..] are already moved/dropped.
13
    array: ManuallyDrop<GenericArray<T, N>>,
14
    index: usize,
15
    index_back: usize,
16
}
17
18
#[cfg(test)]
19
mod test {
20
    use super::*;
21
22
    fn send<I: Send>(_iter: I) {}
23
24
    #[test]
25
    fn test_send_iter() {
26
        send(GenericArray::from([1, 2, 3, 4]).into_iter());
27
    }
28
}
29
30
impl<T, N> GenericArrayIter<T, N>
31
where
32
    N: ArrayLength<T>,
33
{
34
    /// Returns the remaining items of this iterator as a slice
35
    #[inline]
36
0
    pub fn as_slice(&self) -> &[T] {
37
0
        &self.array.as_slice()[self.index..self.index_back]
38
0
    }
39
40
    /// Returns the remaining items of this iterator as a mutable slice
41
    #[inline]
42
0
    pub fn as_mut_slice(&mut self) -> &mut [T] {
43
0
        &mut self.array.as_mut_slice()[self.index..self.index_back]
44
0
    }
45
}
46
47
impl<T, N> IntoIterator for GenericArray<T, N>
48
where
49
    N: ArrayLength<T>,
50
{
51
    type Item = T;
52
    type IntoIter = GenericArrayIter<T, N>;
53
54
0
    fn into_iter(self) -> Self::IntoIter {
55
0
        GenericArrayIter {
56
0
            array: ManuallyDrop::new(self),
57
0
            index: 0,
58
0
            index_back: N::USIZE,
59
0
        }
60
0
    }
61
}
62
63
// Based on work in rust-lang/rust#49000
64
impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
65
where
66
    N: ArrayLength<T>,
67
{
68
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69
0
        f.debug_tuple("GenericArrayIter")
70
0
            .field(&self.as_slice())
71
0
            .finish()
72
0
    }
73
}
74
75
impl<T, N> Drop for GenericArrayIter<T, N>
76
where
77
    N: ArrayLength<T>,
78
{
79
    #[inline]
80
0
    fn drop(&mut self) {
81
0
        if mem::needs_drop::<T>() {
82
            // Drop values that are still alive.
83
0
            for p in self.as_mut_slice() {
84
0
                unsafe {
85
0
                    ptr::drop_in_place(p);
86
0
                }
87
            }
88
0
        }
89
0
    }
90
}
91
92
// Based on work in rust-lang/rust#49000
93
impl<T: Clone, N> Clone for GenericArrayIter<T, N>
94
where
95
    N: ArrayLength<T>,
96
{
97
0
    fn clone(&self) -> Self {
98
0
        // This places all cloned elements at the start of the new array iterator,
99
0
        // not at their original indices.
100
0
101
0
        let mut array = unsafe { ptr::read(&self.array) };
102
0
        let mut index_back = 0;
103
104
0
        for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) {
105
0
            unsafe { ptr::write(dst, src.clone()) };
106
0
            index_back += 1;
107
0
        }
108
109
0
        GenericArrayIter {
110
0
            array,
111
0
            index: 0,
112
0
            index_back,
113
0
        }
114
0
    }
115
}
116
117
impl<T, N> Iterator for GenericArrayIter<T, N>
118
where
119
    N: ArrayLength<T>,
120
{
121
    type Item = T;
122
123
    #[inline]
124
0
    fn next(&mut self) -> Option<T> {
125
0
        if self.index < self.index_back {
126
0
            let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) };
127
0
128
0
            self.index += 1;
129
0
130
0
            p
131
        } else {
132
0
            None
133
        }
134
0
    }
135
136
0
    fn fold<B, F>(mut self, init: B, mut f: F) -> B
137
0
    where
138
0
        F: FnMut(B, Self::Item) -> B,
139
0
    {
140
0
        let ret = unsafe {
141
0
            let GenericArrayIter {
142
0
                ref array,
143
0
                ref mut index,
144
0
                index_back,
145
0
            } = self;
146
0
147
0
            let remaining = &array[*index..index_back];
148
0
149
0
            remaining.iter().fold(init, |acc, src| {
150
0
                let value = ptr::read(src);
151
0
152
0
                *index += 1;
153
0
154
0
                f(acc, value)
155
0
            })
156
0
        };
157
0
158
0
        // ensure the drop happens here after iteration
159
0
        drop(self);
160
0
161
0
        ret
162
0
    }
163
164
    #[inline]
165
0
    fn size_hint(&self) -> (usize, Option<usize>) {
166
0
        let len = self.len();
167
0
        (len, Some(len))
168
0
    }
169
170
    #[inline]
171
0
    fn count(self) -> usize {
172
0
        self.len()
173
0
    }
174
175
0
    fn nth(&mut self, n: usize) -> Option<T> {
176
0
        // First consume values prior to the nth.
177
0
        let ndrop = cmp::min(n, self.len());
178
179
0
        for p in &mut self.array[self.index..self.index + ndrop] {
180
0
            self.index += 1;
181
0
182
0
            unsafe {
183
0
                ptr::drop_in_place(p);
184
0
            }
185
        }
186
187
0
        self.next()
188
0
    }
189
190
    #[inline]
191
0
    fn last(mut self) -> Option<T> {
192
0
        // Note, everything else will correctly drop first as `self` leaves scope.
193
0
        self.next_back()
194
0
    }
195
}
196
197
impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N>
198
where
199
    N: ArrayLength<T>,
200
{
201
0
    fn next_back(&mut self) -> Option<T> {
202
0
        if self.index < self.index_back {
203
0
            self.index_back -= 1;
204
0
205
0
            unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) }
206
        } else {
207
0
            None
208
        }
209
0
    }
210
211
0
    fn rfold<B, F>(mut self, init: B, mut f: F) -> B
212
0
    where
213
0
        F: FnMut(B, Self::Item) -> B,
214
0
    {
215
0
        let ret = unsafe {
216
0
            let GenericArrayIter {
217
0
                ref array,
218
0
                index,
219
0
                ref mut index_back,
220
0
            } = self;
221
0
222
0
            let remaining = &array[index..*index_back];
223
0
224
0
            remaining.iter().rfold(init, |acc, src| {
225
0
                let value = ptr::read(src);
226
0
227
0
                *index_back -= 1;
228
0
229
0
                f(acc, value)
230
0
            })
231
0
        };
232
0
233
0
        // ensure the drop happens here after iteration
234
0
        drop(self);
235
0
236
0
        ret
237
0
    }
238
}
239
240
impl<T, N> ExactSizeIterator for GenericArrayIter<T, N>
241
where
242
    N: ArrayLength<T>,
243
{
244
0
    fn len(&self) -> usize {
245
0
        self.index_back - self.index
246
0
    }
247
}
248
249
impl<T, N> FusedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {}
250
251
// TODO: Implement `TrustedLen` when stabilized