auto merge of #18966 : huonw/rust/iter2slice, r=aturon
A slice iterator is isomorphic to a slice, just with a slightly different form: storing start and end pointers rather than start pointer and length. This patch reflects this by making converting between them as easy as `iter.as_slice()` (or even `iter[]` if the shorter lifetime is ok). That is, `slice.iter().as_slice() == slice`. r? @aturon
This commit is contained in:
@@ -1104,6 +1104,21 @@ macro_rules! iterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! make_slice {
|
||||||
|
($t: ty -> $result: ty: $start: expr, $end: expr) => {{
|
||||||
|
let diff = $end as uint - $start as uint;
|
||||||
|
let len = if mem::size_of::<T>() == 0 {
|
||||||
|
diff
|
||||||
|
} else {
|
||||||
|
diff / mem::size_of::<$t>()
|
||||||
|
};
|
||||||
|
unsafe {
|
||||||
|
transmute::<_, $result>(RawSlice { data: $start as *const T, len: len })
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Immutable slice iterator
|
/// Immutable slice iterator
|
||||||
#[experimental = "needs review"]
|
#[experimental = "needs review"]
|
||||||
pub struct Items<'a, T: 'a> {
|
pub struct Items<'a, T: 'a> {
|
||||||
@@ -1112,6 +1127,36 @@ pub struct Items<'a, T: 'a> {
|
|||||||
marker: marker::ContravariantLifetime<'a>
|
marker: marker::ContravariantLifetime<'a>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[experimental]
|
||||||
|
impl<'a, T> ops::Slice<uint, [T]> for Items<'a, T> {
|
||||||
|
fn as_slice_(&self) -> &[T] {
|
||||||
|
self.as_slice()
|
||||||
|
}
|
||||||
|
fn slice_from_or_fail<'b>(&'b self, from: &uint) -> &'b [T] {
|
||||||
|
use ops::Slice;
|
||||||
|
self.as_slice().slice_from_or_fail(from)
|
||||||
|
}
|
||||||
|
fn slice_to_or_fail<'b>(&'b self, to: &uint) -> &'b [T] {
|
||||||
|
use ops::Slice;
|
||||||
|
self.as_slice().slice_to_or_fail(to)
|
||||||
|
}
|
||||||
|
fn slice_or_fail<'b>(&'b self, from: &uint, to: &uint) -> &'b [T] {
|
||||||
|
use ops::Slice;
|
||||||
|
self.as_slice().slice_or_fail(from, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Items<'a, T> {
|
||||||
|
/// View the underlying data as a subslice of the original data.
|
||||||
|
///
|
||||||
|
/// This has the same lifetime as the original slice, and so the
|
||||||
|
/// iterator can continue to be used while this exists.
|
||||||
|
#[experimental]
|
||||||
|
pub fn as_slice(&self) -> &'a [T] {
|
||||||
|
make_slice!(T -> &'a [T]: self.ptr, self.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iterator!{struct Items -> *const T, &'a T}
|
iterator!{struct Items -> *const T, &'a T}
|
||||||
|
|
||||||
#[experimental = "needs review"]
|
#[experimental = "needs review"]
|
||||||
@@ -1156,6 +1201,57 @@ pub struct MutItems<'a, T: 'a> {
|
|||||||
marker2: marker::NoCopy
|
marker2: marker::NoCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[experimental]
|
||||||
|
impl<'a, T> ops::Slice<uint, [T]> for MutItems<'a, T> {
|
||||||
|
fn as_slice_<'b>(&'b self) -> &'b [T] {
|
||||||
|
make_slice!(T -> &'b [T]: self.ptr, self.end)
|
||||||
|
}
|
||||||
|
fn slice_from_or_fail<'b>(&'b self, from: &uint) -> &'b [T] {
|
||||||
|
use ops::Slice;
|
||||||
|
self.as_slice_().slice_from_or_fail(from)
|
||||||
|
}
|
||||||
|
fn slice_to_or_fail<'b>(&'b self, to: &uint) -> &'b [T] {
|
||||||
|
use ops::Slice;
|
||||||
|
self.as_slice_().slice_to_or_fail(to)
|
||||||
|
}
|
||||||
|
fn slice_or_fail<'b>(&'b self, from: &uint, to: &uint) -> &'b [T] {
|
||||||
|
use ops::Slice;
|
||||||
|
self.as_slice_().slice_or_fail(from, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[experimental]
|
||||||
|
impl<'a, T> ops::SliceMut<uint, [T]> for MutItems<'a, T> {
|
||||||
|
fn as_mut_slice_<'b>(&'b mut self) -> &'b mut [T] {
|
||||||
|
make_slice!(T -> &'b mut [T]: self.ptr, self.end)
|
||||||
|
}
|
||||||
|
fn slice_from_or_fail_mut<'b>(&'b mut self, from: &uint) -> &'b mut [T] {
|
||||||
|
use ops::SliceMut;
|
||||||
|
self.as_mut_slice_().slice_from_or_fail_mut(from)
|
||||||
|
}
|
||||||
|
fn slice_to_or_fail_mut<'b>(&'b mut self, to: &uint) -> &'b mut [T] {
|
||||||
|
use ops::SliceMut;
|
||||||
|
self.as_mut_slice_().slice_to_or_fail_mut(to)
|
||||||
|
}
|
||||||
|
fn slice_or_fail_mut<'b>(&'b mut self, from: &uint, to: &uint) -> &'b mut [T] {
|
||||||
|
use ops::SliceMut;
|
||||||
|
self.as_mut_slice_().slice_or_fail_mut(from, to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> MutItems<'a, T> {
|
||||||
|
/// View the underlying data as a subslice of the original data.
|
||||||
|
///
|
||||||
|
/// To avoid creating `&mut` references that alias, this is forced
|
||||||
|
/// to consume the iterator. Consider using the `Slice` and
|
||||||
|
/// `SliceMut` implementations for obtaining slices with more
|
||||||
|
/// restricted lifetimes that do not consume the iterator.
|
||||||
|
#[experimental]
|
||||||
|
pub fn into_slice(self) -> &'a mut [T] {
|
||||||
|
make_slice!(T -> &'a mut [T]: self.ptr, self.end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iterator!{struct MutItems -> *mut T, &'a mut T}
|
iterator!{struct MutItems -> *mut T, &'a mut T}
|
||||||
|
|
||||||
#[experimental = "needs review"]
|
#[experimental = "needs review"]
|
||||||
|
|||||||
@@ -33,3 +33,52 @@ fn binary_search_not_found() {
|
|||||||
let b = [1i, 2, 4, 5, 6, 8];
|
let b = [1i, 2, 4, 5, 6, 8];
|
||||||
assert!(b.binary_search(|v| v.cmp(&9)) == NotFound(6));
|
assert!(b.binary_search(|v| v.cmp(&9)) == NotFound(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iterator_to_slice() {
|
||||||
|
macro_rules! test {
|
||||||
|
($data: expr) => {{
|
||||||
|
let data: &mut [_] = &mut $data;
|
||||||
|
let other_data: &mut [_] = &mut $data;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut iter = data.iter();
|
||||||
|
assert_eq!(iter[], other_data[]);
|
||||||
|
|
||||||
|
iter.next();
|
||||||
|
assert_eq!(iter[], other_data[1..]);
|
||||||
|
|
||||||
|
iter.next_back();
|
||||||
|
assert_eq!(iter[], other_data[1..2]);
|
||||||
|
|
||||||
|
let s = iter.as_slice();
|
||||||
|
iter.next();
|
||||||
|
assert_eq!(s, other_data[1..2]);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut iter = data.iter_mut();
|
||||||
|
assert_eq!(iter[], other_data[]);
|
||||||
|
// mutability:
|
||||||
|
assert!(iter[mut] == other_data);
|
||||||
|
|
||||||
|
iter.next();
|
||||||
|
assert_eq!(iter[], other_data[1..]);
|
||||||
|
assert!(iter[mut] == other_data[mut 1..]);
|
||||||
|
|
||||||
|
iter.next_back();
|
||||||
|
|
||||||
|
assert_eq!(iter[], other_data[1..2]);
|
||||||
|
assert!(iter[mut] == other_data[mut 1..2]);
|
||||||
|
|
||||||
|
let s = iter.into_slice();
|
||||||
|
assert!(s == other_data[mut 1..2]);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try types of a variety of sizes
|
||||||
|
test!([(1u64, 1u64, 1u8), (2, 2, 2), (3, 3, 3)]);
|
||||||
|
test!([1u64,2,3]);
|
||||||
|
test!([1u8,2,3]);
|
||||||
|
test!([(),(),()]);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user