Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add core::ops::Range*::contains() as per #32311
Signed-off-by: NODA, Kai <nodakai@gmail.com>
  • Loading branch information
nodakai committed Mar 24, 2016
1 parent 98f0a91 commit a21c5f2
Showing 1 changed file with 208 additions and 6 deletions.
214 changes: 208 additions & 6 deletions src/libcore/ops.rs
Expand Up @@ -1446,7 +1446,24 @@ pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
}

/// An unbounded range.
/// An unbounded range. Use `..` (two dots) for its shorthand.
///
/// Its primary use case is slicing index. It cannot serve as an iterator
/// because it doesn't have a starting point.
///
/// # Examples
///
/// ```
/// fn main() {
/// assert_eq!((..), std::ops::RangeFull);
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull
/// assert_eq!(arr[ ..3], [0,1,2 ]);
/// assert_eq!(arr[1.. ], [ 1,2,3]);
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// }
/// ```
#[derive(Copy, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFull;
Expand All @@ -1458,7 +1475,26 @@ impl fmt::Debug for RangeFull {
}
}

/// A (half-open) range which is bounded at both ends.
/// A (half-open) range which is bounded at both ends: { x | start <= x < end }.
/// Use `start..end` (two dots) for its shorthand.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// # Examples
///
/// ```
/// #![feature(iter_arith)]
/// fn main() {
/// assert_eq!((3..5), std::ops::Range{ start: 3, end: 5 });
/// assert_eq!(3+4+5, (3..6).sum());
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ .. ], [0,1,2,3]);
/// assert_eq!(arr[ ..3], [0,1,2 ]);
/// assert_eq!(arr[1.. ], [ 1,2,3]);
/// assert_eq!(arr[1..3], [ 1,2 ]); // Range
/// }
/// ```
#[derive(Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Range<Idx> {
Expand All @@ -1477,7 +1513,47 @@ impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
}
}

/// A range which is only bounded below.
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> Range<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
/// fn main() {
/// assert!( ! (3..5).contains(2));
/// assert!( (3..5).contains(3));
/// assert!( (3..5).contains(4));
/// assert!( ! (3..5).contains(5));
///
/// assert!( ! (3..3).contains(3));
/// assert!( ! (3..2).contains(3));
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
(self.start <= item) && (item < self.end)
}
}

/// A range which is only bounded below: { x | start <= x }.
/// Use `start..` for its shorthand.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// # Examples
///
/// ```
/// #![feature(iter_arith)]
/// fn main() {
/// assert_eq!((2..), std::ops::RangeFrom{ start: 2 });
/// assert_eq!(2+3+4, (2..).take(3).sum());
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ .. ], [0,1,2,3]);
/// assert_eq!(arr[ ..3], [0,1,2 ]);
/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// }
/// ```
#[derive(Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFrom<Idx> {
Expand All @@ -1493,7 +1569,40 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
}
}

/// A range which is only bounded above.
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
/// fn main() {
/// assert!( ! (3..).contains(2));
/// assert!( (3..).contains(3));
/// assert!( (3..).contains(1_000_000_000));
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
(self.start <= item)
}
}

/// A range which is only bounded above: { x | x < end }.
/// Use `..end` (two dots) for its shorthand.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// It cannot serve as an iterator because it doesn't have a starting point.
/// ```
/// fn main() {
/// assert_eq!((..5), std::ops::RangeTo{ end: 5 });
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ .. ], [0,1,2,3]);
/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo
/// assert_eq!(arr[1.. ], [ 1,2,3]);
/// assert_eq!(arr[1..3], [ 1,2 ]);
/// }
/// ```
#[derive(Copy, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeTo<Idx> {
Expand All @@ -1509,7 +1618,41 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
}
}

/// An inclusive range which is bounded at both ends.
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains)]
/// fn main() {
/// assert!( (..5).contains(-1_000_000_000));
/// assert!( (..5).contains(4));
/// assert!( ! (..5).contains(5));
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
(item < self.end)
}
}

/// An inclusive range which is bounded at both ends: { x | start <= x <= end }.
/// Use `start...end` (three dots) for its shorthand.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// # Examples
///
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax,iter_arith)]
/// fn main() {
/// assert_eq!((3...5), std::ops::RangeInclusive::NonEmpty{ start: 3, end: 5 });
/// assert_eq!(3+4+5, (3...5).sum());
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]);
/// assert_eq!(arr[1...2], [ 1,2 ]); // RangeInclusive
/// }
/// ```
#[derive(Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
pub enum RangeInclusive<Idx> {
Expand Down Expand Up @@ -1572,7 +1715,49 @@ impl<Idx: PartialOrd + One + Sub<Output=Idx>> From<Range<Idx>> for RangeInclusiv
}
}

/// An inclusive range which is only bounded above.
#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains,inclusive_range_syntax)]
/// fn main() {
/// 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));
///
/// assert!( (3...3).contains(3));
/// assert!( ! (3...2).contains(3));
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
if let &RangeInclusive::NonEmpty{ref start, ref end} = self {
(*start <= item) && (item <= *end)
} else { false }
}
}

/// An inclusive range which is only bounded above: { x | x <= end }.
/// Use `...end` (three dots) for its shorthand.
///
/// See the [`contains()`](#method.contains) method for its characterization.
///
/// It cannot serve as an iterator because it doesn't have a starting point.
///
/// # Examples
///
/// ```
/// #![feature(inclusive_range,inclusive_range_syntax)]
/// fn main() {
/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 });
///
/// let arr = [0, 1, 2, 3];
/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive
/// assert_eq!(arr[1...2], [ 1,2 ]);
/// }
/// ```
#[derive(Copy, Clone, PartialEq, Eq)]
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
pub struct RangeToInclusive<Idx> {
Expand All @@ -1590,6 +1775,23 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
}
}

#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
/// # Examples
///
/// ```
/// #![feature(range_contains,inclusive_range_syntax)]
/// fn main() {
/// assert!( (...5).contains(-1_000_000_000));
/// assert!( (...5).contains(5));
/// assert!( ! (...5).contains(6));
/// }
/// ```
pub fn contains(&self, item: Idx) -> bool {
(item <= self.end)
}
}

// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
// because underflow would be possible with (..0).into()

Expand Down

0 comments on commit a21c5f2

Please sign in to comment.