Skip to content

Commit e4c2e20

Browse files
committed
Add Range::contains_range
1 parent fb6aeea commit e4c2e20

1 file changed

Lines changed: 51 additions & 13 deletions

File tree

types/range.rs

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ impl Normalizable for Timespec {
5050
}
5151
}
5252

53+
#[deriving(Eq)]
5354
enum BoundSide {
5455
Upper,
5556
Lower
@@ -128,6 +129,19 @@ impl<S: BoundSided, T: Ord> RangeBound<S, T> {
128129
}
129130
}
130131

132+
struct OptBound<'self, S, T>(&'self Option<RangeBound<S, T>>);
133+
134+
impl<'self, S: BoundSided, T: Ord> Ord for OptBound<'self, S, T> {
135+
fn lt(&self, other: &OptBound<'self, S, T>) -> bool {
136+
match (**self, **other) {
137+
(&None, &None) => false,
138+
(&None, _) => BoundSided::side(None::<S>) == Lower,
139+
(_, &None) => BoundSided::side(None::<S>) == Upper,
140+
(&Some(ref a), &Some(ref b)) => a < b
141+
}
142+
}
143+
}
144+
131145
/// Represents a range of values.
132146
#[deriving(Eq,Clone)]
133147
pub enum Range<T> {
@@ -200,6 +214,20 @@ impl<T: Ord+Normalizable> Range<T> {
200214
}
201215
}
202216
}
217+
218+
/// Determines if a range lies completely within this range.
219+
pub fn contains_range(&self, other: &Range<T>) -> bool {
220+
if other.is_empty() {
221+
return true;
222+
}
223+
224+
if self.is_empty() {
225+
return false;
226+
}
227+
228+
OptBound(self.lower()) <= OptBound(other.lower()) &&
229+
OptBound(self.upper()) >= OptBound(other.upper())
230+
}
203231
}
204232

205233
impl<T: Ord+Normalizable+Clone> Range<T> {
@@ -209,19 +237,10 @@ impl<T: Ord+Normalizable+Clone> Range<T> {
209237
return Range::empty();
210238
}
211239

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-
};
240+
let lower = cmp::max(OptBound(self.lower()), OptBound(other.lower()))
241+
.clone();
242+
let upper = cmp::min(OptBound(self.upper()), OptBound(other.upper()))
243+
.clone();
225244

226245
Range::new(lower, upper)
227246
}
@@ -391,4 +410,23 @@ mod test {
391410
assert_eq!(r2, r1.intersect(&r2));
392411
assert_eq!(r2, r2.intersect(&r1));
393412
}
413+
414+
#[test]
415+
fn test_contains_range() {
416+
assert!(Range::<i32>::empty().contains_range(&Range::empty()));
417+
418+
let r1 = Range::new(Some(RangeBound::new(10i32, Inclusive)),
419+
Some(RangeBound::new(15i32, Exclusive)));
420+
assert!(r1.contains_range(&r1));
421+
422+
let r2 = Range::new(Some(RangeBound::new(10i32, Exclusive)),
423+
None);
424+
assert!(!r1.contains_range(&r2));
425+
assert!(!r2.contains_range(&r1));
426+
427+
let r2 = Range::new(None,
428+
Some(RangeBound::new(15i32, Inclusive)));
429+
assert!(!r1.contains_range(&r2));
430+
assert!(r2.contains_range(&r1));
431+
}
394432
}

0 commit comments

Comments
 (0)