Skip to content

Commit edc4927

Browse files
committed
Support empty ranges
1 parent f54d40a commit edc4927

3 files changed

Lines changed: 99 additions & 89 deletions

File tree

tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,8 @@ macro_rules! test_range(
368368
(Some(Range::new(Some(RangeBound::new($low, Exclusive)),
369369
Some(RangeBound::new($high, Exclusive)))),
370370
"'(" + $low_str + "," + $high_str + ")'"),
371-
(None, ~"NULL")];
371+
(Some(Range::empty()), ~"'empty'"),
372+
(None, ~"NULL")];
372373
let test_refs: ~[(Option<Range<$t>>, &str)] = tests.iter()
373374
.map(|&(ref val, ref s)| { (val.clone(), s.as_slice()) })
374375
.collect();

types/mod.rs

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ static RANGE_UPPER_UNBOUNDED: i8 = 0b0001_0000;
4848
static RANGE_LOWER_UNBOUNDED: i8 = 0b0000_1000;
4949
static RANGE_UPPER_INCLUSIVE: i8 = 0b0000_0100;
5050
static RANGE_LOWER_INCLUSIVE: i8 = 0b0000_0010;
51+
static RANGE_EMPTY: i8 = 0b0000_0001;
5152

5253
/// A Postgres type
5354
#[deriving(Eq)]
@@ -281,30 +282,36 @@ macro_rules! from_range_impl(
281282
let mut rdr = BufReader::new(buf.as_slice());
282283
let t = rdr.read_i8();
283284

284-
let lower = match t & RANGE_LOWER_UNBOUNDED {
285-
0 => {
286-
let type_ = match t & RANGE_LOWER_INCLUSIVE {
287-
0 => Exclusive,
288-
_ => Inclusive
289-
};
290-
rdr.read_be_i32();
291-
Some(RangeBound::new(RawFromSql::raw_from_sql(&mut rdr), type_))
292-
}
293-
_ => None
294-
};
295-
let upper = match t & RANGE_UPPER_UNBOUNDED {
296-
0 => {
297-
let type_ = match t & RANGE_UPPER_INCLUSIVE {
298-
0 => Exclusive,
299-
_ => Inclusive
300-
};
301-
rdr.read_be_i32();
302-
Some(RangeBound::new(RawFromSql::raw_from_sql(&mut rdr), type_))
303-
}
304-
_ => None
305-
};
285+
if t & RANGE_EMPTY != 0 {
286+
Range::empty()
287+
} else {
288+
let lower = match t & RANGE_LOWER_UNBOUNDED {
289+
0 => {
290+
let type_ = match t & RANGE_LOWER_INCLUSIVE {
291+
0 => Exclusive,
292+
_ => Inclusive
293+
};
294+
rdr.read_be_i32();
295+
Some(RangeBound::new(RawFromSql::raw_from_sql(&mut rdr),
296+
type_))
297+
}
298+
_ => None
299+
};
300+
let upper = match t & RANGE_UPPER_UNBOUNDED {
301+
0 => {
302+
let type_ = match t & RANGE_UPPER_INCLUSIVE {
303+
0 => Exclusive,
304+
_ => Inclusive
305+
};
306+
rdr.read_be_i32();
307+
Some(RangeBound::new(RawFromSql::raw_from_sql(&mut rdr),
308+
type_))
309+
}
310+
_ => None
311+
};
306312

307-
Range::new(lower, upper)
313+
Range::new(lower, upper)
314+
}
308315
})
309316
)
310317
)
@@ -495,17 +502,21 @@ macro_rules! to_range_impl(
495502
let mut buf = MemWriter::new();
496503

497504
let mut tag = 0;
498-
match self.lower() {
499-
&None => tag |= RANGE_LOWER_UNBOUNDED,
500-
&Some(RangeBound { type_: Inclusive, _ }) =>
501-
tag |= RANGE_LOWER_INCLUSIVE,
502-
_ => {}
503-
}
504-
match self.upper() {
505-
&None => tag |= RANGE_UPPER_UNBOUNDED,
506-
&Some(RangeBound { type_: Inclusive, _ }) =>
507-
tag |= RANGE_UPPER_INCLUSIVE,
508-
_ => {}
505+
if self.is_empty() {
506+
tag |= RANGE_EMPTY;
507+
} else {
508+
match self.lower() {
509+
&None => tag |= RANGE_LOWER_UNBOUNDED,
510+
&Some(RangeBound { type_: Inclusive, _ }) =>
511+
tag |= RANGE_LOWER_INCLUSIVE,
512+
_ => {}
513+
}
514+
match self.upper() {
515+
&None => tag |= RANGE_UPPER_UNBOUNDED,
516+
&Some(RangeBound { type_: Inclusive, _ }) =>
517+
tag |= RANGE_UPPER_INCLUSIVE,
518+
_ => {}
519+
}
509520
}
510521

511522
buf.write_i8(tag);

types/range.rs

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -127,22 +127,12 @@ impl<S: BoundSided, T: Ord> RangeBound<S, T> {
127127
}
128128
}
129129

130-
/// The relation of a value to a range
131-
#[deriving(Eq)]
132-
pub enum RangeComparison {
133-
/// The value lies above the range
134-
Above,
135-
/// The value lies within the range
136-
Within,
137-
/// The value lies below the range
138-
Below
139-
}
140-
141130
/// Represents a range of values.
142131
#[deriving(Eq,Clone)]
143-
pub struct Range<T> {
144-
priv lower: Option<RangeBound<LowerBound, T>>,
145-
priv upper: Option<RangeBound<UpperBound, T>>,
132+
pub enum Range<T> {
133+
priv Empty,
134+
priv Normal(Option<RangeBound<LowerBound, T>>,
135+
Option<RangeBound<UpperBound, T>>)
146136
}
147137

148138
impl<T: Ord+Normalizable> Range<T> {
@@ -160,39 +150,47 @@ impl<T: Ord+Normalizable> Range<T> {
160150
_ => {}
161151
}
162152

163-
Range { lower: lower, upper: upper }
153+
Normal(lower, upper)
154+
}
155+
156+
/// Creates a new empty range.
157+
pub fn empty() -> Range<T> {
158+
Empty
159+
}
160+
161+
/// Determines if this range is the empty range.
162+
pub fn is_empty(&self) -> bool {
163+
match *self {
164+
Empty => true,
165+
Normal(*) => false
166+
}
164167
}
165168

166169
/// Returns the lower bound if it exists.
167170
pub fn lower<'a>(&'a self) -> &'a Option<RangeBound<LowerBound, T>> {
168-
&self.lower
171+
match *self {
172+
Empty => &None,
173+
Normal(ref lower, _) => lower
174+
}
169175
}
170176

