//! # Experimental replacement range types //! //! The types within this module are meant to replace the existing //! `Range`, `RangeInclusive`, and `RangeFrom` types in a future edition. //! //! ``` //! #![feature(new_range_api)] //! use core::range::{Range, RangeFrom, RangeInclusive}; //! //! 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[ RangeFrom::from(1.. )], [ 1, 2, 3, 4]); //! assert_eq!(arr[ Range::from(1..3 )], [ 1, 2 ]); //! assert_eq!(arr[RangeInclusive::from(1..=3)], [ 1, 2, 3 ]); //! ``` use crate::fmt; use crate::hash::Hash; mod iter; #[unstable(feature = "new_range_api", issue = "125687")] pub mod legacy; use Bound::{Excluded, Included, Unbounded}; #[doc(inline)] pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive}; #[doc(inline)] pub use crate::iter::Step; #[doc(inline)] pub use crate::ops::{Bound, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive}; /// A (half-open) range bounded inclusively below and exclusively above /// (`start..end` in a future edition). /// /// The range `start..end` contains all values with `start <= x < end`. /// It is empty if `start >= end`. /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 }); /// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum()); /// ``` #[derive(Clone, Copy, Default, PartialEq, Eq, Hash)] #[unstable(feature = "new_range_api", issue = "125687")] pub struct Range { /// The lower bound of the range (inclusive). #[unstable(feature = "new_range_api", issue = "125687")] pub start: Idx, /// The upper bound of the range (exclusive). #[unstable(feature = "new_range_api", issue = "125687")] pub end: Idx, } #[unstable(feature = "new_range_api", issue = "125687")] impl fmt::Debug for Range { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; write!(fmt, "..")?; self.end.fmt(fmt)?; Ok(()) } } impl Range { /// Creates an iterator over the elements within this range. /// /// Shorthand for `.clone().into_iter()` /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::Range; /// /// let mut i = Range::from(3..9).iter().map(|n| n*n); /// assert_eq!(i.next(), Some(9)); /// assert_eq!(i.next(), Some(16)); /// assert_eq!(i.next(), Some(25)); /// ``` #[unstable(feature = "new_range_api", issue = "125687")] #[inline] pub fn iter(&self) -> IterRange { self.clone().into_iter() } } impl> Range { /// Returns `true` if `item` is contained in the range. /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert!(!Range::from(3..5).contains(&2)); /// assert!( Range::from(3..5).contains(&3)); /// assert!( Range::from(3..5).contains(&4)); /// assert!(!Range::from(3..5).contains(&5)); /// /// assert!(!Range::from(3..3).contains(&3)); /// assert!(!Range::from(3..2).contains(&3)); /// /// assert!( Range::from(0.0..1.0).contains(&0.5)); /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN)); /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5)); /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5)); /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] pub fn contains(&self, item: &U) -> bool where Idx: PartialOrd, U: ?Sized + PartialOrd, { >::contains(self, item) } /// Returns `true` if the range contains no items. /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert!(!Range::from(3..5).is_empty()); /// assert!( Range::from(3..3).is_empty()); /// assert!( Range::from(3..2).is_empty()); /// ``` /// /// The range is empty if either side is incomparable: /// /// ``` /// #![feature(new_range_api)] /// use core::range::Range; /// /// assert!(!Range::from(3.0..5.0).is_empty()); /// assert!( Range::from(3.0..f32::NAN).is_empty()); /// assert!( Range::from(f32::NAN..5.0).is_empty()); /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] pub fn is_empty(&self) -> bool { !(self.start < self.end) } } #[unstable(feature = "new_range_api", issue = "125687")] impl RangeBounds for Range { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } fn end_bound(&self) -> Bound<&T> { Excluded(&self.end) } } #[unstable(feature = "new_range_api", issue = "125687")] impl RangeBounds for Range<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } fn end_bound(&self) -> Bound<&T> { Excluded(self.end) } } #[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::Range { #[inline] fn from(value: Range) -> Self { Self { start: value.start, end: value.end } } } #[unstable(feature = "new_range_api", issue = "125687")] impl From> for Range { #[inline] fn from(value: legacy::Range) -> Self { Self { start: value.start, end: value.end } } } /// A range bounded inclusively below and above (`start..=end`). /// /// The `RangeInclusive` `start..=end` contains all values with `x >= start` /// and `x <= end`. It is empty unless `start <= end`. /// /// # Examples /// /// The `start..=end` syntax is a `RangeInclusive`: /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 }); /// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum()); /// ``` #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[unstable(feature = "new_range_api", issue = "125687")] pub struct RangeInclusive { /// The lower bound of the range (inclusive). #[unstable(feature = "new_range_api", issue = "125687")] pub start: Idx, /// The upper bound of the range (inclusive). #[unstable(feature = "new_range_api", issue = "125687")] pub end: Idx, } #[unstable(feature = "new_range_api", issue = "125687")] impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; write!(fmt, "..=")?; self.end.fmt(fmt)?; Ok(()) } } impl> RangeInclusive { /// Returns `true` if `item` is contained in the range. /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3..=5).contains(&2)); /// assert!( RangeInclusive::from(3..=5).contains(&3)); /// assert!( RangeInclusive::from(3..=5).contains(&4)); /// assert!( RangeInclusive::from(3..=5).contains(&5)); /// assert!(!RangeInclusive::from(3..=5).contains(&6)); /// /// assert!( RangeInclusive::from(3..=3).contains(&3)); /// assert!(!RangeInclusive::from(3..=2).contains(&3)); /// /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0)); /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN)); /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0)); /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0)); /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] pub fn contains(&self, item: &U) -> bool where Idx: PartialOrd, U: ?Sized + PartialOrd, { >::contains(self, item) } /// Returns `true` if the range contains no items. /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3..=5).is_empty()); /// assert!(!RangeInclusive::from(3..=3).is_empty()); /// assert!( RangeInclusive::from(3..=2).is_empty()); /// ``` /// /// The range is empty if either side is incomparable: /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty()); /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty()); /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty()); /// ``` #[unstable(feature = "new_range_api", issue = "125687")] #[inline] pub fn is_empty(&self) -> bool { !(self.start <= self.end) } } impl RangeInclusive { /// Creates an iterator over the elements within this range. /// /// Shorthand for `.clone().into_iter()` /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeInclusive; /// /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n); /// assert_eq!(i.next(), Some(9)); /// assert_eq!(i.next(), Some(16)); /// assert_eq!(i.next(), Some(25)); /// ``` #[unstable(feature = "new_range_api", issue = "125687")] #[inline] pub fn iter(&self) -> IterRangeInclusive { self.clone().into_iter() } } impl RangeInclusive { /// Converts to an exclusive `Range` for `SliceIndex` implementations. /// The caller is responsible for dealing with `end == usize::MAX`. #[inline] pub(crate) const fn into_slice_range(self) -> Range { Range { start: self.start, end: self.end + 1 } } } #[unstable(feature = "new_range_api", issue = "125687")] impl RangeBounds for RangeInclusive { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } fn end_bound(&self) -> Bound<&T> { Included(&self.end) } } #[unstable(feature = "new_range_api", issue = "125687")] impl RangeBounds for RangeInclusive<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } fn end_bound(&self) -> Bound<&T> { Included(self.end) } } #[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::RangeInclusive { #[inline] fn from(value: RangeInclusive) -> Self { Self::new(value.start, value.end) } } #[unstable(feature = "new_range_api", issue = "125687")] impl From> for RangeInclusive { #[inline] fn from(value: legacy::RangeInclusive) -> Self { assert!( !value.exhausted, "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)" ); let (start, end) = value.into_inner(); RangeInclusive { start, end } } } /// A range only bounded inclusively below (`start..`). /// /// The `RangeFrom` `start..` contains all values with `x >= start`. /// /// *Note*: Overflow in the [`Iterator`] implementation (when the contained /// data type reaches its numerical limit) is allowed to panic, wrap, or /// saturate. This behavior is defined by the implementation of the [`Step`] /// trait. For primitive integers, this follows the normal rules, and respects /// the overflow checks profile (panic in debug, wrap in release). Note also /// that overflow happens earlier than you might assume: the overflow happens /// in the call to `next` that yields the maximum value, as the range must be /// set to a state to yield the next value. /// /// [`Step`]: crate::iter::Step /// /// # Examples /// /// The `start..` syntax is a `RangeFrom`: /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeFrom; /// /// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 }); /// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum()); /// ``` #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[unstable(feature = "new_range_api", issue = "125687")] pub struct RangeFrom { /// The lower bound of the range (inclusive). #[unstable(feature = "new_range_api", issue = "125687")] pub start: Idx, } #[unstable(feature = "new_range_api", issue = "125687")] impl fmt::Debug for RangeFrom { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { self.start.fmt(fmt)?; write!(fmt, "..")?; Ok(()) } } impl RangeFrom { /// Creates an iterator over the elements within this range. /// /// Shorthand for `.clone().into_iter()` /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeFrom; /// /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n); /// assert_eq!(i.next(), Some(9)); /// assert_eq!(i.next(), Some(16)); /// assert_eq!(i.next(), Some(25)); /// ``` #[unstable(feature = "new_range_api", issue = "125687")] #[inline] pub fn iter(&self) -> IterRangeFrom { self.clone().into_iter() } } impl> RangeFrom { /// Returns `true` if `item` is contained in the range. /// /// # Examples /// /// ``` /// #![feature(new_range_api)] /// use core::range::RangeFrom; /// /// assert!(!RangeFrom::from(3..).contains(&2)); /// assert!( RangeFrom::from(3..).contains(&3)); /// assert!( RangeFrom::from(3..).contains(&1_000_000_000)); /// /// assert!( RangeFrom::from(0.0..).contains(&0.5)); /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN)); /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5)); /// ``` #[inline] #[unstable(feature = "new_range_api", issue = "125687")] pub fn contains(&self, item: &U) -> bool where Idx: PartialOrd, U: ?Sized + PartialOrd, { >::contains(self, item) } } #[unstable(feature = "new_range_api", issue = "125687")] impl RangeBounds for RangeFrom { fn start_bound(&self) -> Bound<&T> { Included(&self.start) } fn end_bound(&self) -> Bound<&T> { Unbounded } } #[unstable(feature = "new_range_api", issue = "125687")] impl RangeBounds for RangeFrom<&T> { fn start_bound(&self) -> Bound<&T> { Included(self.start) } fn end_bound(&self) -> Bound<&T> { Unbounded } } #[unstable(feature = "new_range_api", issue = "125687")] impl From> for legacy::RangeFrom { #[inline] fn from(value: RangeFrom) -> Self { Self { start: value.start } } } #[unstable(feature = "new_range_api", issue = "125687")] impl From> for RangeFrom { #[inline] fn from(value: legacy::RangeFrom) -> Self { Self { start: value.start } } }