about summary refs log tree commit diff
path: root/src/libcore/ops.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore/ops.rs')
-rw-r--r--src/libcore/ops.rs113
1 files changed, 113 insertions, 0 deletions
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`.
 ///