about summary refs log tree commit diff
path: root/src/libcore/slice.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore/slice.rs')
-rw-r--r--src/libcore/slice.rs529
1 files changed, 310 insertions, 219 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 3cc904162a1..eaa52c99c4a 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -57,9 +57,9 @@ use raw::Slice as RawSlice;
 // Extension traits
 //
 
-/// Extension methods for immutable slices.
-#[unstable = "may merge with other traits; region parameter may disappear"]
-pub trait ImmutableSlice<T> for Sized? {
+/// Extension methods for slices.
+#[unstable = "may merge with other traits"]
+pub trait SlicePrelude<T> for Sized? {
     /// Returns a subslice spanning the interval [`start`, `end`).
     ///
     /// Fails when the end of the new slice lies beyond the end of the
@@ -256,216 +256,12 @@ pub trait ImmutableSlice<T> for Sized? {
     #[inline]
     #[experimental = "not triaged yet"]
     fn is_empty(&self) -> bool { self.len() == 0 }
-}
-
-#[unstable]
-impl<T> ImmutableSlice<T> for [T] {
-    #[inline]
-    fn slice(&self, start: uint, end: uint) -> &[T] {
-        assert!(start <= end);
-        assert!(end <= self.len());
-        unsafe {
-            transmute(RawSlice {
-                data: self.as_ptr().offset(start as int),
-                len: (end - start)
-            })
-        }
-    }
-
-    #[inline]
-    fn slice_from(&self, start: uint) -> &[T] {
-        self.slice(start, self.len())
-    }
-
-    #[inline]
-    fn slice_to(&self, end: uint) -> &[T] {
-        self.slice(0, end)
-    }
-
-    #[inline]
-    fn split_at(&self, mid: uint) -> (&[T], &[T]) {
-        (self[..mid], self[mid..])
-    }
-
-    #[inline]
-    fn iter<'a>(&'a self) -> Items<'a, T> {
-        unsafe {
-            let p = self.as_ptr();
-            if mem::size_of::<T>() == 0 {
-                Items{ptr: p,
-                      end: (p as uint + self.len()) as *const T,
-                      marker: marker::ContravariantLifetime::<'a>}
-            } else {
-                Items{ptr: p,
-                      end: p.offset(self.len() as int),
-                      marker: marker::ContravariantLifetime::<'a>}
-            }
-        }
-    }
-
-    #[inline]
-    fn split<'a>(&'a self, pred: |&T|: 'a -> bool) -> Splits<'a, T> {
-        Splits {
-            v: self,
-            pred: pred,
-            finished: false
-        }
-    }
 
-    #[inline]
-    fn splitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: false
-        }
-    }
-
-    #[inline]
-    fn rsplitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
-        SplitsN {
-            iter: self.split(pred),
-            count: n,
-            invert: true
-        }
-    }
-
-    #[inline]
-    fn windows(&self, size: uint) -> Windows<T> {
-        assert!(size != 0);
-        Windows { v: self, size: size }
-    }
-
-    #[inline]
-    fn chunks(&self, size: uint) -> Chunks<T> {
-        assert!(size != 0);
-        Chunks { v: self, size: size }
-    }
-
-    #[inline]
-    fn get(&self, index: uint) -> Option<&T> {
-        if index < self.len() { Some(&self[index]) } else { None }
-    }
-
-    #[inline]
-    fn head(&self) -> Option<&T> {
-        if self.len() == 0 { None } else { Some(&self[0]) }
-    }
-
-    #[inline]
-    fn tail(&self) -> &[T] { self[1..] }
-
-    #[inline]
-    fn init(&self) -> &[T] {
-        self[..self.len() - 1]
-    }
-
-    #[inline]
-    fn last(&self) -> Option<&T> {
-        if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
-    }
-
-    #[inline]
-    unsafe fn unsafe_get(&self, index: uint) -> &T {
-        transmute(self.repr().data.offset(index as int))
-    }
-
-    #[inline]
-    fn as_ptr(&self) -> *const T {
-        self.repr().data
-    }
-
-    #[unstable]
-    fn binary_search(&self, f: |&T| -> Ordering) -> BinarySearchResult {
-        let mut base : uint = 0;
-        let mut lim : uint = self.len();
-
-        while lim != 0 {
-            let ix = base + (lim >> 1);
-            match f(&self[ix]) {
-                Equal => return Found(ix),
-                Less => {
-                    base = ix + 1;
-                    lim -= 1;
-                }
-                Greater => ()
-            }
-            lim >>= 1;
-        }
-        return NotFound(base);
-    }
-
-    #[inline]
-    fn len(&self) -> uint { self.repr().len }
-}
-
-
-
-impl<T> ops::Slice<uint, [T]> for [T] {
-    #[inline]
-    fn as_slice_<'a>(&'a self) -> &'a [T] {
-        self
-    }
-
-    #[inline]
-    fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
-        self.slice_or_fail(start, &self.len())
-    }
-
-    #[inline]
-    fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
-        self.slice_or_fail(&0, end)
-    }
-    #[inline]
-    fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
-        assert!(*start <= *end);
-        assert!(*end <= self.len());
-        unsafe {
-            transmute(RawSlice {
-                    data: self.as_ptr().offset(*start as int),
-                    len: (*end - *start)
-                })
-        }
-    }
-}
-
-impl<T> ops::SliceMut<uint, [T]> for [T] {
-    #[inline]
-    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
-        self
-    }
-
-    #[inline]
-    fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
-        let len = &self.len();
-        self.slice_or_fail_mut(start, len)
-    }
-
-    #[inline]
-    fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
-        self.slice_or_fail_mut(&0, end)
-    }
-    #[inline]
-    fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
-        assert!(*start <= *end);
-        assert!(*end <= self.len());
-        unsafe {
-            transmute(RawSlice {
-                    data: self.as_ptr().offset(*start as int),
-                    len: (*end - *start)
-                })
-        }
-    }
-}
-
-/// Extension methods for slices such that their elements are
-/// mutable.
-#[experimental = "may merge with other traits; may lose region param; needs review"]
-pub trait MutableSlice<T> for Sized? {
     /// Returns a mutable reference to the element at the given index,
     /// or `None` if the index is out of bounds
     #[unstable = "waiting on final error conventions"]
     fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
+
     /// Work with `self` as a mut slice.
     /// Primarily intended for getting a &mut [T] from a [T, ..N].
     fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
@@ -626,8 +422,146 @@ pub trait MutableSlice<T> for Sized? {
     fn as_mut_ptr(&mut self) -> *mut T;
 }
 
-#[experimental = "trait is experimental"]
-impl<T> MutableSlice<T> for [T] {
+#[unstable]
+impl<T> SlicePrelude<T> for [T] {
+    #[inline]
+    fn slice(&self, start: uint, end: uint) -> &[T] {
+        assert!(start <= end);
+        assert!(end <= self.len());
+        unsafe {
+            transmute(RawSlice {
+                data: self.as_ptr().offset(start as int),
+                len: (end - start)
+            })
+        }
+    }
+
+    #[inline]
+    fn slice_from(&self, start: uint) -> &[T] {
+        self.slice(start, self.len())
+    }
+
+    #[inline]
+    fn slice_to(&self, end: uint) -> &[T] {
+        self.slice(0, end)
+    }
+
+    #[inline]
+    fn split_at(&self, mid: uint) -> (&[T], &[T]) {
+        (self[..mid], self[mid..])
+    }
+
+    #[inline]
+    fn iter<'a>(&'a self) -> Items<'a, T> {
+        unsafe {
+            let p = self.as_ptr();
+            if mem::size_of::<T>() == 0 {
+                Items{ptr: p,
+                      end: (p as uint + self.len()) as *const T,
+                      marker: marker::ContravariantLifetime::<'a>}
+            } else {
+                Items{ptr: p,
+                      end: p.offset(self.len() as int),
+                      marker: marker::ContravariantLifetime::<'a>}
+            }
+        }
+    }
+
+    #[inline]
+    fn split<'a>(&'a self, pred: |&T|: 'a -> bool) -> Splits<'a, T> {
+        Splits {
+            v: self,
+            pred: pred,
+            finished: false
+        }
+    }
+
+    #[inline]
+    fn splitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
+        SplitsN {
+            iter: self.split(pred),
+            count: n,
+            invert: false
+        }
+    }
+
+    #[inline]
+    fn rsplitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
+        SplitsN {
+            iter: self.split(pred),
+            count: n,
+            invert: true
+        }
+    }
+
+    #[inline]
+    fn windows(&self, size: uint) -> Windows<T> {
+        assert!(size != 0);
+        Windows { v: self, size: size }
+    }
+
+    #[inline]
+    fn chunks(&self, size: uint) -> Chunks<T> {
+        assert!(size != 0);
+        Chunks { v: self, size: size }
+    }
+
+    #[inline]
+    fn get(&self, index: uint) -> Option<&T> {
+        if index < self.len() { Some(&self[index]) } else { None }
+    }
+
+    #[inline]
+    fn head(&self) -> Option<&T> {
+        if self.len() == 0 { None } else { Some(&self[0]) }
+    }
+
+    #[inline]
+    fn tail(&self) -> &[T] { self[1..] }
+
+    #[inline]
+    fn init(&self) -> &[T] {
+        self[..self.len() - 1]
+    }
+
+    #[inline]
+    fn last(&self) -> Option<&T> {
+        if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
+    }
+
+    #[inline]
+    unsafe fn unsafe_get(&self, index: uint) -> &T {
+        transmute(self.repr().data.offset(index as int))
+    }
+
+    #[inline]
+    fn as_ptr(&self) -> *const T {
+        self.repr().data
+    }
+
+    #[unstable]
+    fn binary_search(&self, f: |&T| -> Ordering) -> BinarySearchResult {
+        let mut base : uint = 0;
+        let mut lim : uint = self.len();
+
+        while lim != 0 {
+            let ix = base + (lim >> 1);
+            match f(&self[ix]) {
+                Equal => return Found(ix),
+                Less => {
+                    base = ix + 1;
+                    lim -= 1;
+                }
+                Greater => ()
+            }
+            lim >>= 1;
+        }
+        return NotFound(base);
+    }
+
+    #[inline]
+    fn len(&self) -> uint { self.repr().len }
+
     #[inline]
     fn get_mut(&mut self, index: uint) -> Option<&mut T> {
         if index < self.len() { Some(&mut self[index]) } else { None }
@@ -764,9 +698,66 @@ impl<T> MutableSlice<T> for [T] {
     }
 }
 
+impl<T> ops::Slice<uint, [T]> for [T] {
+    #[inline]
+    fn as_slice_<'a>(&'a self) -> &'a [T] {
+        self
+    }
+
+    #[inline]
+    fn slice_from_or_fail<'a>(&'a self, start: &uint) -> &'a [T] {
+        self.slice_or_fail(start, &self.len())
+    }
+
+    #[inline]
+    fn slice_to_or_fail<'a>(&'a self, end: &uint) -> &'a [T] {
+        self.slice_or_fail(&0, end)
+    }
+    #[inline]
+    fn slice_or_fail<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
+        assert!(*start <= *end);
+        assert!(*end <= self.len());
+        unsafe {
+            transmute(RawSlice {
+                    data: self.as_ptr().offset(*start as int),
+                    len: (*end - *start)
+                })
+        }
+    }
+}
+
+impl<T> ops::SliceMut<uint, [T]> for [T] {
+    #[inline]
+    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
+        self
+    }
+
+    #[inline]
+    fn slice_from_or_fail_mut<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
+        let len = &self.len();
+        self.slice_or_fail_mut(start, len)
+    }
+
+    #[inline]
+    fn slice_to_or_fail_mut<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
+        self.slice_or_fail_mut(&0, end)
+    }
+    #[inline]
+    fn slice_or_fail_mut<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
+        assert!(*start <= *end);
+        assert!(*end <= self.len());
+        unsafe {
+            transmute(RawSlice {
+                    data: self.as_ptr().offset(*start as int),
+                    len: (*end - *start)
+                })
+        }
+    }
+}
+
 /// Extension methods for slices containing `PartialEq` elements.
 #[unstable = "may merge with other traits"]
