2017-06-07 21:44:03 -04:00
|
|
|
use fmt;
|
2018-06-19 04:08:20 +08:00
|
|
|
use hash::{Hash, Hasher};
|
2017-06-07 21:44:03 -04:00
|
|
|
|
2017-08-07 22:55:20 +02:00
|
|
|
/// An unbounded range (`..`).
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-08-08 14:34:37 +02:00
|
|
|
/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`.
|
2017-08-07 22:55:20 +02:00
|
|
|
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// The `..` syntax is a `RangeFull`:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// assert_eq!((..), std::ops::RangeFull);
|
|
|
|
/// ```
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// It does not have an [`IntoIterator`] implementation, so you can't use it in
|
|
|
|
/// a `for` loop directly. This won't compile:
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-06-20 15:15:16 +08:00
|
|
|
/// ```compile_fail,E0277
|
2017-06-07 21:44:03 -04:00
|
|
|
/// for i in .. {
|
|
|
|
/// // ...
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// ```
|
2019-03-10 01:02:38 -05:00
|
|
|
/// let arr = [0, 1, 2, 3, 4];
|
|
|
|
/// assert_eq!(arr[ .. ], [0,1,2,3,4]); // RangeFull
|
|
|
|
/// assert_eq!(arr[ .. 3], [0,1,2 ]);
|
|
|
|
/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
|
|
|
|
/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[1.. 3], [ 1,2 ]);
|
|
|
|
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
|
|
|
/// [`IntoIterator`]: ../iter/trait.Iterator.html
|
|
|
|
/// [`Iterator`]: ../iter/trait.IntoIterator.html
|
|
|
|
/// [slicing index]: ../slice/trait.SliceIndex.html
|
2018-04-25 20:10:58 +02:00
|
|
|
#[doc(alias = "..")]
|
2017-06-07 21:44:03 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub struct RangeFull;
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
impl fmt::Debug for RangeFull {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(fmt, "..")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-07 22:55:20 +02:00
|
|
|
/// A (half-open) range bounded inclusively below and exclusively above
|
|
|
|
/// (`start..end`).
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// The `Range` `start..end` contains all values with `x >= start` and
|
2019-02-09 22:16:58 +00:00
|
|
|
/// `x < end`. It is empty unless `start < end`.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
|
|
|
|
/// assert_eq!(3 + 4 + 5, (3..6).sum());
|
|
|
|
///
|
2019-03-10 01:02:38 -05:00
|
|
|
/// let arr = [0, 1, 2, 3, 4];
|
|
|
|
/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[ .. 3], [0,1,2 ]);
|
|
|
|
/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
|
|
|
|
/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[1.. 3], [ 1,2 ]); // Range
|
|
|
|
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2018-04-25 20:10:58 +02:00
|
|
|
#[doc(alias = "..")]
|
2019-03-12 21:00:37 -07:00
|
|
|
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
|
2017-06-07 21:44:03 -04:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub struct Range<Idx> {
|
|
|
|
/// The lower bound of the range (inclusive).
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub start: Idx,
|
|
|
|
/// The upper bound of the range (exclusive).
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub end: Idx,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(fmt, "{:?}..{:?}", self.start, self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Idx: PartialOrd<Idx>> Range<Idx> {
|
2017-08-07 22:55:20 +02:00
|
|
|
/// Returns `true` if `item` is contained in the range.
|
|
|
|
///
|
2017-06-07 21:44:03 -04:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-04-07 21:09:26 -07:00
|
|
|
/// use std::f32;
|
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!(!(3..5).contains(&2));
|
|
|
|
/// assert!( (3..5).contains(&3));
|
|
|
|
/// assert!( (3..5).contains(&4));
|
|
|
|
/// assert!(!(3..5).contains(&5));
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!(!(3..3).contains(&3));
|
|
|
|
/// assert!(!(3..2).contains(&3));
|
2018-04-07 21:09:26 -07:00
|
|
|
///
|
|
|
|
/// assert!( (0.0..1.0).contains(&0.5));
|
|
|
|
/// assert!(!(0.0..1.0).contains(&f32::NAN));
|
|
|
|
/// assert!(!(0.0..f32::NAN).contains(&0.5));
|
|
|
|
/// assert!(!(f32::NAN..1.0).contains(&0.5));
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2019-03-12 21:00:37 -07:00
|
|
|
#[stable(feature = "range_contains", since = "1.35.0")]
|
2018-04-07 15:47:18 -07:00
|
|
|
pub fn contains<U>(&self, item: &U) -> bool
|
|
|
|
where
|
|
|
|
Idx: PartialOrd<U>,
|
2018-04-10 19:26:25 -07:00
|
|
|
U: ?Sized + PartialOrd<Idx>,
|
2018-04-07 15:47:18 -07:00
|
|
|
{
|
|
|
|
<Self as RangeBounds<Idx>>::contains(self, item)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
2018-02-09 01:47:18 -08:00
|
|
|
|
|
|
|
/// Returns `true` if the range contains no items.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// #![feature(range_is_empty)]
|
|
|
|
///
|
|
|
|
/// assert!(!(3..5).is_empty());
|
|
|
|
/// assert!( (3..3).is_empty());
|
|
|
|
/// assert!( (3..2).is_empty());
|
|
|
|
/// ```
|
2018-02-10 16:32:05 -08:00
|
|
|
///
|
|
|
|
/// The range is empty if either side is incomparable:
|
|
|
|
///
|
|
|
|
/// ```
|
2018-01-28 03:19:29 +08:00
|
|
|
/// #![feature(range_is_empty)]
|
2018-02-10 16:32:05 -08:00
|
|
|
///
|
|
|
|
/// use std::f32::NAN;
|
|
|
|
/// assert!(!(3.0..5.0).is_empty());
|
|
|
|
/// assert!( (3.0..NAN).is_empty());
|
|
|
|
/// assert!( (NAN..5.0).is_empty());
|
|
|
|
/// ```
|
2018-02-09 18:01:12 -08:00
|
|
|
#[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
|
2018-02-09 01:47:18 -08:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
!(self.start < self.end)
|
|
|
|
}
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
|
2017-08-07 22:55:20 +02:00
|
|
|
/// A range only bounded inclusively below (`start..`).
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// The `RangeFrom` `start..` contains all values with `x >= start`.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
|
2017-06-07 21:44:03 -04:00
|
|
|
/// implementation; if you use an integer range and the integer overflows, it
|
2017-08-07 22:55:20 +02:00
|
|
|
/// might panic in debug mode or create an endless loop in release mode. **This
|
|
|
|
/// overflow behavior might change in the future.**
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
|
|
|
|
/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
|
|
|
|
///
|
2019-03-10 01:02:38 -05:00
|
|
|
/// let arr = [0, 1, 2, 3, 4];
|
|
|
|
/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[ .. 3], [0,1,2 ]);
|
|
|
|
/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
|
|
|
|
/// assert_eq!(arr[1.. ], [ 1,2,3,4]); // RangeFrom
|
|
|
|
/// assert_eq!(arr[1.. 3], [ 1,2 ]);
|
|
|
|
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
|
|
|
/// [`Iterator`]: ../iter/trait.IntoIterator.html
|
2018-04-25 20:10:58 +02:00
|
|
|
#[doc(alias = "..")]
|
2019-03-12 21:00:37 -07:00
|
|
|
#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
|
2017-06-07 21:44:03 -04:00
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub struct RangeFrom<Idx> {
|
|
|
|
/// The lower bound of the range (inclusive).
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub start: Idx,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(fmt, "{:?}..", self.start)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
|
2017-08-07 22:55:20 +02:00
|
|
|
/// Returns `true` if `item` is contained in the range.
|
|
|
|
///
|
2017-06-07 21:44:03 -04:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-04-07 21:09:26 -07:00
|
|
|
/// use std::f32;
|
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!(!(3..).contains(&2));
|
|
|
|
/// assert!( (3..).contains(&3));
|
|
|
|
/// assert!( (3..).contains(&1_000_000_000));
|
2018-04-07 21:09:26 -07:00
|
|
|
///
|
|
|
|
/// assert!( (0.0..).contains(&0.5));
|
|
|
|
/// assert!(!(0.0..).contains(&f32::NAN));
|
|
|
|
/// assert!(!(f32::NAN..).contains(&0.5));
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2019-03-12 21:00:37 -07:00
|
|
|
#[stable(feature = "range_contains", since = "1.35.0")]
|
2018-04-07 15:47:18 -07:00
|
|
|
pub fn contains<U>(&self, item: &U) -> bool
|
|
|
|
where
|
|
|
|
Idx: PartialOrd<U>,
|
2018-04-10 19:26:25 -07:00
|
|
|
U: ?Sized + PartialOrd<Idx>,
|
2018-04-07 15:47:18 -07:00
|
|
|
{
|
|
|
|
<Self as RangeBounds<Idx>>::contains(self, item)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-07 22:55:20 +02:00
|
|
|
/// A range only bounded exclusively above (`..end`).
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// The `RangeTo` `..end` contains all values with `x < end`.
|
|
|
|
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// The `..end` syntax is a `RangeTo`:
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
/// assert_eq!((..5), std::ops::RangeTo { end: 5 });
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// It does not have an [`IntoIterator`] implementation, so you can't use it in
|
|
|
|
/// a `for` loop directly. This won't compile:
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-06-20 15:15:16 +08:00
|
|
|
/// ```compile_fail,E0277
|
2017-08-08 14:34:37 +02:00
|
|
|
/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>:
|
|
|
|
/// // std::iter::Iterator` is not satisfied
|
2017-06-07 21:44:03 -04:00
|
|
|
/// for i in ..5 {
|
|
|
|
/// // ...
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// When used as a [slicing index], `RangeTo` produces a slice of all array
|
2017-06-07 21:44:03 -04:00
|
|
|
/// elements before the index indicated by `end`.
|
|
|
|
///
|
|
|
|
/// ```
|
2019-03-10 01:02:38 -05:00
|
|
|
/// let arr = [0, 1, 2, 3, 4];
|
|
|
|
/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[ .. 3], [0,1,2 ]); // RangeTo
|
|
|
|
/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
|
|
|
|
/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[1.. 3], [ 1,2 ]);
|
|
|
|
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
|
|
|
/// [`IntoIterator`]: ../iter/trait.Iterator.html
|
|
|
|
/// [`Iterator`]: ../iter/trait.IntoIterator.html
|
|
|
|
/// [slicing index]: ../slice/trait.SliceIndex.html
|
2018-04-25 20:10:58 +02:00
|
|
|
#[doc(alias = "..")]
|
2017-06-07 21:44:03 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub struct RangeTo<Idx> {
|
|
|
|
/// The upper bound of the range (exclusive).
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
pub end: Idx,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
|
|
impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(fmt, "..{:?}", self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
|
2017-08-07 22:55:20 +02:00
|
|
|
/// Returns `true` if `item` is contained in the range.
|
|
|
|
///
|
2017-06-07 21:44:03 -04:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-04-07 21:09:26 -07:00
|
|
|
/// use std::f32;
|
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!( (..5).contains(&-1_000_000_000));
|
|
|
|
/// assert!( (..5).contains(&4));
|
|
|
|
/// assert!(!(..5).contains(&5));
|
2018-04-07 21:09:26 -07:00
|
|
|
///
|
|
|
|
/// assert!( (..1.0).contains(&0.5));
|
|
|
|
/// assert!(!(..1.0).contains(&f32::NAN));
|
|
|
|
/// assert!(!(..f32::NAN).contains(&0.5));
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2019-03-12 21:00:37 -07:00
|
|
|
#[stable(feature = "range_contains", since = "1.35.0")]
|
2018-04-07 15:47:18 -07:00
|
|
|
pub fn contains<U>(&self, item: &U) -> bool
|
|
|
|
where
|
|
|
|
Idx: PartialOrd<U>,
|
2018-04-10 19:26:25 -07:00
|
|
|
U: ?Sized + PartialOrd<Idx>,
|
2018-04-07 15:47:18 -07:00
|
|
|
{
|
|
|
|
<Self as RangeBounds<Idx>>::contains(self, item)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-21 23:42:19 +02:00
|
|
|
/// A range bounded inclusively below and above (`start..=end`).
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-09-19 05:40:04 +00:00
|
|
|
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
|
2019-02-09 22:16:58 +00:00
|
|
|
/// and `x <= end`. It is empty unless `start <= end`.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2018-02-09 17:54:27 -08:00
|
|
|
/// This iterator is [fused], but the specific values of `start` and `end` after
|
|
|
|
/// iteration has finished are **unspecified** other than that [`.is_empty()`]
|
|
|
|
/// will return `true` once no more values will be produced.
|
|
|
|
///
|
|
|
|
/// [fused]: ../iter/trait.FusedIterator.html
|
|
|
|
/// [`.is_empty()`]: #method.is_empty
|
|
|
|
///
|
2017-06-07 21:44:03 -04:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-04-06 02:03:22 +08:00
|
|
|
/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
|
2017-09-19 05:40:04 +00:00
|
|
|
/// assert_eq!(3 + 4 + 5, (3..=5).sum());
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
2019-03-10 01:02:38 -05:00
|
|
|
/// let arr = [0, 1, 2, 3, 4];
|
|
|
|
/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[ .. 3], [0,1,2 ]);
|
|
|
|
/// assert_eq!(arr[ ..=3], [0,1,2,3 ]);
|
|
|
|
/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[1.. 3], [ 1,2 ]);
|
|
|
|
/// assert_eq!(arr[1..=3], [ 1,2,3 ]); // RangeInclusive
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2018-04-25 20:10:58 +02:00
|
|
|
#[doc(alias = "..=")]
|
2019-03-12 21:00:37 -07:00
|
|
|
#[derive(Clone)] // not Copy -- see #27186
|
2018-01-28 03:09:36 +08:00
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
2017-06-07 21:44:03 -04:00
|
|
|
pub struct RangeInclusive<Idx> {
|
2018-04-06 02:03:22 +08:00
|
|
|
pub(crate) start: Idx,
|
|
|
|
pub(crate) end: Idx,
|
2018-07-13 13:08:28 +08:00
|
|
|
pub(crate) is_empty: Option<bool>,
|
2018-06-19 04:08:20 +08:00
|
|
|
// This field is:
|
|
|
|
// - `None` when next() or next_back() was never called
|
2018-07-13 13:08:28 +08:00
|
|
|
// - `Some(false)` when `start <= end` assuming no overflow
|
|
|
|
// - `Some(true)` otherwise
|
2018-06-19 04:08:20 +08:00
|
|
|
// The field cannot be a simple `bool` because the `..=` constructor can
|
|
|
|
// accept non-PartialOrd types, also we want the constructor to be const.
|
|
|
|
}
|
|
|
|
|
2018-06-30 17:13:21 +08:00
|
|
|
trait RangeInclusiveEquality: Sized {
|
|
|
|
fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool;
|
|
|
|
}
|
RangeInclusive internal iteration performance improvement.
Specialize Iterator::try_fold and DoubleEndedIterator::try_rfold to
improve code generation in all internal iteration scenarios.
This changes brings the performance of internal iteration with
RangeInclusive on par with the performance of iteration with Range:
- Single conditional jump in hot loop,
- Unrolling and vectorization,
- And even Closed Form substitution.
Unfortunately, it only applies to internal iteration. Despite various
attempts at stream-lining the implementation of next and next_back,
LLVM has stubbornly refused to optimize external iteration
appropriately, leaving me with a choice between:
- The current implementation, for which Closed Form substitution is
performed, but which uses 2 conditional jumps in the hot loop when
optimization fail.
- An implementation using a "is_done" boolean, which uses 1
conditional jump in the hot loop when optimization fail, allowing
unrolling and vectorization, but for which Closed Form substitution
fails.
In the absence of any conclusive evidence as to which usecase matters
most, and with no assurance that the lack of Closed Form substitution
is not indicative of other optimizations being foiled, there is no way
to pick one implementation over the other, and thus I defer to the
statu quo as far as next and next_back are concerned.
2019-02-03 16:58:29 +01:00
|
|
|
|
2018-06-30 17:13:21 +08:00
|
|
|
impl<T> RangeInclusiveEquality for T {
|
|
|
|
#[inline]
|
|
|
|
default fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool {
|
2018-07-13 13:08:28 +08:00
|
|
|
range.is_empty.unwrap_or_default()
|
2018-06-30 17:13:21 +08:00
|
|
|
}
|
|
|
|
}
|
RangeInclusive internal iteration performance improvement.
Specialize Iterator::try_fold and DoubleEndedIterator::try_rfold to
improve code generation in all internal iteration scenarios.
This changes brings the performance of internal iteration with
RangeInclusive on par with the performance of iteration with Range:
- Single conditional jump in hot loop,
- Unrolling and vectorization,
- And even Closed Form substitution.
Unfortunately, it only applies to internal iteration. Despite various
attempts at stream-lining the implementation of next and next_back,
LLVM has stubbornly refused to optimize external iteration
appropriately, leaving me with a choice between:
- The current implementation, for which Closed Form substitution is
performed, but which uses 2 conditional jumps in the hot loop when
optimization fail.
- An implementation using a "is_done" boolean, which uses 1
conditional jump in the hot loop when optimization fail, allowing
unrolling and vectorization, but for which Closed Form substitution
fails.
In the absence of any conclusive evidence as to which usecase matters
most, and with no assurance that the lack of Closed Form substitution
is not indicative of other optimizations being foiled, there is no way
to pick one implementation over the other, and thus I defer to the
statu quo as far as next and next_back are concerned.
2019-02-03 16:58:29 +01:00
|
|
|
|
2018-06-30 17:13:21 +08:00
|
|
|
impl<T: PartialOrd> RangeInclusiveEquality for T {
|
|
|
|
#[inline]
|
|
|
|
fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool {
|
|
|
|
range.is_empty()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-19 04:08:20 +08:00
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
|
|
|
impl<Idx: PartialEq> PartialEq for RangeInclusive<Idx> {
|
|
|
|
#[inline]
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
2019-03-12 21:00:37 -07:00
|
|
|
self.start == other.start
|
|
|
|
&& self.end == other.end
|
2018-06-30 17:13:21 +08:00
|
|
|
&& RangeInclusiveEquality::canonicalized_is_empty(self)
|
|
|
|
== RangeInclusiveEquality::canonicalized_is_empty(other)
|
2018-06-19 04:08:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
|
|
|
impl<Idx: Eq> Eq for RangeInclusive<Idx> {}
|
|
|
|
|
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
|
|
|
impl<Idx: Hash> Hash for RangeInclusive<Idx> {
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
|
|
self.start.hash(state);
|
|
|
|
self.end.hash(state);
|
2018-06-30 17:13:21 +08:00
|
|
|
RangeInclusiveEquality::canonicalized_is_empty(self).hash(state);
|
2018-06-19 04:08:20 +08:00
|
|
|
}
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
|
2018-04-06 02:03:22 +08:00
|
|
|
impl<Idx> RangeInclusive<Idx> {
|
|
|
|
/// Creates a new inclusive range. Equivalent to writing `start..=end`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::ops::RangeInclusive;
|
|
|
|
///
|
|
|
|
/// assert_eq!(3..=5, RangeInclusive::new(3, 5));
|
|
|
|
/// ```
|
2018-05-14 23:25:22 +01:00
|
|
|
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
|
2018-04-06 02:03:22 +08:00
|
|
|
#[inline]
|
2018-10-31 11:53:17 -07:00
|
|
|
#[rustc_promotable]
|
2018-04-07 14:19:34 +08:00
|
|
|
pub const fn new(start: Idx, end: Idx) -> Self {
|
2019-03-12 21:00:37 -07:00
|
|
|
Self {
|
|
|
|
start,
|
|
|
|
end,
|
|
|
|
is_empty: None,
|
|
|
|
}
|
2018-04-06 02:03:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the lower bound of the range (inclusive).
|
|
|
|
///
|
2018-04-07 14:19:34 +08:00
|
|
|
/// When using an inclusive range for iteration, the values of `start()` and
|
|
|
|
/// [`end()`] are unspecified after the iteration ended. To determine
|
|
|
|
/// whether the inclusive range is empty, use the [`is_empty()`] method
|
|
|
|
/// instead of comparing `start() > end()`.
|
|
|
|
///
|
2018-05-16 21:19:17 +01:00
|
|
|
/// Note: the value returned by this method is unspecified after the range
|
|
|
|
/// has been iterated to exhaustion.
|
|
|
|
///
|
2018-04-07 14:19:34 +08:00
|
|
|
/// [`end()`]: #method.end
|
|
|
|
/// [`is_empty()`]: #method.is_empty
|
|
|
|
///
|
2018-04-06 02:03:22 +08:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// assert_eq!((3..=5).start(), &3);
|
|
|
|
/// ```
|
2018-05-14 23:25:22 +01:00
|
|
|
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
|
2018-04-06 02:03:22 +08:00
|
|
|
#[inline]
|
2018-10-23 02:04:14 +02:00
|
|
|
pub const fn start(&self) -> &Idx {
|
2018-04-06 02:03:22 +08:00
|
|
|
&self.start
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the upper bound of the range (inclusive).
|
|
|
|
///
|
2018-04-07 14:19:34 +08:00
|
|
|
/// When using an inclusive range for iteration, the values of [`start()`]
|
|
|
|
/// and `end()` are unspecified after the iteration ended. To determine
|
|
|
|
/// whether the inclusive range is empty, use the [`is_empty()`] method
|
|
|
|
/// instead of comparing `start() > end()`.
|
|
|
|
///
|
2018-05-16 21:19:17 +01:00
|
|
|
/// Note: the value returned by this method is unspecified after the range
|
|
|
|
/// has been iterated to exhaustion.
|
|
|
|
///
|
2018-04-07 14:19:34 +08:00
|
|
|
/// [`start()`]: #method.start
|
|
|
|
/// [`is_empty()`]: #method.is_empty
|
|
|
|
///
|
2018-04-06 02:03:22 +08:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// assert_eq!((3..=5).end(), &5);
|
|
|
|
/// ```
|
2018-05-14 23:25:22 +01:00
|
|
|
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
|
2018-04-06 02:03:22 +08:00
|
|
|
#[inline]
|
2018-10-23 02:04:14 +02:00
|
|
|
pub const fn end(&self) -> &Idx {
|
2018-04-06 02:03:22 +08:00
|
|
|
&self.end
|
|
|
|
}
|
2018-05-09 18:03:13 +02:00
|
|
|
|
2018-05-16 21:19:17 +01:00
|
|
|
/// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound).
|
|
|
|
///
|
|
|
|
/// Note: the value returned by this method is unspecified after the range
|
|
|
|
/// has been iterated to exhaustion.
|
2018-05-09 18:03:13 +02:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// assert_eq!((3..=5).into_inner(), (3, 5));
|
|
|
|
/// ```
|
2018-05-14 23:31:20 +01:00
|
|
|
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
|
2018-05-09 18:03:13 +02:00
|
|
|
#[inline]
|
|
|
|
pub fn into_inner(self) -> (Idx, Idx) {
|
|
|
|
(self.start, self.end)
|
|
|
|
}
|
2018-04-06 02:03:22 +08:00
|
|
|
}
|
|
|
|
|
2018-01-28 03:09:36 +08:00
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
2017-06-07 21:44:03 -04:00
|
|
|
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
2017-09-19 05:40:04 +00:00
|
|
|
write!(fmt, "{:?}..={:?}", self.start, self.end)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
|
2017-08-07 22:55:20 +02:00
|
|
|
/// Returns `true` if `item` is contained in the range.
|
|
|
|
///
|
2017-06-07 21:44:03 -04:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-04-07 21:09:26 -07:00
|
|
|
/// use std::f32;
|
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!(!(3..=5).contains(&2));
|
|
|
|
/// assert!( (3..=5).contains(&3));
|
|
|
|
/// assert!( (3..=5).contains(&4));
|
|
|
|
/// assert!( (3..=5).contains(&5));
|
|
|
|
/// assert!(!(3..=5).contains(&6));
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!( (3..=3).contains(&3));
|
|
|
|
/// assert!(!(3..=2).contains(&3));
|
2018-04-07 21:09:26 -07:00
|
|
|
///
|
|
|
|
/// assert!( (0.0..=1.0).contains(&1.0));
|
|
|
|
/// assert!(!(0.0..=1.0).contains(&f32::NAN));
|
|
|
|
/// assert!(!(0.0..=f32::NAN).contains(&0.0));
|
|
|
|
/// assert!(!(f32::NAN..=1.0).contains(&1.0));
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2019-03-12 21:00:37 -07:00
|
|
|
#[stable(feature = "range_contains", since = "1.35.0")]
|
2018-04-07 15:47:18 -07:00
|
|
|
pub fn contains<U>(&self, item: &U) -> bool
|
|
|
|
where
|
|
|
|
Idx: PartialOrd<U>,
|
2018-04-10 19:26:25 -07:00
|
|
|
U: ?Sized + PartialOrd<Idx>,
|
2018-04-07 15:47:18 -07:00
|
|
|
{
|
|
|
|
<Self as RangeBounds<Idx>>::contains(self, item)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
2018-02-09 01:47:18 -08:00
|
|
|
|
|
|
|
/// Returns `true` if the range contains no items.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-01-28 03:19:29 +08:00
|
|
|
/// #![feature(range_is_empty)]
|
2018-02-09 01:47:18 -08:00
|
|
|
///
|
|
|
|
/// assert!(!(3..=5).is_empty());
|
|
|
|
/// assert!(!(3..=3).is_empty());
|
|
|
|
/// assert!( (3..=2).is_empty());
|
|
|
|
/// ```
|
2018-02-09 17:54:27 -08:00
|
|
|
///
|
2018-02-10 16:32:05 -08:00
|
|
|
/// The range is empty if either side is incomparable:
|
|
|
|
///
|
|
|
|
/// ```
|
2018-01-28 03:19:29 +08:00
|
|
|
/// #![feature(range_is_empty)]
|
2018-02-10 16:32:05 -08:00
|
|
|
///
|
|
|
|
/// use std::f32::NAN;
|
|
|
|
/// assert!(!(3.0..=5.0).is_empty());
|
|
|
|
/// assert!( (3.0..=NAN).is_empty());
|
|
|
|
/// assert!( (NAN..=5.0).is_empty());
|
|
|
|
/// ```
|
|
|
|
///
|
2018-02-09 17:54:27 -08:00
|
|
|
/// This method returns `true` after iteration has finished:
|
|
|
|
///
|
|
|
|
/// ```
|
2018-01-28 03:19:29 +08:00
|
|
|
/// #![feature(range_is_empty)]
|
2018-02-09 17:54:27 -08:00
|
|
|
///
|
|
|
|
/// let mut r = 3..=5;
|
|
|
|
/// for _ in r.by_ref() {}
|
|
|
|
/// // Precise field values are unspecified here
|
|
|
|
/// assert!(r.is_empty());
|
|
|
|
/// ```
|
2018-02-09 18:01:12 -08:00
|
|
|
#[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
|
2018-06-19 04:08:20 +08:00
|
|
|
#[inline]
|
2018-02-09 01:47:18 -08:00
|
|
|
pub fn is_empty(&self) -> bool {
|
2018-07-13 13:08:28 +08:00
|
|
|
self.is_empty.unwrap_or_else(|| !(self.start <= self.end))
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this range's `is_empty` is field is unknown (`None`), update it to be a concrete value.
|
|
|
|
#[inline]
|
|
|
|
pub(crate) fn compute_is_empty(&mut self) {
|
|
|
|
if self.is_empty.is_none() {
|
|
|
|
self.is_empty = Some(!(self.start <= self.end));
|
|
|
|
}
|
2018-02-09 01:47:18 -08:00
|
|
|
}
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
|
2017-09-19 05:40:04 +00:00
|
|
|
/// A range only bounded inclusively above (`..=end`).
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
2017-09-19 05:40:04 +00:00
|
|
|
/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
|
2017-08-07 22:55:20 +02:00
|
|
|
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
2017-09-19 05:40:04 +00:00
|
|
|
/// The `..=end` syntax is a `RangeToInclusive`:
|
2017-06-07 21:44:03 -04:00
|
|
|
///
|
|
|
|
/// ```
|
2017-09-19 05:40:04 +00:00
|
|
|
/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
|
2017-06-07 21:44:03 -04:00
|
|
|
/// `for` loop directly. This won't compile:
|
|
|
|
///
|
2017-06-20 15:15:16 +08:00
|
|
|
/// ```compile_fail,E0277
|
2017-08-08 14:34:37 +02:00
|
|
|
/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
|
|
|
|
/// // std::iter::Iterator` is not satisfied
|
2017-09-19 05:40:04 +00:00
|
|
|
/// for i in ..=5 {
|
2017-06-07 21:44:03 -04:00
|
|
|
/// // ...
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
///
|
2017-08-07 22:55:20 +02:00
|
|
|
/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
|
2017-06-07 21:44:03 -04:00
|
|
|
/// array elements up to and including the index indicated by `end`.
|
|
|
|
///
|
|
|
|
/// ```
|
2019-03-10 01:02:38 -05:00
|
|
|
/// let arr = [0, 1, 2, 3, 4];
|
|
|
|
/// assert_eq!(arr[ .. ], [0,1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[ .. 3], [0,1,2 ]);
|
|
|
|
/// assert_eq!(arr[ ..=3], [0,1,2,3 ]); // RangeToInclusive
|
|
|
|
/// assert_eq!(arr[1.. ], [ 1,2,3,4]);
|
|
|
|
/// assert_eq!(arr[1.. 3], [ 1,2 ]);
|
|
|
|
/// assert_eq!(arr[1..=3], [ 1,2,3 ]);
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2017-08-07 22:55:20 +02:00
|
|
|
///
|
|
|
|
/// [`IntoIterator`]: ../iter/trait.Iterator.html
|
|
|
|
/// [`Iterator`]: ../iter/trait.IntoIterator.html
|
|
|
|
/// [slicing index]: ../slice/trait.SliceIndex.html
|
2018-04-25 20:10:58 +02:00
|
|
|
#[doc(alias = "..=")]
|
2017-06-07 21:44:03 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
2018-01-28 03:09:36 +08:00
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
2017-06-07 21:44:03 -04:00
|
|
|
pub struct RangeToInclusive<Idx> {
|
|
|
|
/// The upper bound of the range (inclusive)
|
2018-01-28 03:09:36 +08:00
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
2017-06-07 21:44:03 -04:00
|
|
|
pub end: Idx,
|
|
|
|
}
|
|
|
|
|
2018-01-28 03:09:36 +08:00
|
|
|
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
2017-06-07 21:44:03 -04:00
|
|
|
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
|
|
|
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
2017-09-19 05:40:04 +00:00
|
|
|
write!(fmt, "..={:?}", self.end)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
|
2017-08-07 22:55:20 +02:00
|
|
|
/// Returns `true` if `item` is contained in the range.
|
|
|
|
///
|
2017-06-07 21:44:03 -04:00
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2018-04-07 21:09:26 -07:00
|
|
|
/// use std::f32;
|
|
|
|
///
|
2018-04-07 18:34:12 -07:00
|
|
|
/// assert!( (..=5).contains(&-1_000_000_000));
|
|
|
|
/// assert!( (..=5).contains(&5));
|
|
|
|
/// assert!(!(..=5).contains(&6));
|
2018-04-07 21:09:26 -07:00
|
|
|
///
|
|
|
|
/// assert!( (..=1.0).contains(&1.0));
|
|
|
|
/// assert!(!(..=1.0).contains(&f32::NAN));
|
|
|
|
/// assert!(!(..=f32::NAN).contains(&0.5));
|
2017-06-07 21:44:03 -04:00
|
|
|
/// ```
|
2019-03-12 21:00:37 -07:00
|
|
|
#[stable(feature = "range_contains", since = "1.35.0")]
|
2018-04-07 15:47:18 -07:00
|
|
|
pub fn contains<U>(&self, item: &U) -> bool
|
|
|
|
where
|
|
|
|
Idx: PartialOrd<U>,
|
2018-04-10 19:26:25 -07:00
|
|
|
U: ?Sized + PartialOrd<Idx>,
|
2018-04-07 15:47:18 -07:00
|
|
|
{
|
|
|
|
<Self as RangeBounds<Idx>>::contains(self, item)
|
2017-06-07 21:44:03 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
|
|
|
|
// because underflow would be possible with (..0).into()
|
2018-03-19 09:01:17 +01:00
|
|
|
|
|
|
|
/// An endpoint of a range of keys.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// `Bound`s are range endpoints:
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::ops::Bound::*;
|
2018-03-19 09:26:29 +01:00
|
|
|
/// use std::ops::RangeBounds;
|
2018-03-19 09:01:17 +01:00
|
|
|
///
|
2018-05-24 04:39:35 -07:00
|
|
|
/// assert_eq!((..100).start_bound(), Unbounded);
|
|
|
|
/// assert_eq!((1..12).start_bound(), Included(&1));
|
|
|
|
/// assert_eq!((1..12).end_bound(), Excluded(&12));
|
2018-03-19 09:01:17 +01:00
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
|
|
|
|
/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::collections::BTreeMap;
|
|
|
|
/// use std::ops::Bound::{Excluded, Included, Unbounded};
|
|
|
|
///
|
|
|
|
/// let mut map = BTreeMap::new();
|
|
|
|
/// map.insert(3, "a");
|
|
|
|
/// map.insert(5, "b");
|
|
|
|
/// map.insert(8, "c");
|
|
|
|
///
|
|
|
|
/// for (key, value) in map.range((Excluded(3), Included(8))) {
|
|
|
|
/// println!("{}: {}", key, value);
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
|
|
|
|
#[stable(feature = "collections_bound", since = "1.17.0")]
|
|
|
|
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
|
|
|
pub enum Bound<T> {
|
|
|
|
/// An inclusive bound.
|
|
|
|
#[stable(feature = "collections_bound", since = "1.17.0")]
|
|
|
|
Included(#[stable(feature = "collections_bound", since = "1.17.0")] T),
|
|
|
|
/// An exclusive bound.
|
|
|
|
#[stable(feature = "collections_bound", since = "1.17.0")]
|
|
|
|
Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T),
|
|
|
|
/// An infinite endpoint. Indicates that there is no bound in this direction.
|
|
|
|
#[stable(feature = "collections_bound", since = "1.17.0")]
|
|
|
|
Unbounded,
|
|
|
|
}
|
2018-03-19 09:26:29 +01:00
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
/// `RangeBounds` is implemented by Rust's built-in range types, produced
|
2019-03-10 01:21:30 -05:00
|
|
|
/// by range syntax like `..`, `a..`, `..b`, `..=c`, `d..e`, or `f..=g`.
|
2018-03-19 09:26:29 +01:00
|
|
|
pub trait RangeBounds<T: ?Sized> {
|
|
|
|
/// Start index bound.
|
|
|
|
///
|
|
|
|
/// Returns the start value as a `Bound`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # fn main() {
|
|
|
|
/// use std::ops::Bound::*;
|
|
|
|
/// use std::ops::RangeBounds;
|
|
|
|
///
|
2018-05-24 04:39:35 -07:00
|
|
|
/// assert_eq!((..10).start_bound(), Unbounded);
|
|
|
|
/// assert_eq!((3..10).start_bound(), Included(&3));
|
2018-03-19 09:26:29 +01:00
|
|
|
/// # }
|
|
|
|
/// ```
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
|
|
|
fn start_bound(&self) -> Bound<&T>;
|
2018-03-19 09:26:29 +01:00
|
|
|
|
|
|
|
/// End index bound.
|
|
|
|
///
|
|
|
|
/// Returns the end value as a `Bound`.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// # fn main() {
|
|
|
|
/// use std::ops::Bound::*;
|
|
|
|
/// use std::ops::RangeBounds;
|
|
|
|
///
|
2018-05-24 04:39:35 -07:00
|
|
|
/// assert_eq!((3..).end_bound(), Unbounded);
|
|
|
|
/// assert_eq!((3..10).end_bound(), Excluded(&10));
|
2018-03-19 09:26:29 +01:00
|
|
|
/// # }
|
|
|
|
/// ```
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
|
|
|
fn end_bound(&self) -> Bound<&T>;
|
2018-04-07 15:47:18 -07:00
|
|
|
|
|
|
|
/// Returns `true` if `item` is contained in the range.
|
2018-04-07 21:09:26 -07:00
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
|
|
|
/// use std::f32;
|
|
|
|
///
|
|
|
|
/// assert!( (3..5).contains(&4));
|
|
|
|
/// assert!(!(3..5).contains(&2));
|
|
|
|
///
|
|
|
|
/// assert!( (0.0..1.0).contains(&0.5));
|
|
|
|
/// assert!(!(0.0..1.0).contains(&f32::NAN));
|
|
|
|
/// assert!(!(0.0..f32::NAN).contains(&0.5));
|
|
|
|
/// assert!(!(f32::NAN..1.0).contains(&0.5));
|
2019-03-12 21:00:37 -07:00
|
|
|
#[stable(feature = "range_contains", since = "1.35.0")]
|
2018-04-07 15:47:18 -07:00
|
|
|
fn contains<U>(&self, item: &U) -> bool
|
|
|
|
where
|
|
|
|
T: PartialOrd<U>,
|
2018-04-10 19:26:25 -07:00
|
|
|
U: ?Sized + PartialOrd<T>,
|
2018-04-07 15:47:18 -07:00
|
|
|
{
|
2018-05-24 04:39:35 -07:00
|
|
|
(match self.start_bound() {
|
2018-04-07 21:09:26 -07:00
|
|
|
Included(ref start) => *start <= item,
|
|
|
|
Excluded(ref start) => *start < item,
|
|
|
|
Unbounded => true,
|
2019-03-12 21:00:37 -07:00
|
|
|
}) && (match self.end_bound() {
|
2018-04-10 19:26:25 -07:00
|
|
|
Included(ref end) => item <= *end,
|
|
|
|
Excluded(ref end) => item < *end,
|
2018-04-07 21:09:26 -07:00
|
|
|
Unbounded => true,
|
|
|
|
})
|
2018-04-07 15:47:18 -07:00
|
|
|
}
|
2018-03-19 09:26:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
use self::Bound::{Excluded, Included, Unbounded};
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T: ?Sized> RangeBounds<T> for RangeFull {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T> RangeBounds<T> for RangeFrom<T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Included(&self.start)
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T> RangeBounds<T> for RangeTo<T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Excluded(&self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T> RangeBounds<T> for Range<T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Included(&self.start)
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Excluded(&self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T> RangeBounds<T> for RangeInclusive<T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Included(&self.start)
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Included(&self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T> RangeBounds<T> for RangeToInclusive<T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
Included(&self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
match *self {
|
|
|
|
(Included(ref start), _) => Included(start),
|
|
|
|
(Excluded(ref start), _) => Excluded(start),
|
2019-03-12 21:00:37 -07:00
|
|
|
(Unbounded, _) => Unbounded,
|
2018-03-19 09:26:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
match *self {
|
|
|
|
(_, Included(ref end)) => Included(end),
|
|
|
|
(_, Excluded(ref end)) => Excluded(end),
|
2019-03-12 21:00:37 -07:00
|
|
|
(_, Unbounded) => Unbounded,
|
2018-03-19 09:26:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-03-19 09:26:29 +01:00
|
|
|
impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
self.0
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-19 09:26:29 +01:00
|
|
|
self.1
|
|
|
|
}
|
|
|
|
}
|
2018-03-20 19:46:11 +01:00
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-09-03 04:50:14 -07:00
|
|
|
impl<T> RangeBounds<T> for RangeFrom<&T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Included(self.start)
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-09-03 04:50:14 -07:00
|
|
|
impl<T> RangeBounds<T> for RangeTo<&T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Excluded(self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-09-03 04:50:14 -07:00
|
|
|
impl<T> RangeBounds<T> for Range<&T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Included(self.start)
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Excluded(self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-09-03 04:50:14 -07:00
|
|
|
impl<T> RangeBounds<T> for RangeInclusive<&T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Included(self.start)
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Included(self.end)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-24 04:39:35 -07:00
|
|
|
#[stable(feature = "collections_range", since = "1.28.0")]
|
2018-09-03 04:50:14 -07:00
|
|
|
impl<T> RangeBounds<T> for RangeToInclusive<&T> {
|
2018-05-24 04:39:35 -07:00
|
|
|
fn start_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Unbounded
|
|
|
|
}
|
2018-05-24 04:39:35 -07:00
|
|
|
fn end_bound(&self) -> Bound<&T> {
|
2018-03-20 19:46:11 +01:00
|
|
|
Included(self.end)
|
|
|
|
}
|
|
|
|
}
|