Add [mut_]shift_ref/[mut_]pop_ref functions, which return a pointer to the first/last item in the slice and modify the slice to exclude the returned item. Useful when writing iterators over mutable references.
This commit is contained in:
parent
40439516ec
commit
ce44094bbb
|
@ -975,6 +975,40 @@ pub trait ImmutableVector<'self, T> {
|
||||||
* foreign interop.
|
* foreign interop.
|
||||||
*/
|
*/
|
||||||
fn as_imm_buf<U>(&self, f: |*T, uint| -> U) -> U;
|
fn as_imm_buf<U>(&self, f: |*T, uint| -> U) -> U;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable reference to the first element in this slice
|
||||||
|
* and adjusts the slice in place so that it no longer contains
|
||||||
|
* that element. O(1).
|
||||||
|
*
|
||||||
|
* Equivalent to:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* let head = &self[0];
|
||||||
|
* *self = self.slice_from(1);
|
||||||
|
* head
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Fails if slice is empty.
|
||||||
|
*/
|
||||||
|
fn shift_ref(&mut self) -> &'self T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable reference to the last element in this slice
|
||||||
|
* and adjusts the slice in place so that it no longer contains
|
||||||
|
* that element. O(1).
|
||||||
|
*
|
||||||
|
* Equivalent to:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* let tail = &self[self.len() - 1];
|
||||||
|
* *self = self.slice_to(self.len() - 1);
|
||||||
|
* tail
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Fails if slice is empty.
|
||||||
|
*/
|
||||||
|
fn pop_ref(&mut self) -> &'self T;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
||||||
|
@ -1141,6 +1175,20 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
||||||
let s = self.repr();
|
let s = self.repr();
|
||||||
f(s.data, s.len)
|
f(s.data, s.len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn shift_ref(&mut self) -> &'self T {
|
||||||
|
unsafe {
|
||||||
|
let s: &mut Slice<T> = cast::transmute(self);
|
||||||
|
&*raw::shift_ptr(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_ref(&mut self) -> &'self T {
|
||||||
|
unsafe {
|
||||||
|
let s: &mut Slice<T> = cast::transmute(self);
|
||||||
|
&*raw::pop_ptr(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension methods for vectors contain `Eq` elements.
|
/// Extension methods for vectors contain `Eq` elements.
|
||||||
|
@ -1859,23 +1907,61 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
|
||||||
pub trait MutableVector<'self, T> {
|
pub trait MutableVector<'self, T> {
|
||||||
/// Return a slice that points into another slice.
|
/// Return a slice that points into another slice.
|
||||||
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T];
|
fn mut_slice(self, start: uint, end: uint) -> &'self mut [T];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a slice of self from `start` to the end of the vec.
|
* Returns a slice of self from `start` to the end of the vec.
|
||||||
*
|
*
|
||||||
* Fails when `start` points outside the bounds of self.
|
* Fails when `start` points outside the bounds of self.
|
||||||
*/
|
*/
|
||||||
fn mut_slice_from(self, start: uint) -> &'self mut [T];
|
fn mut_slice_from(self, start: uint) -> &'self mut [T];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a slice of self from the start of the vec to `end`.
|
* Returns a slice of self from the start of the vec to `end`.
|
||||||
*
|
*
|
||||||
* Fails when `end` points outside the bounds of self.
|
* Fails when `end` points outside the bounds of self.
|
||||||
*/
|
*/
|
||||||
fn mut_slice_to(self, end: uint) -> &'self mut [T];
|
fn mut_slice_to(self, end: uint) -> &'self mut [T];
|
||||||
|
|
||||||
/// Returns an iterator that allows modifying each value
|
/// Returns an iterator that allows modifying each value
|
||||||
fn mut_iter(self) -> VecMutIterator<'self, T>;
|
fn mut_iter(self) -> VecMutIterator<'self, T>;
|
||||||
|
|
||||||
/// Returns a reversed iterator that allows modifying each value
|
/// Returns a reversed iterator that allows modifying each value
|
||||||
fn mut_rev_iter(self) -> MutRevIterator<'self, T>;
|
fn mut_rev_iter(self) -> MutRevIterator<'self, T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable reference to the first element in this slice
|
||||||
|
* and adjusts the slice in place so that it no longer contains
|
||||||
|
* that element. O(1).
|
||||||
|
*
|
||||||
|
* Equivalent to:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* let head = &mut self[0];
|
||||||
|
* *self = self.mut_slice_from(1);
|
||||||
|
* head
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Fails if slice is empty.
|
||||||
|
*/
|
||||||
|
fn mut_shift_ref(&mut self) -> &'self mut T;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a mutable reference to the last element in this slice
|
||||||
|
* and adjusts the slice in place so that it no longer contains
|
||||||
|
* that element. O(1).
|
||||||
|
*
|
||||||
|
* Equivalent to:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* let tail = &mut self[self.len() - 1];
|
||||||
|
* *self = self.mut_slice_to(self.len() - 1);
|
||||||
|
* tail
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Fails if slice is empty.
|
||||||
|
*/
|
||||||
|
fn mut_pop_ref(&mut self) -> &'self mut T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swaps two elements in a vector
|
* Swaps two elements in a vector
|
||||||
*
|
*
|
||||||
|
@ -1978,6 +2064,20 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
|
||||||
self.mut_iter().invert()
|
self.mut_iter().invert()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mut_shift_ref(&mut self) -> &'self mut T {
|
||||||
|
unsafe {
|
||||||
|
let s: &mut Slice<T> = cast::transmute(self);
|
||||||
|
cast::transmute_mut(&*raw::shift_ptr(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_pop_ref(&mut self) -> &'self mut T {
|
||||||
|
unsafe {
|
||||||
|
let s: &mut Slice<T> = cast::transmute(self);
|
||||||
|
cast::transmute_mut(&*raw::pop_ptr(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn swap(self, a: uint, b: uint) {
|
fn swap(self, a: uint, b: uint) {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Can't take two mutable loans from one vector, so instead just cast
|
// Can't take two mutable loans from one vector, so instead just cast
|
||||||
|
@ -2189,6 +2289,31 @@ pub mod raw {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to first element in slice and adjusts
|
||||||
|
* slice so it no longer contains that element. Fails if
|
||||||
|
* slice is empty. O(1).
|
||||||
|
*/
|
||||||
|
pub unsafe fn shift_ptr<T>(slice: &mut Slice<T>) -> *T {
|
||||||
|
if slice.len == 0 { fail!("shift on empty slice"); }
|
||||||
|
let head: *T = slice.data;
|
||||||
|
slice.data = ptr::offset(slice.data, 1);
|
||||||
|
slice.len -= 1;
|
||||||
|
head
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to last element in slice and adjusts
|
||||||
|
* slice so it no longer contains that element. Fails if
|
||||||
|
* slice is empty. O(1).
|
||||||
|
*/
|
||||||
|
pub unsafe fn pop_ptr<T>(slice: &mut Slice<T>) -> *T {
|
||||||
|
if slice.len == 0 { fail!("pop on empty slice"); }
|
||||||
|
let tail: *T = ptr::offset(slice.data, (slice.len - 1) as int);
|
||||||
|
slice.len -= 1;
|
||||||
|
tail
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Operations on `[u8]`
|
/// Operations on `[u8]`
|
||||||
|
@ -3822,6 +3947,75 @@ mod tests {
|
||||||
assert!(!empty.ends_with(bytes!("foo")));
|
assert!(!empty.ends_with(bytes!("foo")));
|
||||||
assert!(bytes!("foobar").ends_with(empty));
|
assert!(bytes!("foobar").ends_with(empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_shift_ref() {
|
||||||
|
let mut x: &[int] = [1, 2, 3, 4, 5];
|
||||||
|
let h = x.shift_ref();
|
||||||
|
assert_eq!(*h, 1);
|
||||||
|
assert_eq!(x.len(), 4);
|
||||||
|
assert_eq!(x[0], 2);
|
||||||
|
assert_eq!(x[3], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn test_shift_ref_empty() {
|
||||||
|
let mut x: &[int] = [];
|
||||||
|
x.shift_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_pop_ref() {
|
||||||
|
let mut x: &[int] = [1, 2, 3, 4, 5];
|
||||||
|
let h = x.pop_ref();
|
||||||
|
assert_eq!(*h, 5);
|
||||||
|
assert_eq!(x.len(), 4);
|
||||||
|
assert_eq!(x[0], 1);
|
||||||
|
assert_eq!(x[3], 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn test_pop_ref_empty() {
|
||||||
|
let mut x: &[int] = [];
|
||||||
|
x.pop_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_shift_ref() {
|
||||||
|
let mut x: &mut [int] = [1, 2, 3, 4, 5];
|
||||||
|
let h = x.mut_shift_ref();
|
||||||
|
assert_eq!(*h, 1);
|
||||||
|
assert_eq!(x.len(), 4);
|
||||||
|
assert_eq!(x[0], 2);
|
||||||
|
assert_eq!(x[3], 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn test_mut_shift_ref_empty() {
|
||||||
|
let mut x: &mut [int] = [];
|
||||||
|
x.mut_shift_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mut_pop_ref() {
|
||||||
|
let mut x: &mut [int] = [1, 2, 3, 4, 5];
|
||||||
|
let h = x.mut_pop_ref();
|
||||||
|
assert_eq!(*h, 5);
|
||||||
|
assert_eq!(x.len(), 4);
|
||||||
|
assert_eq!(x[0], 1);
|
||||||
|
assert_eq!(x[3], 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn test_mut_pop_ref_empty() {
|
||||||
|
let mut x: &mut [int] = [];
|
||||||
|
x.mut_pop_ref();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
Loading…
Reference in New Issue