1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
// RangeBounds support for older Rust versions.

use lib::ops::{Range, RangeFrom, RangeTo, RangeFull};
use super::bound::*;

#[cfg(has_full_range_inclusive)]
use lib::ops::{RangeInclusive, RangeToInclusive};

//  The compiler does not have RangeBounds defined, this is code
//  adopted from Rust:
//      https://doc.rust-lang.org/src/core/ops/range.rs.html
//
//  All copyright for the remainder of this file remains with the
//  Rust contributors:
//      https://github.com/rust-lang/rust/blob/master/COPYRIGHT

#[cfg(has_range_bounds)]
pub use lib::ops::RangeBounds;

#[cfg(not(has_range_bounds))]
pub trait RangeBounds<T: ?Sized> {
    /// Start index bound.
    fn start_bound(&self) -> Bound<&T>;

    /// End index bound.
    fn end_bound(&self) -> Bound<&T>;

    /// Detect if item is in range.
    fn contains<U>(&self, item: &U) -> bool
    where
        T: PartialOrd<U>,
        U: ?Sized + PartialOrd<T>,
    {
        (match self.start_bound() {
            Included(ref start) => *start <= item,
            Excluded(ref start) => *start < item,
            Unbounded => true,
        }) && (match self.end_bound() {
            Included(ref end) => item <= *end,
            Excluded(ref end) => item < *end,
            Unbounded => true,
        })
    }
}

#[cfg(not(has_range_bounds))]
impl<T: ?Sized> RangeBounds<T> for RangeFull {
    fn start_bound(&self) -> Bound<&T> {
        Unbounded
    }
    fn end_bound(&self) -> Bound<&T> {
        Unbounded
    }
}

#[cfg(not(has_range_bounds))]
impl<T> RangeBounds<T> for RangeFrom<T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Unbounded
    }
}

#[cfg(not(has_range_bounds))]
impl<T> RangeBounds<T> for RangeTo<T> {
    fn start_bound(&self) -> Bound<&T> {
        Unbounded
    }
    fn end_bound(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

#[cfg(not(has_range_bounds))]
impl<T> RangeBounds<T> for Range<T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

#[cfg(all(not(has_range_bounds), has_full_range_inclusive))]
impl<T> RangeBounds<T> for RangeInclusive<T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(self.start())
    }
    fn end_bound(&self) -> Bound<&T> {
        Included(self.end())
    }
}

#[cfg(all(not(has_range_bounds), has_full_range_inclusive))]
impl<T> RangeBounds<T> for RangeToInclusive<T> {
    fn start_bound(&self) -> Bound<&T> {
        Unbounded
    }
    fn end_bound(&self) -> Bound<&T> {
        Included(&self.end)
    }
}