Skip to content

Commit 848dbc9

Browse files
committed
std: add an external iterator for mutating vec elements
1 parent f5ef076 commit 848dbc9

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/libstd/vec.rs

+44
Original file line numberDiff line numberDiff line change
@@ -2427,6 +2427,7 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
24272427
#[allow(missing_doc)]
24282428
pub trait MutableVector<'self, T> {
24292429
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T];
2430+
fn mut_iter(self) -> MutVecIterator<'self, T>;
24302431

24312432
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
24322433
unsafe fn unsafe_set(&self, index: uint, val: T);
@@ -2438,6 +2439,15 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
24382439
mut_slice(self, start, end)
24392440
}
24402441

2442+
#[inline]
2443+
fn mut_iter(self) -> MutVecIterator<'self, T> {
2444+
unsafe {
2445+
let p = vec::raw::to_mut_ptr(self);
2446+
MutVecIterator{ptr: p, end: p.offset(self.len()),
2447+
lifetime: cast::transmute(p)}
2448+
}
2449+
}
2450+
24412451
#[inline(always)]
24422452
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T {
24432453
let pair_ptr: &(*mut T, uint) = transmute(self);
@@ -2962,6 +2972,30 @@ impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> {
29622972
}
29632973
}
29642974

2975+
/// An external iterator for vectors with the possibility of mutating
2976+
/// elements. (use with the std::iterator module)
2977+
pub struct MutVecIterator<'self, T> {
2978+
priv ptr: *mut T,
2979+
priv end: *mut T,
2980+
priv lifetime: &'self mut T // FIXME: #5922
2981+
}
2982+
2983+
// could be implemented with &[T] with .slice(), but this avoids bounds checks
2984+
impl<'self, T> Iterator<&'self mut T> for MutVecIterator<'self, T> {
2985+
#[inline]
2986+
fn next(&mut self) -> Option<&'self mut T> {
2987+
unsafe {
2988+
if self.ptr == self.end {
2989+
None
2990+
} else {
2991+
let old = self.ptr;
2992+
self.ptr = self.ptr.offset(1);
2993+
Some(cast::transmute(old))
2994+
}
2995+
}
2996+
}
2997+
}
2998+
29652999
#[cfg(test)]
29663000
mod tests {
29673001
use option::{None, Option, Some};
@@ -4669,6 +4703,16 @@ mod tests {
46694703
}
46704704
}
46714705

4706+
#[test]
4707+
fn test_mut_iterator() {
4708+
use iterator::*;
4709+
let mut xs = [1, 2, 3, 4, 5];
4710+
for xs.mut_iter().advance |x| {
4711+
*x += 1;
4712+
}
4713+
assert_eq!(xs, [2, 3, 4, 5, 6])
4714+
}
4715+
46724716
#[test]
46734717
fn test_reverse_part() {
46744718
let mut values = [1,2,3,4,5];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::iterator::*;
12+
13+
fn main() {
14+
let mut xs = ~[1, 2, 3, 4];
15+
16+
for xs.mut_iter().advance |x| {
17+
xs.push(1) //~ ERROR cannot borrow `xs` as mutable
18+
}
19+
}

0 commit comments

Comments
 (0)