Skip to content

Commit 021389f

Browse files
committed
Auto merge of #27652 - alex-ozdemir:iter, r=bluss
Provides a custom implementation of Iterator methods `count`, `nth`, and `last` for the structures `slice::{Windows,Chunks,ChunksMut}` in the core module. These implementations run in constant time as opposed to the default implementations which run in linear time. Addresses Issue #24214 r? @aturon
2 parents 82169af + e09f83e commit 021389f

File tree

2 files changed

+215
-0
lines changed

2 files changed

+215
-0
lines changed

src/libcore/slice.rs

+95
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ use ptr;
5050
use mem;
5151
use mem::size_of;
5252
use marker::{Send, Sync, self};
53+
use num::wrapping::OverflowingOps;
5354
use raw::Repr;
5455
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
5556
use raw::Slice as RawSlice;
@@ -1180,6 +1181,34 @@ impl<'a, T> Iterator for Windows<'a, T> {
11801181
(size, Some(size))
11811182
}
11821183
}
1184+
1185+
#[inline]
1186+
fn count(self) -> usize {
1187+
self.size_hint().0
1188+
}
1189+
1190+
#[inline]
1191+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1192+
let (end, overflow) = self.size.overflowing_add(n);
1193+
if end > self.v.len() || overflow {
1194+
self.v = &[];
1195+
None
1196+
} else {
1197+
let nth = &self.v[n..end];
1198+
self.v = &self.v[n+1..];
1199+
Some(nth)
1200+
}
1201+
}
1202+
1203+
#[inline]
1204+
fn last(self) -> Option<Self::Item> {
1205+
if self.size > self.v.len() {
1206+
None
1207+
} else {
1208+
let start = self.v.len() - self.size;
1209+
Some(&self.v[start..])
1210+
}
1211+
}
11831212
}
11841213

11851214
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1266,6 +1295,38 @@ impl<'a, T> Iterator for Chunks<'a, T> {
12661295
(n, Some(n))
12671296
}
12681297
}
1298+
1299+
#[inline]
1300+
fn count(self) -> usize {
1301+
self.size_hint().0
1302+
}
1303+
1304+
#[inline]
1305+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1306+
let (start, overflow) = n.overflowing_mul(self.size);
1307+
if start >= self.v.len() || overflow {
1308+
self.v = &[];
1309+
None
1310+
} else {
1311+
let end = match start.checked_add(self.size) {
1312+
Some(sum) => cmp::min(self.v.len(), sum),
1313+
None => self.v.len(),
1314+
};
1315+
let nth = &self.v[start..end];
1316+
self.v = &self.v[end..];
1317+
Some(nth)
1318+
}
1319+
}
1320+
1321+
#[inline]
1322+
fn last(self) -> Option<Self::Item> {
1323+
if self.v.is_empty() {
1324+
None
1325+
} else {
1326+
let start = (self.v.len() - 1) / self.size * self.size;
1327+
Some(&self.v[start..])
1328+
}
1329+
}
12691330
}
12701331

12711332
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1346,6 +1407,40 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
13461407
(n, Some(n))
13471408
}
13481409
}
1410+
1411+
#[inline]
1412+
fn count(self) -> usize {
1413+
self.size_hint().0
1414+
}
1415+
1416+
#[inline]
1417+
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
1418+
let (start, overflow) = n.overflowing_mul(self.chunk_size);
1419+
if start >= self.v.len() || overflow {
1420+
self.v = &mut [];
1421+
None
1422+
} else {
1423+
let end = match start.checked_add(self.chunk_size) {
1424+
Some(sum) => cmp::min(self.v.len(), sum),
1425+
None => self.v.len(),
1426+
};
1427+
let tmp = mem::replace(&mut self.v, &mut []);
1428+
let (head, tail) = tmp.split_at_mut(end);
1429+
let (_, nth) = head.split_at_mut(start);
1430+
self.v = tail;
1431+
Some(nth)
1432+
}
1433+
}
1434+
1435+
#[inline]
1436+
fn last(self) -> Option<Self::Item> {
1437+
if self.v.is_empty() {
1438+
None
1439+
} else {
1440+
let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size;
1441+
Some(&mut self.v[start..])
1442+
}
1443+
}
13491444
}
13501445

13511446
#[stable(feature = "rust1", since = "1.0.0")]

src/libcoretest/slice.rs

