diff options
| author | Huon Wilson <dbau.pp+github@gmail.com> | 2014-11-15 14:44:55 +1100 |
|---|---|---|
| committer | Huon Wilson <dbau.pp+github@gmail.com> | 2014-11-25 17:10:32 +1100 |
| commit | b86a7808c74fa0da1f1fcb9b7df760314f9e4104 (patch) | |
| tree | 40bc88044c4b03681b4c67d2b4373e0649e8c95f /src/libcore | |
| parent | bb2168c5252adeda1dd35ccf7050df89655233d7 (diff) | |
Add methods to go from a slice iterators to a slice.
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`.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/slice.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 665b6705dad..65f61791127 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1092,6 +1092,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 #[experimental = "needs review"] pub struct Items<'a, T: 'a> { @@ -1100,6 +1115,36 @@ pub struct Items<'a, T: '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} #[experimental = "needs review"] @@ -1144,6 +1189,57 @@ pub struct MutItems<'a, T: 'a> { 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} #[experimental = "needs review"] |