-pub trait ImmutablePartialEqSlice<T: PartialEq> for Sized? {
+pub trait PartialEqSlicePrelude<T: PartialEq> for Sized? {
     /// Find the first index containing a matching value.
     fn position_elem(&self, t: &T) -> Option<uint>;
 
@@ -784,7 +775,7 @@ pub trait ImmutablePartialEqSlice<T: PartialEq> for Sized? {
 }
 
 #[unstable = "trait is unstable"]
-impl<T: PartialEq> ImmutablePartialEqSlice<T> for [T] {
+impl<T: PartialEq> PartialEqSlicePrelude<T> for [T] {
     #[inline]
     fn position_elem(&self, x: &T) -> Option<uint> {
         self.iter().position(|y| *x == *y)
@@ -815,7 +806,7 @@ impl<T: PartialEq> ImmutablePartialEqSlice<T> for [T] {
 
 /// Extension methods for slices containing `Ord` elements.
 #[unstable = "may merge with other traits"]
-pub trait ImmutableOrdSlice<T: Ord> for Sized? {
+pub trait OrdSlicePrelude<T: Ord> for Sized? {
     /// Binary search a sorted slice for a given element.
     ///
     /// If the value is found then `Found` is returned, containing the
@@ -842,19 +833,119 @@ pub trait ImmutableOrdSlice<T: Ord> for Sized? {
     /// ```
     #[unstable = "name likely to change"]
     fn binary_search_elem(&self, x: &T) -> BinarySearchResult;
+
+    /// Mutates the slice to the next lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// last-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [0i, 1, 2];
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.next_permutation();
+    /// let b: &mut [_] = &mut [1i, 0, 2];
+    /// assert!(v == b);
+    /// ```
+    #[experimental]
+    fn next_permutation(&mut self) -> bool;
+
+    /// Mutates the slice to the previous lexicographic permutation.
+    ///
+    /// Returns `true` if successful and `false` if the slice is at the
+    /// first-ordered permutation.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// let v: &mut [_] = &mut [1i, 0, 2];
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 2, 1];
+    /// assert!(v == b);
+    /// v.prev_permutation();
+    /// let b: &mut [_] = &mut [0i, 1, 2];
+    /// assert!(v == b);
+    /// ```
+    #[experimental]
+    fn prev_permutation(&mut self) -> bool;
 }
 
 #[unstable = "trait is unstable"]
-impl<T: Ord> ImmutableOrdSlice<T> for [T] {
+impl<T: Ord> OrdSlicePrelude<T> for [T] {
     #[unstable]
     fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
         self.binary_search(|p| p.cmp(x))
     }
+
+    #[experimental]
+    fn next_permutation(&mut self) -> bool {
+        // These cases only have 1 permutation each, so we can't do anything.
+        if self.len() < 2 { return false; }
+
+        // Step 1: Identify the longest, rightmost weakly decreasing part of the vector
+        let mut i = self.len() - 1;
+        while i > 0 && self[i-1] >= self[i] {
+            i -= 1;
+        }
+
+        // If that is the entire vector, this is the last-ordered permutation.
+        if i == 0 {
+            return false;
+        }
+
+        // Step 2: Find the rightmost element larger than the pivot (i-1)
+        let mut j = self.len() - 1;
+        while j >= i && self[j] <= self[i-1]  {
+            j -= 1;
+        }
+
+        // Step 3: Swap that element with the pivot
+        self.swap(j, i-1);
+
+        // Step 4: Reverse the (previously) weakly decreasing part
+        self[mut i..].reverse();
+
+        true
+    }
+
+    #[experimental]
+    fn prev_permutation(&mut self) -> bool {
+        // These cases only have 1 permutation each, so we can't do anything.
+        if self.len() < 2 { return false; }
+
+        // Step 1: Identify the longest, rightmost weakly increasing part of the vector
+        let mut i = self.len() - 1;
+        while i > 0 && self[i-1] <= self[i] {
+            i -= 1;
+        }
+
+        // If that is the entire vector, this is the first-ordered permutation.
+        if i == 0 {
+            return false;
+        }
+
+        // Step 2: Reverse the weakly increasing part
+        self[mut i..].reverse();
+
+        // Step 3: Find the rightmost element equal to or bigger than the pivot (i-1)
+        let mut j = self.len() - 1;
+        while j >= i && self[j-1] < self[i-1]  {
+            j -= 1;
+        }
+
+        // Step 4: Swap that element with the pivot
+        self.swap(i-1, j);
+
+        true
+    }
 }
 
-/// Trait for &[T] where T is Cloneable
+/// Extension methods for slices on Clone elements
 #[unstable = "may merge with other traits"]
-pub trait MutableCloneableSlice<T> for Sized? {
+pub trait CloneSlicePrelude<T> for Sized? {
     /// Copies as many elements from `src` as it can into `self` (the
     /// shorter of `self.len()` and `src.len()`). Returns the number
     /// of elements copied.
@@ -862,7 +953,7 @@ pub trait MutableCloneableSlice<T> for Sized? {
     /// # Example
     ///
     /// ```rust
-    /// use std::slice::MutableCloneableSlice;
+    /// use std::slice::CloneSlicePrelude;
     ///
     /// let mut dst = [0i, 0, 0];
     /// let src = [1i, 2];
@@ -878,7 +969,7 @@ pub trait MutableCloneableSlice<T> for Sized? {
 }
 
 #[unstable = "trait is unstable"]
-impl<T: Clone> MutableCloneableSlice<T> for [T] {
+impl<T: Clone> CloneSlicePrelude<T> for [T] {
     #[inline]
     fn clone_from_slice(&mut self, src: &[T]) -> uint {
         let min = cmp::min(self.len(), src.len());
@@ -1517,7 +1608,7 @@ pub mod raw {
 pub mod bytes {
     use kinds::Sized;
     use ptr;
-    use slice::{ImmutableSlice, MutableSlice};
+    use slice::SlicePrelude;
 
     /// A trait for operations on mutable `[u8]`s.
     pub trait MutableByteVector for Sized? {