171177
/// Returns the upper bound if it exists.
172178
pub fn upper<'a>(&'a self) -> &'a Option<RangeBound<UpperBound, T>> {
173-
&self.upper
174-
}
175-
176-
/// Compares a value to this range.
177-
pub fn cmp(&self, value: &T) -> RangeComparison {
178-
let lower = do self.lower.as_ref().map_default(true) |b| {
179-
b.in_bounds(value)
180-
};
181-
let upper = do self.upper.as_ref().map_default(true) |b| {
182-
b.in_bounds(value)
183-
};
184-
185-
match (lower, upper) {
186-
(true, false) => Above,
187-
(true, true) => Within,
188-
(false, true) => Below,
189-
_ => unreachable!()
179+
match *self {
180+
Empty => &None,
181+
Normal(_, ref upper) => upper
190182
}
191183
}
192184

193185
/// Determines if a value lies within this range.
194186
pub fn contains(&self, value: &T) -> bool {
195-
self.cmp(value) == Within
187+
match *self {
188+
Empty => false,
189+
Normal(ref lower, ref upper) => {
190+
lower.as_ref().map_default(true, |b| { b.in_bounds(value) }) &&
191+
upper.as_ref().map_default(true, |b| { b.in_bounds(value) })
192+
}
193+
}
196194
}
197195
}
198196

@@ -263,37 +261,37 @@ mod test {
263261
}
264262

265263
#[test]
266-
fn test_range_cmp() {
264+
fn test_range_contains() {
267265
let r = Range::new(Some(RangeBound::new(1i32, Inclusive)),
268266
Some(RangeBound::new(3i32, Inclusive)));
269-
assert_eq!(Above, r.cmp(&4));
270-
assert_eq!(Within, r.cmp(&3));
271-
assert_eq!(Within, r.cmp(&2));
272-
assert_eq!(Within, r.cmp(&1));
273-
assert_eq!(Below, r.cmp(&0));
267+
assert!(!r.contains(&4));
268+
assert!(r.contains(&3));
269+
assert!(r.contains(&2));
270+
assert!(r.contains(&1));
271+
assert!(!r.contains(&0));
274272

275273
let r = Range::new(Some(RangeBound::new(1i32, Exclusive)),
276274
Some(RangeBound::new(3i32, Exclusive)));
277-
assert_eq!(Above, r.cmp(&4));
278-
assert_eq!(Above, r.cmp(&3));
279-
assert_eq!(Within, r.cmp(&2));
280-
assert_eq!(Below, r.cmp(&1));
281-
assert_eq!(Below, r.cmp(&0));
275+
assert!(!r.contains(&4));
276+
assert!(!r.contains(&3));
277+
assert!(r.contains(&2));
278+
assert!(!r.contains(&1));
279+
assert!(!r.contains(&0));
282280

283281
let r = Range::new(None, Some(RangeBound::new(3i32, Inclusive)));
284-
assert_eq!(Above, r.cmp(&4));
285-
assert_eq!(Within, r.cmp(&2));
286-
assert_eq!(Within, r.cmp(&Bounded::min_value()));
282+
assert!(!r.contains(&4));
283+
assert!(r.contains(&2));
284+
assert!(r.contains(&Bounded::min_value()));
287285

288286
let r = Range::new(Some(RangeBound::new(1i32, Inclusive)), None);
289-
assert_eq!(Within, r.cmp(&Bounded::max_value()));
290-
assert_eq!(Within, r.cmp(&4));
291-
assert_eq!(Below, r.cmp(&0));
287+
assert!(r.contains(&Bounded::max_value()));
288+
assert!(r.contains(&4));
289+
assert!(!r.contains(&0));
292290

293291
let r = Range::new(None, None);
294-
assert_eq!(Within, r.cmp(&Bounded::max_value()));
295-
assert_eq!(Within, r.cmp(&0i32));
296-
assert_eq!(Within, r.cmp(&Bounded::min_value()));
292+
assert!(r.contains(&Bounded::max_value()));
293+
assert!(r.contains(&0i32));
294+
assert!(r.contains(&Bounded::min_value()));
297295
}
298296

299297
#[test]

0 commit comments

Comments
 (0)