Skip to content

Commit 21ea66f

Browse files
committed
Add structs for ranges to core::ops.
1 parent 6585294 commit 21ea66f

File tree

3 files changed

+141
-1
lines changed

3 files changed

+141
-1
lines changed

src/libcore/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
#![allow(unknown_features, raw_pointer_deriving)]
6060
#![feature(globs, intrinsics, lang_items, macro_rules, phase)]
6161
#![feature(simd, unsafe_destructor, slicing_syntax)]
62-
#![feature(default_type_params, unboxed_closures)]
62+
#![feature(default_type_params, unboxed_closures, associated_types)]
6363
#![deny(missing_docs)]
6464

6565
mod macros;

src/libcore/ops.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@
5151
//! See the documentation for each trait for a minimum implementation that prints
5252
//! something to the screen.
5353
54+
use clone::Clone;
55+
use cmp::Ord;
56+
use iter::{Iterator,DoubleEndedIterator};
5457
use kinds::Sized;
58+
use kinds::Copy;
59+
use option::Option::{mod, Some, None};
5560

5661
/// The `Drop` trait is used to run some code when a value goes out of scope. This
5762
/// is sometimes called a 'destructor'.
@@ -833,6 +838,114 @@ pub trait SliceMut<Sized? Idx, Sized? Result> for Sized? {
833838
fn slice_or_fail_mut<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
834839
}
835840

841+
842+
843+
/// REVIEW could be in a better module
844+
/// The `Countable` trait identifies objects which are countable, i.e., are
845+
/// analogous to the natural numbers. A countable object can be incremented and
846+
/// and decremented and ordered. The `difference` function provides a way to
847+
/// compare two Countable objects (it could be provided using increment and Ord,
848+
/// but the implementation would be so inefficient as to be useless).
849+
#[unstable = "Trait is unstable."]
850+
pub trait Countable: Ord {
851+
// FIXME(#19391) needs a snapshot
852+
//type T;
853+
854+
/// Change self to the next object.
855+
fn increment(&mut self);
856+
/// Change self to the previous object.
857+
fn decrement(&mut self);
858+
/// The difference between two countable objects.
859+
/// Temporarily a uint, should be an associated type, but
860+
// FIXME(#19391) needs a snapshot
861+
fn difference(a: &Self, b: &Self) -> uint;
862+
//fn difference(a: &Self, b: &Self) -> <Self as Countable>::T;
863+
}
864+
865+
macro_rules! countable_impl(
866+
($($t:ty)*) => ($(
867+
#[unstable = "Trait is unstable."]
868+
impl Countable for $t {
869+
// FIXME(#19391) needs a snapshot
870+
//type T = uint;
871+
872+
#[inline]
873+
fn increment(&mut self) { *self += 1; }
874+
#[inline]
875+
fn decrement(&mut self) { *self -= 1; }
876+
#[inline]
877+
fn difference(a: &$t, b: &$t) -> uint { (*a - *b) as uint }
878+
}
879+
)*)
880+
)
881+
882+
countable_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
883+
884+
/// An unbounded range.
885+
pub struct FullRange;
886+
887+
/// A range which i bounded at both ends.
888+
pub struct Range<Idx> {
889+
/// The lower bound of the range (inclusive).
890+
pub start: Idx,
891+
/// The upper bound of the range (exclusive).
892+
pub end: Idx,
893+
}
894+
895+
// FIXME(#19391) needs a snapshot
896+
//impl<Idx: Clone + Countable<T=uint>> Iterator<Idx> for Range<Idx> {
897+
impl<Idx: Clone + Countable> Iterator<Idx> for Range<Idx> {
898+
#[inline]
899+
fn next(&mut self) -> Option<Idx> {
900+
if self.start < self.end {
901+
let result = self.start.clone();
902+
self.start.increment();
903+
return Some(result);
904+
}
905+
906+
return None;
907+
}
908+
909+
#[inline]
910+
fn size_hint(&self) -> (uint, Option<uint>) {
911+
let hint = Countable::difference(&self.end, &self.start);
912+
(hint, Some(hint))
913+
}
914+
}
915+
916+
impl<Idx: Clone + Countable> DoubleEndedIterator<Idx> for Range<Idx> {
917+
#[inline]
918+
fn next_back(&mut self) -> Option<Idx> {
919+
if self.start < self.end {
920+
self.end.decrement();
921+
return Some(self.end.clone());
922+
}
923+
924+
return None;
925+
}
926+
}
927+
928+
/// A range which is only bounded below.
929+
pub struct RangeFrom<Idx> {
930+
/// The lower bound of the range (inclusive).
931+
pub start: Idx,
932+
}
933+
934+
impl<Idx: Clone + Countable> Iterator<Idx> for RangeFrom<Idx> {
935+
#[inline]
936+
fn next(&mut self) -> Option<Idx> {
937+
// Deliberately overflow so we loop forever.
938+
let result = self.start.clone();
939+
self.start.increment();
940+
return Some(result);
941+
}
942+
}
943+
944+
impl<Idx: Copy> Copy for Range<Idx> {}
945+
impl<Idx: Copy> Copy for RangeFrom<Idx> {}
946+
impl Copy for FullRange {}
947+
948+
836949
/// The `Deref` trait is used to specify the functionality of dereferencing
837950
/// operations like `*v`.
838951
///

src/libcoretest/ops.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use test::Bencher;
12+
use core::ops::{Range, FullRange, RangeFrom};
1213

1314
// Overhead of dtors
1415

@@ -27,3 +28,29 @@ fn alloc_obj_with_dtor(b: &mut Bencher) {
2728
HasDtor { _x : 10 };
2829
})
2930
}
31+
32+
// Test the Range structs without the syntactic sugar.
33+
34+
#[test]
35+
fn test_range() {
36+
let r = Range { start: 2u, end: 10 };
37+
for (i, ri) in r.enumerate() {
38+
assert!(ri == i + 2);
39+
assert!(ri >= 2u && ri < 10u);
40+
}
41+
}
42+
43+
#[test]
44+
fn test_range_from() {
45+
let r = RangeFrom { start: 2u };
46+
for (i, ri) in r.take(10).enumerate() {
47+
assert!(ri == i + 2);
48+
assert!(ri >= 2u && ri < 12u);
49+
}
50+
}
51+
52+
#[test]
53+
fn test_full_range() {
54+
// Not much to test.
55+
let _ = FullRange;
56+
}

0 commit comments

Comments
 (0)