std: add an external iterator for mutating vec elements

This commit is contained in:
Huon Wilson 2013-06-06 15:12:39 +10:00
parent f5ef0766da
commit 848dbc93ee
2 changed files with 63 additions and 0 deletions

View File

@ -2427,6 +2427,7 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
#[allow(missing_doc)]
pub trait MutableVector<'self, T> {
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T];
fn mut_iter(self) -> MutVecIterator<'self, T>;
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
unsafe fn unsafe_set(&self, index: uint, val: T);
@ -2438,6 +2439,15 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
mut_slice(self, start, end)
}
#[inline]
fn mut_iter(self) -> MutVecIterator<'self, T> {
unsafe {
let p = vec::raw::to_mut_ptr(self);
MutVecIterator{ptr: p, end: p.offset(self.len()),
lifetime: cast::transmute(p)}
}
}
#[inline(always)]
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T {
let pair_ptr: &(*mut T, uint) = transmute(self);
@ -2962,6 +2972,30 @@ impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> {
}
}
/// An external iterator for vectors with the possibility of mutating
/// elements. (use with the std::iterator module)
pub struct MutVecIterator<'self, T> {
priv ptr: *mut T,
priv end: *mut T,
priv lifetime: &'self mut T // FIXME: #5922
}
// could be implemented with &[T] with .slice(), but this avoids bounds checks
impl<'self, T> Iterator<&'self mut T> for MutVecIterator<'self, T> {
#[inline]
fn next(&mut self) -> Option<&'self mut T> {
unsafe {
if self.ptr == self.end {
None
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
Some(cast::transmute(old))
}
}
}
}
#[cfg(test)]
mod tests {
use option::{None, Option, Some};
@ -4669,6 +4703,16 @@ mod tests {
}
}
#[test]
fn test_mut_iterator() {
use iterator::*;
let mut xs = [1, 2, 3, 4, 5];
for xs.mut_iter().advance |x| {
*x += 1;
}
assert_eq!(xs, [2, 3, 4, 5, 6])
}
#[test]
fn test_reverse_part() {
let mut values = [1,2,3,4,5];

View File

@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::iterator::*;
fn main() {
let mut xs = ~[1, 2, 3, 4];
for xs.mut_iter().advance |x| {
xs.push(1) //~ ERROR cannot borrow `xs` as mutable
}
}