1#![doc(html_root_url = "https://sfackler.github.io/rust-postgres-range/doc/v0.11")]
3#![warn(clippy::all, rust_2018_idioms, missing_docs)]
4
5#[macro_use(to_sql_checked)]
6extern crate postgres_types;
7
8#[cfg(feature = "with-chrono-0_4")]
9mod chrono_04;
10
11use std::cmp::Ordering;
12use std::fmt;
13use std::i32;
14use std::i64;
15use std::marker::PhantomData;
16
17use BoundSide::{Lower, Upper};
18use BoundType::{Exclusive, Inclusive};
19use InnerRange::{Empty, Normal};
20
21#[macro_export]
56macro_rules! range {
57 (empty) => ($crate::Range::empty());
58 ('(',; ')') => ($crate::Range::new(None, None));
59 ('(', $h:expr; ')') => (
60 $crate::Range::new(None,
61 Some($crate::RangeBound::new($h,
62 $crate::BoundType::Exclusive)))
63 );
64 ('(', $h:expr; ']') => (
65 $crate::Range::new(None,
66 Some($crate::RangeBound::new($h,
67 $crate::BoundType::Inclusive)))
68 );
69 ('(' $l:expr,; ')') => (
70 $crate::Range::new(
71 Some($crate::RangeBound::new($l,
72 $crate::BoundType::Exclusive)), None)
73 );
74 ('[' $l:expr,; ')') => (
75 $crate::Range::new(
76 Some($crate::RangeBound::new($l,
77 $crate::BoundType::Inclusive)), None)
78 );
79 ('(' $l:expr, $h:expr; ')') => (
80 $crate::Range::new(
81 Some($crate::RangeBound::new($l,
82 $crate::BoundType::Exclusive)),
83 Some($crate::RangeBound::new($h,
84 $crate::BoundType::Exclusive)))
85 );
86 ('(' $l:expr, $h:expr; ']') => (
87 $crate::Range::new(
88 Some($crate::RangeBound::new($l,
89 $crate::BoundType::Exclusive)),
90 Some($crate::RangeBound::new($h,
91 $crate::BoundType::Inclusive)))
92 );
93 ('[' $l:expr, $h:expr; ')') => (
94 $crate::Range::new(
95 Some($crate::RangeBound::new($l,
96 $crate::BoundType::Inclusive)),
97 Some($crate::RangeBound::new($h,
98 $crate::BoundType::Exclusive)))
99 );
100 ('[' $l:expr, $h:expr; ']') => (
101 $crate::Range::new(
102 Some($crate::RangeBound::new($l,
103 $crate::BoundType::Inclusive)),
104 Some($crate::RangeBound::new($h,
105 $crate::BoundType::Inclusive)))
106 )
107}
108
109mod impls;
110
111pub trait Normalizable: Sized {
113 fn normalize<S>(bound: RangeBound<S, Self>) -> RangeBound<S, Self>
122 where
123 S: BoundSided;
124}
125
126macro_rules! bounded_normalizable {
127 ($t:ident) => (
128 impl Normalizable for $t {
129 fn normalize<S>(bound: RangeBound<S, $t>) -> RangeBound<S, $t> where S: BoundSided {
130 match (<S as BoundSided>::side(), bound.type_) {
131 (Upper, Inclusive) => {
132 assert!(bound.value != $t::MAX);
133 RangeBound::new(bound.value + 1, Exclusive)
134 }
135 (Lower, Exclusive) => {
136 assert!(bound.value != $t::MAX);
137 RangeBound::new(bound.value + 1, Inclusive)
138 }
139 _ => bound
140 }
141 }
142 }
143 )
144}
145
146bounded_normalizable!(i32);
147bounded_normalizable!(i64);
148
149#[derive(Debug, PartialEq, Eq, Clone, Copy)]
151pub enum BoundSide {
152 Upper,
154 Lower,
156}
157
158pub trait BoundSided {
160 fn side() -> BoundSide;
162}
163
164pub enum UpperBound {}
166
167pub enum LowerBound {}
169
170impl BoundSided for UpperBound {
171 fn side() -> BoundSide {
172 Upper
173 }
174}
175
176impl BoundSided for LowerBound {
177 fn side() -> BoundSide {
178 Lower
179 }
180}
181
182#[derive(Debug, PartialEq, Eq, Clone, Copy)]
184pub enum BoundType {
185 Inclusive,
187 Exclusive,
189}
190
191pub struct RangeBound<S: BoundSided, T> {
195 pub value: T,
197 pub type_: BoundType,
199 _m: PhantomData<S>,
200}
201
202fn _is_send_sync() {
203 fn is_send_sync<T: Send + Sync>() {}
204 is_send_sync::<RangeBound<LowerBound, i32>>();
205}
206
207impl<S, T> Copy for RangeBound<S, T>
208where
209 S: BoundSided,
210 T: Copy,
211{
212}
213
214impl<S, T> Clone for RangeBound<S, T>
215where
216 S: BoundSided,
217 T: Clone,
218{
219 fn clone(&self) -> RangeBound<S, T> {
220 RangeBound {
221 value: self.value.clone(),
222 type_: self.type_,
223 _m: PhantomData,
224 }
225 }
226}
227
228impl<S, T> fmt::Debug for RangeBound<S, T>
229where
230 S: BoundSided,
231 T: fmt::Debug,
232{
233 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
234 fmt.debug_struct("RangeBound")
235 .field("value", &self.value)
236 .field("type_", &self.type_)
237 .finish()
238 }
239}
240
241impl<S, T> fmt::Display for RangeBound<S, T>
242where
243 S: BoundSided,
244 T: fmt::Display,
245{
246 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
247 let (lower, upper) = match self.type_ {
248 Inclusive => ('[', ']'),
249 Exclusive => ('(', ')'),
250 };
251
252 match <S as BoundSided>::side() {
253 Lower => write!(fmt, "{}{}", lower, self.value),
254 Upper => write!(fmt, "{}{}", self.value, upper),
255 }
256 }
257}
258
259impl<S, T> PartialEq for RangeBound<S, T>
260where
261 S: BoundSided,
262 T: PartialEq,
263{
264 fn eq(&self, other: &RangeBound<S, T>) -> bool {
265 self.value == other.value && self.type_ == other.type_
266 }
267
268 }
272
273impl<S, T> Eq for RangeBound<S, T>
274where
275 S: BoundSided,
276 T: Eq,
277{
278}
279
280impl<S, T> PartialOrd for RangeBound<S, T>
281where
282 S: BoundSided,
283 T: PartialOrd,
284{
285 fn partial_cmp(&self, other: &RangeBound<S, T>) -> Option<Ordering> {
286 match (
287 <S as BoundSided>::side(),
288 self.type_,
289 other.type_,
290 self.value.partial_cmp(&other.value),
291 ) {
292 (Upper, Exclusive, Inclusive, Some(Ordering::Equal)) | (Lower, Inclusive, Exclusive, Some(Ordering::Equal)) => Some(Ordering::Less),
293 (Upper, Inclusive, Exclusive, Some(Ordering::Equal)) | (Lower, Exclusive, Inclusive, Some(Ordering::Equal)) => Some(Ordering::Greater),
294 (_, _, _, cmp) => cmp,
295 }
296 }
297}
298
299impl<S, T> Ord for RangeBound<S, T>
300where
301 S: BoundSided,
302 T: Ord,
303{
304 fn cmp(&self, other: &RangeBound<S, T>) -> Ordering {
305 match (
306 <S as BoundSided>::side(),
307 self.type_,
308 other.type_,
309 self.value.cmp(&other.value),
310 ) {
311 (Upper, Exclusive, Inclusive, Ordering::Equal) | (Lower, Inclusive, Exclusive, Ordering::Equal) => Ordering::Less,
312 (Upper, Inclusive, Exclusive, Ordering::Equal) | (Lower, Exclusive, Inclusive, Ordering::Equal) => Ordering::Greater,
313 (_, _, _, ord) => ord,
314 }
315 }
316}
317
318impl<S, T> RangeBound<S, T>
319where
320 S: BoundSided,
321 T: PartialOrd,
322{
323 pub fn new(value: T, type_: BoundType) -> RangeBound<S, T> {
325 RangeBound {
326 value,
327 type_,
328 _m: PhantomData,
329 }
330 }
331
332 pub fn in_bounds(&self, value: &T) -> bool {
334 match (self.type_, <S as BoundSided>::side()) {
335 (Inclusive, Upper) => value <= &self.value,
336 (Exclusive, Upper) => value < &self.value,
337 (Inclusive, Lower) => value >= &self.value,
338 (Exclusive, Lower) => value > &self.value,
339 }
340 }
341}
342
343struct OptBound<'a, S: BoundSided, T>(Option<&'a RangeBound<S, T>>);
344
345impl<'a, S, T> PartialEq for OptBound<'a, S, T>
346where
347 S: BoundSided,
348 T: PartialEq,
349{
350 fn eq(&self, &OptBound(ref other): &OptBound<'a, S, T>) -> bool {
351 let &OptBound(ref self_) = self;
352 self_ == other
353 }
354
355 }
360
361impl<'a, S, T> PartialOrd for OptBound<'a, S, T>
362where
363 S: BoundSided,
364 T: PartialOrd,
365{
366 fn partial_cmp(&self, other: &OptBound<'a, S, T>) -> Option<Ordering> {
367 match (self, other, <S as BoundSided>::side()) {
368 (&OptBound(None), &OptBound(None), _) => Some(Ordering::Equal),
369 (&OptBound(None), _, Lower) | (_, &OptBound(None), Upper) => Some(Ordering::Less),
370 (&OptBound(None), _, Upper) | (_, &OptBound(None), Lower) => Some(Ordering::Greater),
371 (&OptBound(Some(a)), &OptBound(Some(b)), _) => a.partial_cmp(b),
372 }
373 }
374}
375
376#[derive(Debug, PartialEq, Eq, Clone, Copy)]
378pub struct Range<T> {
379 inner: InnerRange<T>,
380}
381
382#[derive(Debug, PartialEq, Eq, Clone, Copy)]
383enum InnerRange<T> {
384 Empty,
385 Normal(
386 Option<RangeBound<LowerBound, T>>,
387 Option<RangeBound<UpperBound, T>>,
388 ),
389}
390
391impl<T> fmt::Display for Range<T>
392where
393 T: fmt::Display,
394{
395 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
396 match self.inner {
397 Empty => write!(fmt, "empty"),
398 Normal(ref lower, ref upper) => {
399 match *lower {
400 Some(ref bound) => write!(fmt, "{}", bound)?,
401 None => write!(fmt, "(")?,
402 }
403 write!(fmt, ",")?;
404 match *upper {
405 Some(ref bound) => write!(fmt, "{}", bound),
406 None => write!(fmt, ")"),
407 }
408 }
409 }
410 }
411}
412
413impl<T> Range<T>
414where
415 T: PartialOrd + Normalizable,
416{
417 pub fn new(lower: Option<RangeBound<LowerBound, T>>, upper: Option<RangeBound<UpperBound, T>>) -> Range<T> {
421 let lower = lower.map(Normalizable::normalize);
422 let upper = upper.map(Normalizable::normalize);
423
424 if let (&Some(ref lower), &Some(ref upper)) = (&lower, &upper) {
425 let empty = match (lower.type_, upper.type_) {
426 (Inclusive, Inclusive) => lower.value > upper.value,
427 _ => lower.value >= upper.value,
428 };
429 if empty {
430 return Range { inner: Empty };
431 }
432 }
433
434 Range {
435 inner: Normal(lower, upper),
436 }
437 }
438
439 pub fn empty() -> Range<T> {
441 Range { inner: Empty }
442 }
443
444 pub fn is_empty(&self) -> bool {
446 match self.inner {
447 Empty => true,
448 Normal(..) => false,
449 }
450 }
451
452 pub fn lower(&self) -> Option<&RangeBound<LowerBound, T>> {
454 match self.inner {
455 Normal(Some(ref lower), _) => Some(lower),
456 _ => None,
457 }
458 }
459
460 pub fn upper(&self) -> Option<&RangeBound<UpperBound, T>> {
462 match self.inner {
463 Normal(_, Some(ref upper)) => Some(upper),
464 _ => None,
465 }
466 }
467
468 pub fn contains(&self, value: &T) -> bool {
470 match self.inner {
471 Empty => false,
472 Normal(ref lower, ref upper) => {
473 lower.as_ref().map_or(true, |b| {
474 b.in_bounds(value)
475 }) && upper.as_ref().map_or(true, |b| {
476 b.in_bounds(value)
477 })
478 }
479 }
480 }
481
482 pub fn contains_range(&self, other: &Range<T>) -> bool {
484 if other.is_empty() {
485 return true;
486 }
487
488 if self.is_empty() {
489 return false;
490 }
491
492 OptBound(self.lower()) <= OptBound(other.lower()) && OptBound(self.upper()) >= OptBound(other.upper())
493 }
494}
495
496fn order<T>(a: T, b: T) -> (T, T)
497where
498 T: PartialOrd,
499{
500 if a < b {
501 (a, b)
502 } else {
503 (b, a)
504 }
505}
506
507impl<T> Range<T>
508where
509 T: PartialOrd + Normalizable + Clone,
510{
511 pub fn intersect(&self, other: &Range<T>) -> Range<T> {
513 if self.is_empty() || other.is_empty() {
514 return Range::empty();
515 }
516
517 let (_, OptBound(lower)) = order(OptBound(self.lower()), OptBound(other.lower()));
518 let (OptBound(upper), _) = order(OptBound(self.upper()), OptBound(other.upper()));
519
520 Range::new(lower.cloned(), upper.cloned())
521 }
522
523 pub fn union(&self, other: &Range<T>) -> Option<Range<T>> {
525 if self.is_empty() {
526 return Some(other.clone());
527 }
528
529 if other.is_empty() {
530 return Some(self.clone());
531 }
532
533 let (OptBound(l_lower), OptBound(u_lower)) = order(OptBound(self.lower()), OptBound(other.lower()));
534 let (OptBound(l_upper), OptBound(u_upper)) = order(OptBound(self.upper()), OptBound(other.upper()));
535
536 let discontiguous = match (u_lower, l_upper) {
537 (
538 Some(&RangeBound {
539 value: ref l,
540 type_: Exclusive,
541 ..
542 }),
543 Some(&RangeBound {
544 value: ref u,
545 type_: Exclusive,
546 ..
547 }),
548 ) => l >= u,
549 (Some(&RangeBound { value: ref l, .. }), Some(&RangeBound { value: ref u, .. })) => l > u,
550 _ => false,
551 };
552
553 if discontiguous {
554 None
555 } else {
556 Some(Range::new(
557 l_lower.cloned(),
558 u_upper.cloned(),
559 ))
560 }
561 }
562}
563
564#[cfg(test)]
565mod test {
566 use std::i32;
567
568 use super::{BoundType, LowerBound, Normalizable, Range, RangeBound, UpperBound};
569 use super::BoundType::{Exclusive, Inclusive};
570
571 #[test]
572 fn test_range_bound_lower_lt() {
573 fn check(val1: isize, inc1: BoundType, val2: isize, inc2: BoundType, expected: bool) {
574 let a: RangeBound<LowerBound, isize> = RangeBound::new(val1, inc1);
575 let b: RangeBound<LowerBound, isize> = RangeBound::new(val2, inc2);
576 assert_eq!(expected, a < b);
577 }
578
579 check(1, Inclusive, 2, Exclusive, true);
580 check(1, Exclusive, 2, Inclusive, true);
581 check(1, Inclusive, 1, Exclusive, true);
582 check(2, Inclusive, 1, Inclusive, false);
583 check(2, Exclusive, 1, Exclusive, false);
584 check(1, Exclusive, 1, Inclusive, false);
585 check(1, Exclusive, 1, Exclusive, false);
586 check(1, Inclusive, 1, Inclusive, false);
587 }
588
589 #[test]
590 fn test_range_bound_upper_lt() {
591 fn check(val1: isize, inc1: BoundType, val2: isize, inc2: BoundType, expected: bool) {
592 let a: RangeBound<UpperBound, isize> = RangeBound::new(val1, inc1);
593 let b: RangeBound<UpperBound, isize> = RangeBound::new(val2, inc2);
594 assert_eq!(expected, a < b);
595 }
596
597 check(1, Inclusive, 2, Exclusive, true);
598 check(1, Exclusive, 2, Exclusive, true);
599 check(1, Exclusive, 1, Inclusive, true);
600 check(2, Inclusive, 1, Inclusive, false);
601 check(2, Exclusive, 1, Exclusive, false);
602 check(1, Inclusive, 1, Exclusive, false);
603 check(1, Inclusive, 1, Inclusive, false);
604 check(1, Exclusive, 1, Exclusive, false);
605 }
606
607 #[test]
608 fn test_range_bound_lower_in_bounds() {
609 fn check(bound: isize, inc: BoundType, val: isize, expected: bool) {
610 let b: RangeBound<LowerBound, isize> = RangeBound::new(bound, inc);
611 assert_eq!(expected, b.in_bounds(&val));
612 }
613
614 check(1, Inclusive, 1, true);
615 check(1, Exclusive, 1, false);
616 check(1, Inclusive, 2, true);
617 check(1, Inclusive, 0, false);
618 }
619
620 #[test]
621 fn test_range_bound_upper_in_bounds() {
622 fn check(bound: isize, inc: BoundType, val: isize, expected: bool) {
623 let b: RangeBound<UpperBound, isize> = RangeBound::new(bound, inc);
624 assert_eq!(expected, b.in_bounds(&val));
625 }
626
627 check(1, Inclusive, 1, true);
628 check(1, Exclusive, 1, false);
629 check(1, Inclusive, 2, false);
630 check(1, Inclusive, 0, true);
631 }
632
633 #[test]
634 fn test_range_contains() {
635 let r = range!('[' 1i32, 3i32; ']');
636 assert!(!r.contains(&4));
637 assert!(r.contains(&3));
638 assert!(r.contains(&2));
639 assert!(r.contains(&1));
640 assert!(!r.contains(&0));
641
642 let r = range!('(' 1i32, 3i32; ')');
643 assert!(!r.contains(&4));
644 assert!(!r.contains(&3));
645 assert!(r.contains(&2));
646 assert!(!r.contains(&1));
647 assert!(!r.contains(&0));
648
649 let r = range!('(', 3i32; ']');
650 assert!(!r.contains(&4));
651 assert!(r.contains(&2));
652 assert!(r.contains(&i32::MIN));
653
654 let r = range!('[' 1i32,; ')');
655 assert!(r.contains(&i32::MAX));
656 assert!(r.contains(&4));
657 assert!(!r.contains(&0));
658
659 let r = range!('(',; ')');
660 assert!(r.contains(&i32::MAX));
661 assert!(r.contains(&0i32));
662 assert!(r.contains(&i32::MIN));
663 }
664
665 #[test]
666 fn test_normalize_lower() {
667 let r: RangeBound<LowerBound, i32> = RangeBound::new(10i32, Inclusive);
668 assert_eq!(
669 RangeBound::new(10i32, Inclusive),
670 Normalizable::normalize(r)
671 );
672
673 let r: RangeBound<LowerBound, i32> = RangeBound::new(10i32, Exclusive);
674 assert_eq!(
675 RangeBound::new(11i32, Inclusive),
676 Normalizable::normalize(r)
677 );
678 }
679
680 #[test]
681 fn test_normalize_upper() {
682 let r: RangeBound<UpperBound, i32> = RangeBound::new(10i32, Inclusive);
683 assert_eq!(
684 RangeBound::new(11i32, Exclusive),
685 Normalizable::normalize(r)
686 );
687
688 let r: RangeBound<UpperBound, i32> = RangeBound::new(10i32, Exclusive);
689 assert_eq!(
690 RangeBound::new(10i32, Exclusive),
691 Normalizable::normalize(r)
692 );
693 }
694
695 #[test]
696 fn test_range_normalizes() {
697 let r1 = range!('(' 10i32, 15i32; ']');
698 let r2 = range!('[' 11i32, 16i32; ')');
699 assert_eq!(r1, r2);
700 }
701
702 #[test]
703 fn test_range_empty() {
704 assert!((range!('(' 9i32, 10i32; ')')).is_empty());
705 assert!((range!('[' 10i32, 10i32; ')')).is_empty());
706 assert!((range!('(' 10i32, 10i32; ']')).is_empty());
707 assert!((range!('[' 10i32, 9i32; ']')).is_empty());
708 }
709
710 #[test]
711 fn test_intersection() {
712 let r1 = range!('[' 10i32, 15i32; ')');
713 let r2 = range!('(' 20i32, 25i32; ']');
714 assert!(r1.intersect(&r2).is_empty());
715 assert!(r2.intersect(&r1).is_empty());
716 assert_eq!(r1, r1.intersect(&range!('(',; ')')));
717 assert_eq!(r1, (range!('(',; ')')).intersect(&r1));
718
719 let r2 = range!('(' 10i32,; ')');
720 let exp = Range::new(r2.lower().copied(), r1.upper().copied());
721 assert_eq!(exp, r1.intersect(&r2));
722 assert_eq!(exp, r2.intersect(&r1));
723
724 let r2 = range!('(', 15i32; ']');
725 assert_eq!(r1, r1.intersect(&r2));
726 assert_eq!(r1, r2.intersect(&r1));
727
728 let r2 = range!('[' 11i32, 14i32; ')');
729 assert_eq!(r2, r1.intersect(&r2));
730 assert_eq!(r2, r2.intersect(&r1));
731 }
732
733 #[test]
734 fn test_union() {
735 let r1 = range!('[' 10i32, 15i32; ')');
736 let r2 = range!('(' 20i32, 25i32; ']');
737 assert_eq!(None, r1.union(&r2));
738 assert_eq!(None, r2.union(&r1));
739
740 let r2 = range!('(',; ')');
741 assert_eq!(Some(r2), r1.union(&r2));
742 assert_eq!(Some(r2), r2.union(&r1));
743
744 let r2 = range!('[' 13i32, 50i32; ')');
745 assert_eq!(Some(range!('[' 10i32, 50i32; ')')), r1.union(&r2));
746 assert_eq!(Some(range!('[' 10i32, 50i32; ')')), r2.union(&r1));
747
748 let r2 = range!('[' 3i32, 50i32; ')');
749 assert_eq!(Some(range!('[' 3i32, 50i32; ')')), r1.union(&r2));
750 assert_eq!(Some(range!('[' 3i32, 50i32; ')')), r2.union(&r1));
751
752 let r2 = range!('(', 11i32; ')');
753 assert_eq!(Some(range!('(', 15i32; ')')), r1.union(&r2));
754 assert_eq!(Some(range!('(', 15i32; ')')), r2.union(&r1));
755
756 let r2 = range!('(' 11i32,; ')');
757 assert_eq!(Some(range!('[' 10i32,; ')')), r1.union(&r2));
758 assert_eq!(Some(range!('[' 10i32,; ')')), r2.union(&r1));
759
760 let r2 = range!('(' 15i32, 20i32; ')');
761 assert_eq!(None, r1.union(&r2));
762 assert_eq!(None, r2.union(&r1));
763
764 let r2 = range!('[' 15i32, 20i32; ']');
765 assert_eq!(Some(range!('[' 10i32, 20i32; ']')), r1.union(&r2));
766 assert_eq!(Some(range!('[' 10i32, 20i32; ']')), r2.union(&r1));
767 }
768
769 #[test]
770 fn test_contains_range() {
771 assert!(Range::<i32>::empty().contains_range(&Range::empty()));
772
773 let r1 = range!('[' 10i32, 15i32; ')');
774 assert!(r1.contains_range(&r1));
775
776 let r2 = range!('(' 10i32,; ')');
777 assert!(!r1.contains_range(&r2));
778 assert!(!r2.contains_range(&r1));
779
780 let r2 = range!('(', 15i32; ']');
781 assert!(!r1.contains_range(&r2));
782 assert!(r2.contains_range(&r1));
783 }
784}