Skip to content

Commit f2a01ea

Browse files
author
Palmer Cox
committed
Implement mut_chunks() method for MutableVector trait.
mut_chunks() returns an iterator that produces mutable slices. This is the mutable version of the existing chunks() method on the ImmutableVector trait.
1 parent dfe46f7 commit f2a01ea

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

src/libstd/vec.rs

+73
Original file line numberDiff line numberDiff line change
@@ -1933,6 +1933,18 @@ pub trait MutableVector<'self, T> {
19331933
/// Returns a reversed iterator that allows modifying each value
19341934
fn mut_rev_iter(self) -> MutRevIterator<'self, T>;
19351935

1936+
/**
1937+
* Returns an iterator over `size` elements of the vector at a time.
1938+
* The chunks are mutable and do not overlap. If `size` does not divide the
1939+
* length of the vector, then the last chunk will not have length
1940+
* `size`.
1941+
*
1942+
* # Failure
1943+
*
1944+
* Fails if `size` is 0.
1945+
*/
1946+
fn mut_chunks(self, chunk_size: uint) -> MutChunkIter<'self, T>;
1947+
19361948
/**
19371949
* Returns a mutable reference to the first element in this slice
19381950
* and adjusts the slice in place so that it no longer contains
@@ -2069,6 +2081,13 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
20692081
self.mut_iter().invert()
20702082
}
20712083

2084+
#[inline]
2085+
fn mut_chunks(self, chunk_size: uint) -> MutChunkIter<'self, T> {
2086+
assert!(chunk_size > 0);
2087+
let len = self.len();
2088+
MutChunkIter { v: self, chunk_size: chunk_size, remaining: len }
2089+
}
2090+
20722091
fn mut_shift_ref(&mut self) -> &'self mut T {
20732092
unsafe {
20742093
let s: &mut Slice<T> = cast::transmute(self);
@@ -2556,6 +2575,42 @@ impl<'self, T> Clone for VecIterator<'self, T> {
25562575
iterator!{struct VecMutIterator -> *mut T, &'self mut T}
25572576
pub type MutRevIterator<'self, T> = Invert<VecMutIterator<'self, T>>;
25582577

2578+
/// An iterator over a vector in (non-overlapping) mutable chunks (`size` elements at a time). When
2579+
/// the vector len is not evenly divided by the chunk size, the last slice of the iteration will be
2580+
/// the remainder.
2581+
pub struct MutChunkIter<'self, T> {
2582+
priv v: &'self mut [T],
2583+
priv chunk_size: uint,
2584+
priv remaining: uint
2585+
}
2586+
2587+
impl<'self, T> Iterator<&'self mut [T]> for MutChunkIter<'self, T> {
2588+
#[inline]
2589+
fn next(&mut self) -> Option<&'self mut [T]> {
2590+
if self.remaining == 0 {
2591+
None
2592+
} else {
2593+
let sz = cmp::min(self.remaining, self.chunk_size);
2594+
let tmp = util::replace(&mut self.v, &mut []);
2595+
let (head, tail) = tmp.mut_split(sz);
2596+
self.v = tail;
2597+
self.remaining -= sz;
2598+
Some(head)
2599+
}
2600+
}
2601+
2602+
#[inline]
2603+
fn size_hint(&self) -> (uint, Option<uint>) {
2604+
if self.remaining == 0 {
2605+
(0, Some(0))
2606+
} else {
2607+
let (n, rem) = self.remaining.div_rem(&self.chunk_size);
2608+
let n = if rem > 0 { n + 1 } else { n };
2609+
(n, Some(n))
2610+
}
2611+
}
2612+
}
2613+
25592614
/// An iterator that moves out of a vector.
25602615
#[deriving(Clone)]
25612616
pub struct MoveIterator<T> {
@@ -3966,6 +4021,24 @@ mod tests {
39664021
x.pop_ref();
39674022
}
39684023

4024+
#[test]
4025+
fn test_mut_chunks() {
4026+
let mut v = [0u8, 1, 2, 3, 4, 5, 6];
4027+
for (i, chunk) in v.mut_chunks(3).enumerate() {
4028+
for x in chunk.mut_iter() {
4029+
*x = i as u8;
4030+
}
4031+
}
4032+
let result = [0u8, 0, 0, 1, 1, 1, 2];
4033+
assert_eq!(v, result);
4034+
}
4035+
4036+
#[test]
4037+
#[should_fail]
4038+
fn test_mut_chunks_0() {
4039+
let mut v = [1, 2, 3, 4];
4040+
let _it = v.mut_chunks(0);
4041+
}
39694042

39704043
#[test]
39714044
fn test_mut_shift_ref() {

0 commit comments

Comments
 (0)