about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2014-09-15 20:48:58 +1200
committerNick Cameron <ncameron@mozilla.com>2014-09-19 11:15:49 +1200
commit31a7e38759cc50b5135e73232dc9fa98e5154710 (patch)
treede88798e8cd58d71183206f7084a647994d01212 /src/libcore
parentaf3889f6979647b9bd2dc5f5132d80e3e5b405a5 (diff)
Implement slicing syntax.
`expr[]`, `expr[expr..]`, `expr[..expr]`,`expr[expr..expr]`

Uses the Slice and SliceMut traits.

Allows ... as well as .. in range patterns.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/ops.rs105
-rw-r--r--src/libcore/slice.rs58
2 files changed, 160 insertions, 3 deletions
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 94febf03635..718d3119995 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
  * ```
  */
 #[lang="index"]
-pub trait Index<Index,Result> {
+pub trait Index<Index, Result> {
     /// The method for the indexing (`Foo[Bar]`) operation
     fn index<'a>(&'a self, index: &Index) -> &'a Result;
 }
@@ -651,7 +651,7 @@ pub trait Index<Index,Result> {
  * # Example
  *
  * A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
- * calling `index`, and therefore, `main` prints `Indexing!`.
+ * calling `index_mut`, and therefore, `main` prints `Indexing!`.
  *
  * ```
  * struct Foo;
@@ -669,13 +669,112 @@ pub trait Index<Index,Result> {
  * ```
  */
 #[lang="index_mut"]
-pub trait IndexMut<Index,Result> {
+pub trait IndexMut<Index, Result> {
     /// The method for the indexing (`Foo[Bar]`) operation
     fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
 }
 
 /**
  *
+ * The `Slice` trait is used to specify the functionality of slicing operations
+ * like `arr[from..to]` when used in an immutable context.
+ *
+ * # Example
+ *
+ * A trivial implementation of `Slice`. When `Foo[..Foo]` happens, it ends up
+ * calling `slice_to`, and therefore, `main` prints `Slicing!`.
+ *
+ * ```
+ * struct Foo;
+ *
+ * impl ::core::ops::Slice<Foo, Foo> for Foo {
+ *     fn as_slice_<'a>(&'a self) -> &'a Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ *     fn slice_from_<'a>(&'a self, from: &Foo) -> &'a Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ *     fn slice_to_<'a>(&'a self, to: &Foo) -> &'a Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ *     fn slice_<'a>(&'a self, from: &Foo, to: &Foo) -> &'a Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ * }
+ *
+ * fn main() {
+ *     Foo[..Foo];
+ * }
+ * ```
+ */
+// FIXME(#17273) remove the postscript _s
+#[lang="slice"]
+pub trait Slice<Idx, Sized? Result> for Sized? {
+    /// The method for the slicing operation foo[]
+    fn as_slice_<'a>(&'a self) -> &'a Result;
+    /// The method for the slicing operation foo[from..]
+    fn slice_from_<'a>(&'a self, from: &Idx) -> &'a Result;
+    /// The method for the slicing operation foo[..to]
+    fn slice_to_<'a>(&'a self, to: &Idx) -> &'a Result;
+    /// The method for the slicing operation foo[from..to]
+    fn slice_<'a>(&'a self, from: &Idx, to: &Idx) -> &'a Result;
+}
+
+/**
+ *
+ * The `SliceMut` trait is used to specify the functionality of slicing
+ * operations like `arr[from..to]`, when used in a mutable context.
+ *
+ * # Example
+ *
+ * A trivial implementation of `SliceMut`. When `Foo[Foo..]` happens, it ends up
+ * calling `slice_from_mut`, and therefore, `main` prints `Slicing!`.
+ *
+ * ```
+ * struct Foo;
+ *
+ * impl ::core::ops::SliceMut<Foo, Foo> for Foo {
+ *     fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ *     fn slice_from_mut_<'a>(&'a mut self, from: &Foo) -> &'a mut Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ *     fn slice_to_mut_<'a>(&'a mut self, to: &Foo) -> &'a mut Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ *     fn slice_mut_<'a>(&'a mut self, from: &Foo, to: &Foo) -> &'a mut Foo {
+ *         println!("Slicing!");
+ *         self
+ *     }
+ * }
+ *
+ * fn main() {
+ *     Foo[mut Foo..];
+ * }
+ * ```
+ */
+// FIXME(#17273) remove the postscript _s
+#[lang="slice_mut"]
+pub trait SliceMut<Idx, Sized? Result> for Sized? {
+    /// The method for the slicing operation foo[]
+    fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result;
+    /// The method for the slicing operation foo[from..]
+    fn slice_from_mut_<'a>(&'a mut self, from: &Idx) -> &'a mut Result;
+    /// The method for the slicing operation foo[..to]
+    fn slice_to_mut_<'a>(&'a mut self, to: &Idx) -> &'a mut Result;
+    /// The method for the slicing operation foo[from..to]
+    fn slice_mut_<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
+}
+/**
+ *
  * The `Deref` trait is used to specify the functionality of dereferencing
  * operations like `*v`.
  *
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 65ad7bb1753..5368cb44502 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -42,6 +42,7 @@ use cmp;
 use default::Default;
 use iter::*;
 use num::{CheckedAdd, Saturating, div_rem};
+use ops;
 use option::{None, Option, Some};
 use ptr;
 use ptr::RawPtr;
@@ -475,6 +476,63 @@ impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
     }
 }
 
+impl<T> ops::Slice<uint, [T]> for [T] {
+    #[inline]
+    fn as_slice_<'a>(&'a self) -> &'a [T] {
+        self
+    }
+
+    #[inline]
+    fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
+        self.slice_(start, &self.len())
+    }
+
+    #[inline]
+    fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
+        self.slice_(&0, end)
+    }
+    #[inline]
+    fn slice_<'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_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
+        let len = &self.len();
+        self.slice_mut_(start, len)
+    }
+
+    #[inline]
+    fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
+        self.slice_mut_(&0, end)
+    }
+    #[inline]
+    fn slice_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 vectors such that their elements are
 /// mutable.
 #[experimental = "may merge with other traits; may lose region param; needs review"]