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
This commit is contained in:
Alex Ozdemir
2015-08-07 00:10:31 -07:00
committed by Alex Ozdemir
parent 6a3545ef05
commit e09f83ea44
2 changed files with 215 additions and 0 deletions

View File

@@ -51,6 +51,7 @@ use ptr;
use mem;
use mem::size_of;
use marker::{Send, Sync, self};
use num::wrapping::OverflowingOps;
use raw::Repr;
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
use raw::Slice as RawSlice;
@@ -1183,6 +1184,34 @@ impl<'a, T> Iterator for Windows<'a, T> {
(size, Some(size))
}
}
#[inline]
fn count(self) -> usize {
self.size_hint().0
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let (end, overflow) = self.size.overflowing_add(n);
if end > self.v.len() || overflow {
self.v = &[];
None
} else {
let nth = &self.v[n..end];
self.v = &self.v[n+1..];
Some(nth)
}
}
#[inline]
fn last(self) -> Option<Self::Item> {
if self.size > self.v.len() {
None
} else {
let start = self.v.len() - self.size;
Some(&self.v[start..])
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1269,6 +1298,38 @@ impl<'a, T> Iterator for Chunks<'a, T> {
(n, Some(n))
}
}
#[inline]
fn count(self) -> usize {
self.size_hint().0
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
let (start, overflow) = n.overflowing_mul(self.size);
if start >= self.v.len() || overflow {
self.v = &[];
None
} else {
let end = match start.checked_add(self.size) {
Some(sum) => cmp::min(self.v.len(), sum),
None => self.v.len(),
};
let nth = &self.v[start..end];
self.v = &self.v[end..];
Some(nth)
}
}
#[inline]
fn last(self) -> Option<Self::Item> {
if self.v.is_empty() {
None
} else {
let start = (self.v.len() - 1) / self.size * self.size;
Some(&self.v[start..])
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1349,6 +1410,40 @@ impl<'a, T> Iterator for ChunksMut<'a, T> {
(n, Some(n))
}
}
#[inline]
fn count(self) -> usize {
self.size_hint().0
}
#[inline]
fn nth(&mut self, n: usize) -> Option<&'a mut [T]> {
let (start, overflow) = n.overflowing_mul(self.chunk_size);
if start >= self.v.len() || overflow {
self.v = &mut [];
None
} else {
let end = match start.checked_add(self.chunk_size) {
Some(sum) => cmp::min(self.v.len(), sum),
None => self.v.len(),
};
let tmp = mem::replace(&mut self.v, &mut []);
let (head, tail) = tmp.split_at_mut(end);
let (_, nth) = head.split_at_mut(start);
self.v = tail;
Some(nth)
}
}
#[inline]
fn last(self) -> Option<Self::Item> {
if self.v.is_empty() {
None
} else {
let start = (self.v.len() - 1) / self.chunk_size * self.chunk_size;
Some(&mut self.v[start..])
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]