about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2014-11-15 14:44:55 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2014-11-25 17:10:32 +1100
commitb86a7808c74fa0da1f1fcb9b7df760314f9e4104 (patch)
tree40bc88044c4b03681b4c67d2b4373e0649e8c95f /src/libcore
parentbb2168c5252adeda1dd35ccf7050df89655233d7 (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.rs96
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"]