Skip to content

Commit fb6aeea

Browse files
committed
More Range work
1 parent edc4927 commit fb6aeea

1 file changed

Lines changed: 73 additions & 2 deletions

File tree

types/range.rs

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
extern mod extra;
44

5+
use std::cmp;
56
use extra::time::Timespec;
67

78
/// A trait that normalizes a range bound for a type
@@ -145,8 +146,15 @@ impl<T: Ord+Normalizable> Range<T> {
145146
let upper = upper.map(|bound| { Normalizable::normalize(bound) });
146147

147148
match (&lower, &upper) {
148-
(&Some(ref lower), &Some(ref upper)) =>
149-
assert!(lower.value <= upper.value),
149+
(&Some(ref lower), &Some(ref upper)) => {
150+
let empty = match (lower.type_, upper.type_) {
151+
(Inclusive, Inclusive) => lower.value > upper.value,
152+
_ => lower.value >= upper.value
153+
};
154+
if empty {
155+
return Empty;
156+
}
157+
}
150158
_ => {}
151159
}
152160

@@ -194,6 +202,31 @@ impl<T: Ord+Normalizable> Range<T> {
194202
}
195203
}
196204

205+
impl<T: Ord+Normalizable+Clone> Range<T> {
206+
/// Returns the intersection of this range with another
207+
pub fn intersect(&self, other: &Range<T>) -> Range<T> {
208+
if self.is_empty() || other.is_empty() {
209+
return Range::empty();
210+
}
211+
212+
let lower = match (self.lower(), other.lower()) {
213+
(&Some(ref a), &Some(ref b)) => Some(cmp::max(a, b).clone()),
214+
(&Some(ref a), &None) => Some(a.clone()),
215+
(&None, &Some(ref b)) => Some(b.clone()),
216+
(&None, &None) => None
217+
};
218+
219+
let upper = match (self.upper(), other.upper()) {
220+
(&Some(ref a), &Some(ref b)) => Some(cmp::min(a, b).clone()),
221+
(&Some(ref a), &None) => Some(a.clone()),
222+
(&None, &Some(ref b)) => Some(b.clone()),
223+
(&None, &None) => None
224+
};
225+
226+
Range::new(lower, upper)
227+
}
228+
}
229+
197230
#[cfg(test)]
198231
mod test {
199232
use super::*;
@@ -320,4 +353,42 @@ mod test {
320353
Some(RangeBound::new(16i32, Exclusive)));
321354
assert_eq!(r1, r2);
322355
}
356+
357+
#[test]
358+
fn test_range_empty() {
359+
assert!(Range::new(Some(RangeBound::new(9i32, Exclusive)),
360+
Some(RangeBound::new(10i32, Exclusive))).is_empty());
361+
assert!(Range::new(Some(RangeBound::new(10i32, Inclusive)),
362+
Some(RangeBound::new(10i32, Exclusive))).is_empty());
363+
assert!(Range::new(Some(RangeBound::new(10i32, Exclusive)),
364+
Some(RangeBound::new(10i32, Inclusive))).is_empty());
365+
assert!(Range::new(Some(RangeBound::new(10i32, Inclusive)),
366+
Some(RangeBound::new(9i32, Inclusive))).is_empty());
367+
}
368+
369+
#[test]
370+
fn test_intersection() {
371+
let r1 = Range::new(Some(RangeBound::new(10i32, Inclusive)),
372+
Some(RangeBound::new(15i32, Exclusive)));
373+
let r2 = Range::new(Some(RangeBound::new(20i32, Exclusive)),
374+
Some(RangeBound::new(25i32, Inclusive)));
375+
assert!(r1.intersect(&r2).is_empty());
376+
assert!(r2.intersect(&r1).is_empty());
377+
assert_eq!(r1, r1.intersect(&Range::new(None, None)));
378+
assert_eq!(r1, Range::new(None, None).intersect(&r1));
379+
380+
let r2 = Range::new(Some(RangeBound::new(10i32, Exclusive)), None);
381+
let exp = Range::new(r2.lower().clone(), r1.upper().clone());
382+
assert_eq!(exp, r1.intersect(&r2));
383+
assert_eq!(exp, r2.intersect(&r1));
384+
385+
let r2 = Range::new(None, Some(RangeBound::new(15i32, Inclusive)));
386+
assert_eq!(r1, r1.intersect(&r2));
387+
assert_eq!(r1, r2.intersect(&r1));
388+
389+
let r2 = Range::new(Some(RangeBound::new(11i32, Inclusive)),
390+
Some(RangeBound::new(14i32, Exclusive)));
391+
assert_eq!(r2, r1.intersect(&r2));
392+
assert_eq!(r2, r2.intersect(&r1));
393+
}
323394
}

0 commit comments

Comments
 (0)