Skip to content

Commit e09f83e

Browse files
alex-ozdemirAlex Ozdemir
authored and
Alex Ozdemir
committed
O(1) count,nth,last for slice::Windows,Chunks(Mut)
Implemented count, nth, and last in constant time for Windows, Chunks, and ChunksMut created from a slice. Included checks for overflow in the implementation of nth(). Also added a test for each implemented method to libcoretest. Addresses #24214
1 parent 6a3545e commit e09f83e

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
@@ -51,6 +51,7 @@ use ptr;
5151
use mem;
5252
use mem::size_of;
5353
use marker::{Send, Sync, self};
54+
use num::wrapping::OverflowingOps;
5455
use raw::Repr;
5556
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
5657
use raw::Slice as RawSlice;
@@ -1183,6 +1184,34 @@ impl<'a, T> Iterator for Windows<'a, T> {
11831184
(size, Some(size))
11841185
}
11851186
}
1187+
1188+
#[inline]
1189+
fn count(self) -> usize {
1190+
self.size_hint().0
1191+
}
1192+
1193+
#[inline]
1194+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1195+
let (end, overflow) = self.size.overflowing_add(n);
1196+
if end > self.v.len() || overflow {
1197+
self.v = &[];
1198+
None
1199+
} else {
1200+
let nth = &self.v[n..end];
1201+
self.v = &self.v[n+1..];
1202+
Some(nth)
1203+
}
1204+
}
1205+
1206+
#[inline]
1207+
fn last(self) -> Option<Self::Item> {
1208+
if self.size > self.v.len() {
1209+
None
1210+
} else {
1211+
let start = self.v.len() - self.size;
1212+
Some(&self.v[start..])
1213+
}
1214+
}
11861215
}
11871216

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

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

13541449
#[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)