about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2014-12-13 16:58:48 +1300
committerNick Cameron <ncameron@mozilla.com>2014-12-24 09:12:45 +1300
commit21ea66f47ad059279628736b31a3a8bddd2710d3 (patch)
tree69fc30d89fadcfc69bea00673820d50209384408
parent658529467d9d69ac9e09cacf98a6d61d781c2c76 (diff)
downloadrust-21ea66f47ad059279628736b31a3a8bddd2710d3.tar.gz
rust-21ea66f47ad059279628736b31a3a8bddd2710d3.zip
Add structs for ranges to core::ops.
-rw-r--r--src/libcore/lib.rs2
-rw-r--r--src/libcore/ops.rs113
-rw-r--r--src/libcoretest/ops.rs27
3 files changed, 141 insertions, 1 deletions
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 9b6622a7127..9de723f38ee 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -59,7 +59,7 @@
 #![allow(unknown_features, raw_pointer_deriving)]
 #![feature(globs, intrinsics, lang_items, macro_rules, phase)]
 #![feature(simd, unsafe_destructor, slicing_syntax)]
-#![feature(default_type_params, unboxed_closures)]
+#![feature(default_type_params, unboxed_closures, associated_types)]
 #![deny(missing_docs)]
 
 mod macros;
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index e752fd11ee5..63451d06cb5 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -51,7 +51,12 @@
 //! See the documentation for each trait for a minimum implementation that prints
 //! something to the screen.
 
+use clone::Clone;
+use cmp::Ord;
+use iter::{Iterator,DoubleEndedIterator};
 use kinds::Sized;
+use kinds::Copy;
+use option::Option::{mod, Some, None};
 
 /// The `Drop` trait is used to run some code when a value goes out of scope. This
 /// is sometimes called a 'destructor'.
@@ -833,6 +838,114 @@ pub trait SliceMut<Sized? Idx, Sized? Result> for Sized? {
     fn slice_or_fail_mut<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
 }
 
+
+
+/// REVIEW could be in a better module
+/// The `Countable` trait identifies objects which are countable, i.e., are
+/// analogous to the natural numbers. A countable object can be incremented and
+/// and decremented and ordered. The `difference` function provides a way to
+/// compare two Countable objects (it could be provided using increment and Ord,
+/// but the implementation would be so inefficient as to be useless).
+#[unstable = "Trait is unstable."]
+pub trait Countable: Ord {
+    // FIXME(#19391) needs a snapshot
+    //type T;
+
+    /// Change self to the next object.
+    fn increment(&mut self);
+    /// Change self to the previous object.
+    fn decrement(&mut self);
+    /// The difference between two countable objects.
+    /// Temporarily a uint, should be an associated type, but
+    // FIXME(#19391) needs a snapshot
+    fn difference(a: &Self, b: &Self) -> uint;
+    //fn difference(a: &Self, b: &Self) -> <Self as Countable>::T;
+}
+
+macro_rules! countable_impl(
+    ($($t:ty)*) => ($(
+        #[unstable = "Trait is unstable."]
+        impl Countable for $t {
+            // FIXME(#19391) needs a snapshot
+            //type T = uint;
+
+            #[inline]
+            fn increment(&mut self) { *self += 1; }
+            #[inline]
+            fn decrement(&mut self) { *self -= 1; }
+            #[inline]
+            fn difference(a: &$t, b: &$t) -> uint { (*a - *b) as uint }
+        }
+    )*)
+)
+
+countable_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
+
+/// An unbounded range.
+pub struct FullRange;
+
+/// A range which i bounded at both ends.
+pub struct Range<Idx> {
+    /// The lower bound of the range (inclusive).
+    pub start: Idx,
+    /// The upper bound of the range (exclusive).
+    pub end: Idx,
+}
+
+// FIXME(#19391) needs a snapshot
+//impl<Idx: Clone + Countable<T=uint>> Iterator<Idx> for Range<Idx> {
+impl<Idx: Clone + Countable> Iterator<Idx> for Range<Idx> {
+    #[inline]
+    fn next(&mut self) -> Option<Idx> {
+        if self.start < self.end {
+            let result = self.start.clone();
+            self.start.increment();
+            return Some(result);
+        }
+
+        return None;
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (uint, Option<uint>) {
+        let hint = Countable::difference(&self.end, &self.start);
+        (hint, Some(hint))
+    }
+}
+
+impl<Idx: Clone + Countable> DoubleEndedIterator<Idx> for Range<Idx> {
+    #[inline]
+    fn next_back(&mut self) -> Option<Idx> {
+        if self.start < self.end {
+            self.end.decrement();
+            return Some(self.end.clone());
+        }
+
+        return None;
+    }
+}
+
+/// A range which is only bounded below.
+pub struct RangeFrom<Idx> {
+    /// The lower bound of the range (inclusive).
+    pub start: Idx,
+}
+
+impl<Idx: Clone + Countable> Iterator<Idx> for RangeFrom<Idx> {
+    #[inline]
+    fn next(&mut self) -> Option<Idx> {
+        // Deliberately overflow so we loop forever.
+        let result = self.start.clone();
+        self.start.increment();
+        return Some(result);
+    }
+}
+
+impl<Idx: Copy> Copy for Range<Idx> {}
+impl<Idx: Copy> Copy for RangeFrom<Idx> {}
+impl Copy for FullRange {}
+
+
 /// The `Deref` trait is used to specify the functionality of dereferencing
 /// operations like `*v`.
 ///
diff --git a/src/libcoretest/ops.rs b/src/libcoretest/ops.rs
index 447fd1c699d..c4acef32ee8 100644
--- a/src/libcoretest/ops.rs
+++ b/src/libcoretest/ops.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use test::Bencher;
+use core::ops::{Range, FullRange, RangeFrom};
 
 // Overhead of dtors
 
@@ -27,3 +28,29 @@ fn alloc_obj_with_dtor(b: &mut Bencher) {
         HasDtor { _x : 10 };
     })
 }
+
+// Test the Range structs without the syntactic sugar.
+
+#[test]
+fn test_range() {
+    let r = Range { start: 2u, end: 10 };
+    for (i, ri) in r.enumerate() {
+        assert!(ri == i + 2);
+        assert!(ri >= 2u && ri < 10u);
+    }
+}
+
+#[test]
+fn test_range_from() {
+    let r = RangeFrom { start: 2u };
+    for (i, ri) in r.take(10).enumerate() {
+        assert!(ri == i + 2);
+        assert!(ri >= 2u && ri < 12u);
+    }
+}
+
+#[test]
+fn test_full_range() {
+    // Not much to test.
+    let _ = FullRange;
+}