core/
range.rs

1//! # Experimental replacement range types
2//!
3//! The types within this module are meant to replace the existing
4//! `Range`, `RangeInclusive`, and `RangeFrom` types in a future edition.
5//!
6//! ```
7//! #![feature(new_range_api)]
8//! use core::range::{Range, RangeFrom, RangeInclusive};
9//!
10//! let arr = [0, 1, 2, 3, 4];
11//! assert_eq!(arr[                      ..   ], [0, 1, 2, 3, 4]);
12//! assert_eq!(arr[                      .. 3 ], [0, 1, 2      ]);
13//! assert_eq!(arr[                      ..=3 ], [0, 1, 2, 3   ]);
14//! assert_eq!(arr[     RangeFrom::from(1..  )], [   1, 2, 3, 4]);
15//! assert_eq!(arr[         Range::from(1..3 )], [   1, 2      ]);
16//! assert_eq!(arr[RangeInclusive::from(1..=3)], [   1, 2, 3   ]);
17//! ```
18
19use crate::fmt;
20use crate::hash::Hash;
21
22mod iter;
23
24#[unstable(feature = "new_range_api", issue = "125687")]
25pub mod legacy;
26
27use Bound::{Excluded, Included, Unbounded};
28#[doc(inline)]
29pub use iter::{IterRange, IterRangeFrom, IterRangeInclusive};
30
31#[doc(inline)]
32pub use crate::iter::Step;
33#[doc(inline)]
34pub use crate::ops::{
35    Bound, IntoBounds, OneSidedRange, RangeBounds, RangeFull, RangeTo, RangeToInclusive,
36};
37
38/// A (half-open) range bounded inclusively below and exclusively above
39/// (`start..end` in a future edition).
40///
41/// The range `start..end` contains all values with `start <= x < end`.
42/// It is empty if `start >= end`.
43///
44/// # Examples
45///
46/// ```
47/// #![feature(new_range_api)]
48/// use core::range::Range;
49///
50/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
51/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
52/// ```
53#[lang = "RangeCopy"]
54#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)]
55#[unstable(feature = "new_range_api", issue = "125687")]
56pub struct Range<Idx> {
57    /// The lower bound of the range (inclusive).
58    #[unstable(feature = "new_range_api", issue = "125687")]
59    pub start: Idx,
60    /// The upper bound of the range (exclusive).
61    #[unstable(feature = "new_range_api", issue = "125687")]
62    pub end: Idx,
63}
64
65#[unstable(feature = "new_range_api", issue = "125687")]
66impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
67    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
68        self.start.fmt(fmt)?;
69        write!(fmt, "..")?;
70        self.end.fmt(fmt)?;
71        Ok(())
72    }
73}
74
75impl<Idx: Step> Range<Idx> {
76    /// Creates an iterator over the elements within this range.
77    ///
78    /// Shorthand for `.clone().into_iter()`
79    ///
80    /// # Examples
81    ///
82    /// ```
83    /// #![feature(new_range_api)]
84    /// use core::range::Range;
85    ///
86    /// let mut i = Range::from(3..9).iter().map(|n| n*n);
87    /// assert_eq!(i.next(), Some(9));
88    /// assert_eq!(i.next(), Some(16));
89    /// assert_eq!(i.next(), Some(25));
90    /// ```
91    #[unstable(feature = "new_range_api", issue = "125687")]
92    #[inline]
93    pub fn iter(&self) -> IterRange<Idx> {
94        self.clone().into_iter()
95    }
96}
97
98impl<Idx: PartialOrd<Idx>> Range<Idx> {
99    /// Returns `true` if `item` is contained in the range.
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// #![feature(new_range_api)]
105    /// use core::range::Range;
106    ///
107    /// assert!(!Range::from(3..5).contains(&2));
108    /// assert!( Range::from(3..5).contains(&3));
109    /// assert!( Range::from(3..5).contains(&4));
110    /// assert!(!Range::from(3..5).contains(&5));
111    ///
112    /// assert!(!Range::from(3..3).contains(&3));
113    /// assert!(!Range::from(3..2).contains(&3));
114    ///
115    /// assert!( Range::from(0.0..1.0).contains(&0.5));
116    /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN));
117    /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5));
118    /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5));
119    /// ```
120    #[inline]
121    #[unstable(feature = "new_range_api", issue = "125687")]
122    pub fn contains<U>(&self, item: &U) -> bool
123    where
124        Idx: PartialOrd<U>,
125        U: ?Sized + PartialOrd<Idx>,
126    {
127        <Self as RangeBounds<Idx>>::contains(self, item)
128    }
129
130    /// Returns `true` if the range contains no items.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// #![feature(new_range_api)]
136    /// use core::range::Range;
137    ///
138    /// assert!(!Range::from(3..5).is_empty());
139    /// assert!( Range::from(3..3).is_empty());
140    /// assert!( Range::from(3..2).is_empty());
141    /// ```
142    ///
143    /// The range is empty if either side is incomparable:
144    ///
145    /// ```
146    /// #![feature(new_range_api)]
147    /// use core::range::Range;
148    ///
149    /// assert!(!Range::from(3.0..5.0).is_empty());
150    /// assert!( Range::from(3.0..f32::NAN).is_empty());
151    /// assert!( Range::from(f32::NAN..5.0).is_empty());
152    /// ```
153    #[inline]
154    #[unstable(feature = "new_range_api", issue = "125687")]
155    pub fn is_empty(&self) -> bool {
156        !(self.start < self.end)
157    }
158}
159
160#[unstable(feature = "new_range_api", issue = "125687")]
161impl<T> RangeBounds<T> for Range<T> {
162    fn start_bound(&self) -> Bound<&T> {
163        Included(&self.start)
164    }
165    fn end_bound(&self) -> Bound<&T> {
166        Excluded(&self.end)
167    }
168}
169
170// This impl intentionally does not have `T: ?Sized`;
171// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
172//
173/// If you need to use this implementation where `T` is unsized,
174/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
175/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
176#[unstable(feature = "new_range_api", issue = "125687")]
177impl<T> RangeBounds<T> for Range<&T> {
178    fn start_bound(&self) -> Bound<&T> {
179        Included(self.start)
180    }
181    fn end_bound(&self) -> Bound<&T> {
182        Excluded(self.end)
183    }
184}
185
186// #[unstable(feature = "range_into_bounds", issue = "136903")]
187#[unstable(feature = "new_range_api", issue = "125687")]
188impl<T> IntoBounds<T> for Range<T> {
189    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
190        (Included(self.start), Excluded(self.end))
191    }
192}
193
194#[unstable(feature = "new_range_api", issue = "125687")]
195#[rustc_const_unstable(feature = "const_index", issue = "143775")]
196impl<T> const From<Range<T>> for legacy::Range<T> {
197    #[inline]
198    fn from(value: Range<T>) -> Self {
199        Self { start: value.start, end: value.end }
200    }
201}
202
203#[unstable(feature = "new_range_api", issue = "125687")]
204#[rustc_const_unstable(feature = "const_index", issue = "143775")]
205impl<T> const From<legacy::Range<T>> for Range<T> {
206    #[inline]
207    fn from(value: legacy::Range<T>) -> Self {
208        Self { start: value.start, end: value.end }
209    }
210}
211
212/// A range bounded inclusively below and above (`start..=end`).
213///
214/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
215/// and `x <= end`. It is empty unless `start <= end`.
216///
217/// # Examples
218///
219/// The `start..=end` syntax is a `RangeInclusive`:
220///
221/// ```
222/// #![feature(new_range_api)]
223/// use core::range::RangeInclusive;
224///
225/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
226/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
227/// ```
228#[lang = "RangeInclusiveCopy"]
229#[derive(Clone, Copy, PartialEq, Eq, Hash)]
230#[unstable(feature = "new_range_api", issue = "125687")]
231pub struct RangeInclusive<Idx> {
232    /// The lower bound of the range (inclusive).
233    #[unstable(feature = "new_range_api", issue = "125687")]
234    pub start: Idx,
235    /// The upper bound of the range (inclusive).
236    #[unstable(feature = "new_range_api", issue = "125687")]
237    pub end: Idx,
238}
239
240#[unstable(feature = "new_range_api", issue = "125687")]
241impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
242    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
243        self.start.fmt(fmt)?;
244        write!(fmt, "..=")?;
245        self.end.fmt(fmt)?;
246        Ok(())
247    }
248}
249
250impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
251    /// Returns `true` if `item` is contained in the range.
252    ///
253    /// # Examples
254    ///
255    /// ```
256    /// #![feature(new_range_api)]
257    /// use core::range::RangeInclusive;
258    ///
259    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
260    /// assert!( RangeInclusive::from(3..=5).contains(&3));
261    /// assert!( RangeInclusive::from(3..=5).contains(&4));
262    /// assert!( RangeInclusive::from(3..=5).contains(&5));
263    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
264    ///
265    /// assert!( RangeInclusive::from(3..=3).contains(&3));
266    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
267    ///
268    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
269    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
270    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
271    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
272    /// ```
273    #[inline]
274    #[unstable(feature = "new_range_api", issue = "125687")]
275    pub fn contains<U>(&self, item: &U) -> bool
276    where
277        Idx: PartialOrd<U>,
278        U: ?Sized + PartialOrd<Idx>,
279    {
280        <Self as RangeBounds<Idx>>::contains(self, item)
281    }
282
283    /// Returns `true` if the range contains no items.
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// #![feature(new_range_api)]
289    /// use core::range::RangeInclusive;
290    ///
291    /// assert!(!RangeInclusive::from(3..=5).is_empty());
292    /// assert!(!RangeInclusive::from(3..=3).is_empty());
293    /// assert!( RangeInclusive::from(3..=2).is_empty());
294    /// ```
295    ///
296    /// The range is empty if either side is incomparable:
297    ///
298    /// ```
299    /// #![feature(new_range_api)]
300    /// use core::range::RangeInclusive;
301    ///
302    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
303    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
304    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
305    /// ```
306    #[unstable(feature = "new_range_api", issue = "125687")]
307    #[inline]
308    pub fn is_empty(&self) -> bool {
309        !(self.start <= self.end)
310    }
311}
312
313impl<Idx: Step> RangeInclusive<Idx> {
314    /// Creates an iterator over the elements within this range.
315    ///
316    /// Shorthand for `.clone().into_iter()`
317    ///
318    /// # Examples
319    ///
320    /// ```
321    /// #![feature(new_range_api)]
322    /// use core::range::RangeInclusive;
323    ///
324    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
325    /// assert_eq!(i.next(), Some(9));
326    /// assert_eq!(i.next(), Some(16));
327    /// assert_eq!(i.next(), Some(25));
328    /// ```
329    #[unstable(feature = "new_range_api", issue = "125687")]
330    #[inline]
331    pub fn iter(&self) -> IterRangeInclusive<Idx> {
332        self.clone().into_iter()
333    }
334}
335
336impl RangeInclusive<usize> {
337    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
338    /// The caller is responsible for dealing with `end == usize::MAX`.
339    #[inline]
340    pub(crate) const fn into_slice_range(self) -> Range<usize> {
341        Range { start: self.start, end: self.end + 1 }
342    }
343}
344
345#[unstable(feature = "new_range_api", issue = "125687")]
346impl<T> RangeBounds<T> for RangeInclusive<T> {
347    fn start_bound(&self) -> Bound<&T> {
348        Included(&self.start)
349    }
350    fn end_bound(&self) -> Bound<&T> {
351        Included(&self.end)
352    }
353}
354
355// This impl intentionally does not have `T: ?Sized`;
356// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
357//
358/// If you need to use this implementation where `T` is unsized,
359/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
360/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
361#[unstable(feature = "new_range_api", issue = "125687")]
362impl<T> RangeBounds<T> for RangeInclusive<&T> {
363    fn start_bound(&self) -> Bound<&T> {
364        Included(self.start)
365    }
366    fn end_bound(&self) -> Bound<&T> {
367        Included(self.end)
368    }
369}
370
371// #[unstable(feature = "range_into_bounds", issue = "136903")]
372#[unstable(feature = "new_range_api", issue = "125687")]
373impl<T> IntoBounds<T> for RangeInclusive<T> {
374    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
375        (Included(self.start), Included(self.end))
376    }
377}
378
379#[unstable(feature = "new_range_api", issue = "125687")]
380#[rustc_const_unstable(feature = "const_index", issue = "143775")]
381impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
382    #[inline]
383    fn from(value: RangeInclusive<T>) -> Self {
384        Self::new(value.start, value.end)
385    }
386}
387#[unstable(feature = "new_range_api", issue = "125687")]
388impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
389    #[inline]
390    fn from(value: legacy::RangeInclusive<T>) -> Self {
391        assert!(
392            !value.exhausted,
393            "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
394        );
395
396        let (start, end) = value.into_inner();
397        RangeInclusive { start, end }
398    }
399}
400
401/// A range only bounded inclusively below (`start..`).
402///
403/// The `RangeFrom` `start..` contains all values with `x >= start`.
404///
405/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
406/// data type reaches its numerical limit) is allowed to panic, wrap, or
407/// saturate. This behavior is defined by the implementation of the [`Step`]
408/// trait. For primitive integers, this follows the normal rules, and respects
409/// the overflow checks profile (panic in debug, wrap in release). Note also
410/// that overflow happens earlier than you might assume: the overflow happens
411/// in the call to `next` that yields the maximum value, as the range must be
412/// set to a state to yield the next value.
413///
414/// [`Step`]: crate::iter::Step
415///
416/// # Examples
417///
418/// The `start..` syntax is a `RangeFrom`:
419///
420/// ```
421/// #![feature(new_range_api)]
422/// use core::range::RangeFrom;
423///
424/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
425/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
426/// ```
427#[lang = "RangeFromCopy"]
428#[derive(Clone, Copy, PartialEq, Eq, Hash)]
429#[unstable(feature = "new_range_api", issue = "125687")]
430pub struct RangeFrom<Idx> {
431    /// The lower bound of the range (inclusive).
432    #[unstable(feature = "new_range_api", issue = "125687")]
433    pub start: Idx,
434}
435
436#[unstable(feature = "new_range_api", issue = "125687")]
437impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
438    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
439        self.start.fmt(fmt)?;
440        write!(fmt, "..")?;
441        Ok(())
442    }
443}
444
445impl<Idx: Step> RangeFrom<Idx> {
446    /// Creates an iterator over the elements within this range.
447    ///
448    /// Shorthand for `.clone().into_iter()`
449    ///
450    /// # Examples
451    ///
452    /// ```
453    /// #![feature(new_range_api)]
454    /// use core::range::RangeFrom;
455    ///
456    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
457    /// assert_eq!(i.next(), Some(9));
458    /// assert_eq!(i.next(), Some(16));
459    /// assert_eq!(i.next(), Some(25));
460    /// ```
461    #[unstable(feature = "new_range_api", issue = "125687")]
462    #[inline]
463    pub fn iter(&self) -> IterRangeFrom<Idx> {
464        self.clone().into_iter()
465    }
466}
467
468impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
469    /// Returns `true` if `item` is contained in the range.
470    ///
471    /// # Examples
472    ///
473    /// ```
474    /// #![feature(new_range_api)]
475    /// use core::range::RangeFrom;
476    ///
477    /// assert!(!RangeFrom::from(3..).contains(&2));
478    /// assert!( RangeFrom::from(3..).contains(&3));
479    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
480    ///
481    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
482    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
483    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
484    /// ```
485    #[inline]
486    #[unstable(feature = "new_range_api", issue = "125687")]
487    pub fn contains<U>(&self, item: &U) -> bool
488    where
489        Idx: PartialOrd<U>,
490        U: ?Sized + PartialOrd<Idx>,
491    {
492        <Self as RangeBounds<Idx>>::contains(self, item)
493    }
494}
495
496#[unstable(feature = "new_range_api", issue = "125687")]
497impl<T> RangeBounds<T> for RangeFrom<T> {
498    fn start_bound(&self) -> Bound<&T> {
499        Included(&self.start)
500    }
501    fn end_bound(&self) -> Bound<&T> {
502        Unbounded
503    }
504}
505
506// This impl intentionally does not have `T: ?Sized`;
507// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
508//
509/// If you need to use this implementation where `T` is unsized,
510/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
511/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
512#[unstable(feature = "new_range_api", issue = "125687")]
513impl<T> RangeBounds<T> for RangeFrom<&T> {
514    fn start_bound(&self) -> Bound<&T> {
515        Included(self.start)
516    }
517    fn end_bound(&self) -> Bound<&T> {
518        Unbounded
519    }
520}
521
522// #[unstable(feature = "range_into_bounds", issue = "136903")]
523#[unstable(feature = "new_range_api", issue = "125687")]
524impl<T> IntoBounds<T> for RangeFrom<T> {
525    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
526        (Included(self.start), Unbounded)
527    }
528}
529
530#[unstable(feature = "new_range_api", issue = "125687")]
531#[rustc_const_unstable(feature = "const_index", issue = "143775")]
532impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
533    #[inline]
534    fn from(value: RangeFrom<T>) -> Self {
535        Self { start: value.start }
536    }
537}
538#[unstable(feature = "new_range_api", issue = "125687")]
539#[rustc_const_unstable(feature = "const_index", issue = "143775")]
540impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
541    #[inline]
542    fn from(value: legacy::RangeFrom<T>) -> Self {
543        Self { start: value.start }
544    }
545}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy