Skip to content

Commit d2210e5

Browse files
committed
Port some improvements from rust-lang/rust#49000
1 parent ffc65b1 commit d2210e5

File tree

3 files changed

+224
-7
lines changed

3 files changed

+224
-7
lines changed

src/iter.rs

+60-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! `GenericArray` iterator implementation.
22
33
use super::{ArrayLength, GenericArray};
4-
use core::{cmp, ptr};
4+
use core::{cmp, ptr, fmt, mem};
55
use core::mem::ManuallyDrop;
66

77
/// An iterator that moves out of a `GenericArray`
@@ -26,6 +26,23 @@ mod test {
2626
}
2727
}
2828

29+
impl<T, N> GenericArrayIter<T, N>
30+
where
31+
N: ArrayLength<T>,
32+
{
33+
/// Returns the remaining items of this iterator as a slice
34+
#[inline]
35+
pub fn as_slice(&self) -> &[T] {
36+
&self.array.as_slice()[self.index..self.index_back]
37+
}
38+
39+
/// Returns the remaining items of this iterator as a mutable slice
40+
#[inline]
41+
pub fn as_mut_slice(&mut self) -> &mut [T] {
42+
&mut self.array.as_mut_slice()[self.index..self.index_back]
43+
}
44+
}
45+
2946
impl<T, N> IntoIterator for GenericArray<T, N>
3047
where
3148
N: ArrayLength<T>,
@@ -42,21 +59,58 @@ where
4259
}
4360
}
4461

62+
// Based on work in rust-land/rust#49000
63+
impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N>
64+
where
65+
N: ArrayLength<T>,
66+
{
67+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68+
f.debug_tuple("GenericArrayIter")
69+
.field(&self.as_slice())
70+
.finish()
71+
}
72+
}
73+
4574
impl<T, N> Drop for GenericArrayIter<T, N>
4675
where
4776
N: ArrayLength<T>,
4877
{
4978
#[inline]
5079
fn drop(&mut self) {
5180
// Drop values that are still alive.
52-
for p in &mut self.array[self.index..self.index_back] {
81+
for p in self.as_mut_slice() {
5382
unsafe {
5483
ptr::drop_in_place(p);
5584
}
5685
}
5786
}
5887
}
5988

89+
impl<T: Clone, N> Clone for GenericArrayIter<T, N>
90+
where
91+
N: ArrayLength<T>,
92+
{
93+
fn clone(&self) -> Self {
94+
// This places all cloned elements at the start of the new array iterator,
95+
// not at their original indices.
96+
unsafe {
97+
let mut iter = GenericArrayIter {
98+
array: ManuallyDrop::new(mem::uninitialized()),
99+
index: 0,
100+
index_back: 0,
101+
};
102+
103+
for (dst, src) in iter.array.iter_mut().zip(self.as_slice()) {
104+
ptr::write(dst, src.clone());
105+
106+
iter.index_back += 1;
107+
}
108+
109+
iter
110+
}
111+
}
112+
}
113+
60114
impl<T, N> Iterator for GenericArrayIter<T, N>
61115
where
62116
N: ArrayLength<T>,
@@ -90,8 +144,10 @@ where
90144
fn nth(&mut self, n: usize) -> Option<T> {
91145
// First consume values prior to the nth.
92146
let ndrop = cmp::min(n, self.len());
147+
93148
for p in &mut self.array[self.index..self.index + ndrop] {
94149
self.index += 1;
150+
95151
unsafe {
96152
ptr::drop_in_place(p);
97153
}
@@ -129,3 +185,5 @@ where
129185
self.index_back - self.index
130186
}
131187
}
188+
189+
// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized

tests/iter.rs

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#[macro_use]
2+
extern crate generic_array;
3+
4+
use std::cell::Cell;
5+
use std::ops::Drop;
6+
7+
use generic_array::GenericArray;
8+
use generic_array::typenum::consts::U5;
9+
10+
#[test]
11+
fn test_into_iter_as_slice() {
12+
let array = arr![char; 'a', 'b', 'c'];
13+
let mut into_iter = array.into_iter();
14+
assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
15+
let _ = into_iter.next().unwrap();
16+
assert_eq!(into_iter.as_slice(), &['b', 'c']);
17+
let _ = into_iter.next().unwrap();
18+
let _ = into_iter.next().unwrap();
19+
assert_eq!(into_iter.as_slice(), &[]);
20+
}
21+
22+
#[test]
23+
fn test_into_iter_as_mut_slice() {
24+
let array = arr![char; 'a', 'b', 'c'];
25+
let mut into_iter = array.into_iter();
26+
assert_eq!(into_iter.as_slice(), &['a', 'b', 'c']);
27+
into_iter.as_mut_slice()[0] = 'x';
28+
into_iter.as_mut_slice()[1] = 'y';
29+
assert_eq!(into_iter.next().unwrap(), 'x');
30+
assert_eq!(into_iter.as_slice(), &['y', 'c']);
31+
}
32+
33+
#[test]
34+
fn test_into_iter_debug() {
35+
let array = arr![char; 'a', 'b', 'c'];
36+
let into_iter = array.into_iter();
37+
let debug = format!("{:?}", into_iter);
38+
assert_eq!(debug, "GenericArrayIter(['a', 'b', 'c'])");
39+
}
40+
41+
#[test]
42+
fn test_into_iter_clone() {
43+
fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
44+
let v: Vec<i32> = it.collect();
45+
assert_eq!(&v[..], slice);
46+
}
47+
let mut it = arr![i32; 1, 2, 3].into_iter();
48+
iter_equal(it.clone(), &[1, 2, 3]);
49+
assert_eq!(it.next(), Some(1));
50+
let mut it = it.rev();
51+
iter_equal(it.clone(), &[3, 2]);
52+
assert_eq!(it.next(), Some(3));
53+
iter_equal(it.clone(), &[2]);
54+
assert_eq!(it.next(), Some(2));
55+
iter_equal(it.clone(), &[]);
56+
assert_eq!(it.next(), None);
57+
}
58+
59+
#[test]
60+
fn test_into_iter_nth() {
61+
let v = arr![i32; 0, 1, 2, 3, 4];
62+
for i in 0..v.len() {
63+
assert_eq!(v.clone().into_iter().nth(i).unwrap(), v[i]);
64+
}
65+
assert_eq!(v.clone().into_iter().nth(v.len()), None);
66+
67+
let mut iter = v.into_iter();
68+
assert_eq!(iter.nth(2).unwrap(), v[2]);
69+
assert_eq!(iter.nth(1).unwrap(), v[4]);
70+
}
71+
72+
#[test]
73+
fn test_into_iter_last() {
74+
let v = arr![i32; 0, 1, 2, 3, 4];
75+
assert_eq!(v.into_iter().last().unwrap(), 4);
76+
assert_eq!(arr![i32; 0].into_iter().last().unwrap(), 0);
77+
}
78+
79+
#[test]
80+
fn test_into_iter_count() {
81+
let v = arr![i32; 0, 1, 2, 3, 4];
82+
assert_eq!(v.clone().into_iter().count(), 5);
83+
84+
let mut iter2 = v.into_iter();
85+
iter2.next();
86+
iter2.next();
87+
assert_eq!(iter2.count(), 3);
88+
}
89+
90+
#[test]
91+
fn test_into_iter_flat_map() {
92+
assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
93+
}
94+
95+
#[test]
96+
fn test_into_iter_drops() {
97+
struct R<'a> {
98+
i: &'a Cell<usize>,
99+
}
100+
101+
impl<'a> Drop for R<'a> {
102+
fn drop(&mut self) {
103+
self.i.set(self.i.get() + 1);
104+
}
105+
}
106+
107+
fn r(i: &Cell<usize>) -> R {
108+
R {
109+
i: i
110+
}
111+
}
112+
113+
fn v(i: &Cell<usize>) -> GenericArray<R, U5> {
114+
arr![R; r(i), r(i), r(i), r(i), r(i)]
115+
}
116+
117+
let i = Cell::new(0);
118+
{
119+
v(&i).into_iter();
120+
}
121+
assert_eq!(i.get(), 5);
122+
123+
let i = Cell::new(0);
124+
{
125+
let mut iter = v(&i).into_iter();
126+
let _x = iter.next();
127+
assert_eq!(i.get(), 0);
128+
assert_eq!(iter.count(), 4);
129+
assert_eq!(i.get(), 4);
130+
}
131+
assert_eq!(i.get(), 5);
132+
133+
let i = Cell::new(0);
134+
{
135+
let mut iter = v(&i).into_iter();
136+
let _x = iter.nth(2);
137+
assert_eq!(i.get(), 2);
138+
let _y = iter.last();
139+
assert_eq!(i.get(), 3);
140+
}
141+
assert_eq!(i.get(), 5);
142+
143+
let i = Cell::new(0);
144+
for (index, _x) in v(&i).into_iter().enumerate() {
145+
assert_eq!(i.get(), index);
146+
}
147+
assert_eq!(i.get(), 5);
148+
149+
let i = Cell::new(0);
150+
for (index, _x) in v(&i).into_iter().rev().enumerate() {
151+
assert_eq!(i.get(), index);
152+
}
153+
assert_eq!(i.get(), 5);
154+
}
155+
156+
/*
157+
//TODO: Cover this
158+
#[allow(dead_code)]
159+
fn assert_covariance() {
160+
fn into_iter<'new>(i: GenericArrayIter<&'static str, U10>) -> GenericArrayIter<&'new str, U10> {
161+
i
162+
}
163+
}
164+
*/

tests/mod.rs

-5
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,6 @@ fn test_copy() {
5757
assert_eq!(test2[0], 1);
5858
}
5959

60-
#[test]
61-
fn test_iter_flat_map() {
62-
assert!((0..5).flat_map(|i| arr![i32; 2 * i, 2 * i + 1]).eq(0..10));
63-
}
64-
6560
#[derive(Debug, PartialEq, Eq)]
6661
struct NoClone<T>(T);
6762

0 commit comments

Comments
 (0)