+120
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,123 @@ fn test_iterator_count() {
6464
iter2.next();
6565
assert_eq!(iter2.count(), 3);
6666
}
67+
68+
#[test]
69+
fn test_chunks_count() {
70+
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
71+
let c = v.chunks(3);
72+
assert_eq!(c.count(), 2);
73+
74+
let v2: &[i32] = &[0, 1, 2, 3, 4];
75+
let c2 = v2.chunks(2);
76+
assert_eq!(c2.count(), 3);
77+
78+
let v3: &[i32] = &[];
79+
let c3 = v3.chunks(2);
80+
assert_eq!(c3.count(), 0);
81+
}
82+
83+
#[test]
84+
fn test_chunks_nth() {
85+
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
86+
let mut c = v.chunks(2);
87+
assert_eq!(c.nth(1).unwrap()[1], 3);
88+
assert_eq!(c.next().unwrap()[0], 4);
89+
90+
let v2: &[i32] = &[0, 1, 2, 3, 4];
91+
let mut c2 = v2.chunks(3);
92+
assert_eq!(c2.nth(1).unwrap()[1], 4);
93+
assert_eq!(c2.next(), None);
94+
}
95+
96+
#[test]
97+
fn test_chunks_last() {
98+
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
99+
let c = v.chunks(2);
100+
assert_eq!(c.last().unwrap()[1], 5);
101+
102+
let v2: &[i32] = &[0, 1, 2, 3, 4];
103+
let c2 = v2.chunks(2);
104+
assert_eq!(c2.last().unwrap()[0], 4);
105+
}
106+
107+
#[test]
108+
fn test_chunks_mut_count() {
109+
let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
110+
let c = v.chunks_mut(3);
111+
assert_eq!(c.count(), 2);
112+
113+
let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
114+
let c2 = v2.chunks_mut(2);
115+
assert_eq!(c2.count(), 3);
116+
117+
let mut v3: &mut [i32] = &mut [];
118+
let c3 = v3.chunks_mut(2);
119+
assert_eq!(c3.count(), 0);
120+
}
121+
122+
#[test]
123+
fn test_chunks_mut_nth() {
124+
let mut v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
125+
let mut c = v.chunks_mut(2);
126+
assert_eq!(c.nth(1).unwrap()[1], 3);
127+
assert_eq!(c.next().unwrap()[0], 4);
128+
129+
let mut v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
130+
let mut c2 = v2.chunks_mut(3);
131+
assert_eq!(c2.nth(1).unwrap()[1], 4);
132+
assert_eq!(c2.next(), None);
133+
}
134+
135+
#[test]
136+
fn test_chunks_mut_last() {
137+
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
138+
let c = v.chunks_mut(2);
139+
assert_eq!(c.last().unwrap()[1], 5);
140+
141+
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
142+
let c2 = v2.chunks_mut(2);
143+
assert_eq!(c2.last().unwrap()[0], 4);
144+
}
145+
146+
147+
148+
149+
#[test]
150+
fn test_windows_count() {
151+
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
152+
let c = v.windows(3);
153+
assert_eq!(c.count(), 4);
154+
155+
let v2: &[i32] = &[0, 1, 2, 3, 4];
156+
let c2 = v2.windows(6);
157+
assert_eq!(c2.count(), 0);
158+
159+
let v3: &[i32] = &[];
160+
let c3 = v3.windows(2);
161+
assert_eq!(c3.count(), 0);
162+
}
163+
164+
#[test]
165+
fn test_windows_nth() {
166+
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
167+
let mut c = v.windows(2);
168+
assert_eq!(c.nth(2).unwrap()[1], 3);
169+
assert_eq!(c.next().unwrap()[0], 3);
170+
171+
let v2: &[i32] = &[0, 1, 2, 3, 4];
172+
let mut c2 = v2.windows(4);
173+
assert_eq!(c2.nth(1).unwrap()[1], 2);
174+
assert_eq!(c2.next(), None);
175+
}
176+
177+
#[test]
178+
fn test_windows_last() {
179+
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
180+
let c = v.windows(2);
181+
assert_eq!(c.last().unwrap()[1], 5);
182+
183+
let v2: &[i32] = &[0, 1, 2, 3, 4];
184+
let c2 = v2.windows(2);
185+
assert_eq!(c2.last().unwrap()[0], 3);
186+
}

0 commit comments

Comments
 (0)