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#[unstable(feature = "new_range_api", issue = "125687")]
171impl<T> RangeBounds<T> for Range<&T> {
172    fn start_bound(&self) -> Bound<&T> {
173        Included(self.start)
174    }
175    fn end_bound(&self) -> Bound<&T> {
176        Excluded(self.end)
177    }
178}
179
180// #[unstable(feature = "range_into_bounds", issue = "136903")]
181#[unstable(feature = "new_range_api", issue = "125687")]
182impl<T> IntoBounds<T> for Range<T> {
183    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
184        (Included(self.start), Excluded(self.end))
185    }
186}
187
188#[unstable(feature = "new_range_api", issue = "125687")]
189#[rustc_const_unstable(feature = "const_index", issue = "143775")]
190impl<T> const From<Range<T>> for legacy::Range<T> {
191    #[inline]
192    fn from(value: Range<T>) -> Self {
193        Self { start: value.start, end: value.end }
194    }
195}
196
197#[unstable(feature = "new_range_api", issue = "125687")]
198#[rustc_const_unstable(feature = "const_index", issue = "143775")]
199impl<T> const From<legacy::Range<T>> for Range<T> {
200    #[inline]
201    fn from(value: legacy::Range<T>) -> Self {
202        Self { start: value.start, end: value.end }
203    }
204}
205
206/// A range bounded inclusively below and above (`start..=end`).
207///
208/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
209/// and `x <= end`. It is empty unless `start <= end`.
210///
211/// # Examples
212///
213/// The `start..=end` syntax is a `RangeInclusive`:
214///
215/// ```
216/// #![feature(new_range_api)]
217/// use core::range::RangeInclusive;
218///
219/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, end: 5 });
220/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
221/// ```
222#[lang = "RangeInclusiveCopy"]
223#[derive(Clone, Copy, PartialEq, Eq, Hash)]
224#[unstable(feature = "new_range_api", issue = "125687")]
225pub struct RangeInclusive<Idx> {
226    /// The lower bound of the range (inclusive).
227    #[unstable(feature = "new_range_api", issue = "125687")]
228    pub start: Idx,
229    /// The upper bound of the range (inclusive).
230    #[unstable(feature = "new_range_api", issue = "125687")]
231    pub end: Idx,
232}
233
234#[unstable(feature = "new_range_api", issue = "125687")]
235impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
236    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
237        self.start.fmt(fmt)?;
238        write!(fmt, "..=")?;
239        self.end.fmt(fmt)?;
240        Ok(())
241    }
242}
243
244impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
245    /// Returns `true` if `item` is contained in the range.
246    ///
247    /// # Examples
248    ///
249    /// ```
250    /// #![feature(new_range_api)]
251    /// use core::range::RangeInclusive;
252    ///
253    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
254    /// assert!( RangeInclusive::from(3..=5).contains(&3));
255    /// assert!( RangeInclusive::from(3..=5).contains(&4));
256    /// assert!( RangeInclusive::from(3..=5).contains(&5));
257    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
258    ///
259    /// assert!( RangeInclusive::from(3..=3).contains(&3));
260    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
261    ///
262    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
263    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
264    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
265    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
266    /// ```
267    #[inline]
268    #[unstable(feature = "new_range_api", issue = "125687")]
269    pub fn contains<U>(&self, item: &U) -> bool
270    where
271        Idx: PartialOrd<U>,
272        U: ?Sized + PartialOrd<Idx>,
273    {
274        <Self as RangeBounds<Idx>>::contains(self, item)
275    }
276
277    /// Returns `true` if the range contains no items.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// #![feature(new_range_api)]
283    /// use core::range::RangeInclusive;
284    ///
285    /// assert!(!RangeInclusive::from(3..=5).is_empty());
286    /// assert!(!RangeInclusive::from(3..=3).is_empty());
287    /// assert!( RangeInclusive::from(3..=2).is_empty());
288    /// ```
289    ///
290    /// The range is empty if either side is incomparable:
291    ///
292    /// ```
293    /// #![feature(new_range_api)]
294    /// use core::range::RangeInclusive;
295    ///
296    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
297    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
298    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
299    /// ```
300    #[unstable(feature = "new_range_api", issue = "125687")]
301    #[inline]
302    pub fn is_empty(&self) -> bool {
303        !(self.start <= self.end)
304    }
305}
306
307impl<Idx: Step> RangeInclusive<Idx> {
308    /// Creates an iterator over the elements within this range.
309    ///
310    /// Shorthand for `.clone().into_iter()`
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// #![feature(new_range_api)]
316    /// use core::range::RangeInclusive;
317    ///
318    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
319    /// assert_eq!(i.next(), Some(9));
320    /// assert_eq!(i.next(), Some(16));
321    /// assert_eq!(i.next(), Some(25));
322    /// ```
323    #[unstable(feature = "new_range_api", issue = "125687")]
324    #[inline]
325    pub fn iter(&self) -> IterRangeInclusive<Idx> {
326        self.clone().into_iter()
327    }
328}
329
330impl RangeInclusive<usize> {
331    /// Converts to an exclusive `Range` for `SliceIndex` implementations.
332    /// The caller is responsible for dealing with `end == usize::MAX`.
333    #[inline]
334    pub(crate) const fn into_slice_range(self) -> Range<usize> {
335        Range { start: self.start, end: self.end + 1 }
336    }
337}
338
339#[unstable(feature = "new_range_api", issue = "125687")]
340impl<T> RangeBounds<T> for RangeInclusive<T> {
341    fn start_bound(&self) -> Bound<&T> {
342        Included(&self.start)
343    }
344    fn end_bound(&self) -> Bound<&T> {
345        Included(&self.end)
346    }
347}
348
349#[unstable(feature = "new_range_api", issue = "125687")]
350impl<T> RangeBounds<T> for RangeInclusive<&T> {
351    fn start_bound(&self) -> Bound<&T> {
352        Included(self.start)
353    }
354    fn end_bound(&self) -> Bound<&T> {
355        Included(self.end)
356    }
357}
358
359// #[unstable(feature = "range_into_bounds", issue = "136903")]
360#[unstable(feature = "new_range_api", issue = "125687")]
361impl<T> IntoBounds<T> for RangeInclusive<T> {
362    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
363        (Included(self.start), Included(self.end))
364    }
365}
366
367#[unstable(feature = "new_range_api", issue = "125687")]
368#[rustc_const_unstable(feature = "const_index", issue = "143775")]
369impl<T> const From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
370    #[inline]
371    fn from(value: RangeInclusive<T>) -> Self {
372        Self::new(value.start, value.end)
373    }
374}
375#[unstable(feature = "new_range_api", issue = "125687")]
376impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
377    #[inline]
378    fn from(value: legacy::RangeInclusive<T>) -> Self {
379        assert!(
380            !value.exhausted,
381            "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
382        );
383
384        let (start, end) = value.into_inner();
385        RangeInclusive { start, end }
386    }
387}
388
389/// A range only bounded inclusively below (`start..`).
390///
391/// The `RangeFrom` `start..` contains all values with `x >= start`.
392///
393/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
394/// data type reaches its numerical limit) is allowed to panic, wrap, or
395/// saturate. This behavior is defined by the implementation of the [`Step`]
396/// trait. For primitive integers, this follows the normal rules, and respects
397/// the overflow checks profile (panic in debug, wrap in release). Note also
398/// that overflow happens earlier than you might assume: the overflow happens
399/// in the call to `next` that yields the maximum value, as the range must be
400/// set to a state to yield the next value.
401///
402/// [`Step`]: crate::iter::Step
403///
404/// # Examples
405///
406/// The `start..` syntax is a `RangeFrom`:
407///
408/// ```
409/// #![feature(new_range_api)]
410/// use core::range::RangeFrom;
411///
412/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
413/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
414/// ```
415#[lang = "RangeFromCopy"]
416#[derive(Clone, Copy, PartialEq, Eq, Hash)]
417#[unstable(feature = "new_range_api", issue = "125687")]
418pub struct RangeFrom<Idx> {
419    /// The lower bound of the range (inclusive).
420    #[unstable(feature = "new_range_api", issue = "125687")]
421    pub start: Idx,
422}
423
424#[unstable(feature = "new_range_api", issue = "125687")]
425impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
426    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
427        self.start.fmt(fmt)?;
428        write!(fmt, "..")?;
429        Ok(())
430    }
431}
432
433impl<Idx: Step> RangeFrom<Idx> {
434    /// Creates an iterator over the elements within this range.
435    ///
436    /// Shorthand for `.clone().into_iter()`
437    ///
438    /// # Examples
439    ///
440    /// ```
441    /// #![feature(new_range_api)]
442    /// use core::range::RangeFrom;
443    ///
444    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
445    /// assert_eq!(i.next(), Some(9));
446    /// assert_eq!(i.next(), Some(16));
447    /// assert_eq!(i.next(), Some(25));
448    /// ```
449    #[unstable(feature = "new_range_api", issue = "125687")]
450    #[inline]
451    pub fn iter(&self) -> IterRangeFrom<Idx> {
452        self.clone().into_iter()
453    }
454}
455
456impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
457    /// Returns `true` if `item` is contained in the range.
458    ///
459    /// # Examples
460    ///
461    /// ```
462    /// #![feature(new_range_api)]
463    /// use core::range::RangeFrom;
464    ///
465    /// assert!(!RangeFrom::from(3..).contains(&2));
466    /// assert!( RangeFrom::from(3..).contains(&3));
467    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
468    ///
469    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
470    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
471    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
472    /// ```
473    #[inline]
474    #[unstable(feature = "new_range_api", issue = "125687")]
475    pub fn contains<U>(&self, item: &U) -> bool
476    where
477        Idx: PartialOrd<U>,
478        U: ?Sized + PartialOrd<Idx>,
479    {
480        <Self as RangeBounds<Idx>>::contains(self, item)
481    }
482}
483
484#[unstable(feature = "new_range_api", issue = "125687")]
485impl<T> RangeBounds<T> for RangeFrom<T> {
486    fn start_bound(&self) -> Bound<&T> {
487        Included(&self.start)
488    }
489    fn end_bound(&self) -> Bound<&T> {
490        Unbounded
491    }
492}
493
494#[unstable(feature = "new_range_api", issue = "125687")]
495impl<T> RangeBounds<T> for RangeFrom<&T> {
496    fn start_bound(&self) -> Bound<&T> {
497        Included(self.start)
498    }
499    fn end_bound(&self) -> Bound<&T> {
500        Unbounded
501    }
502}
503
504// #[unstable(feature = "range_into_bounds", issue = "136903")]
505#[unstable(feature = "new_range_api", issue = "125687")]
506impl<T> IntoBounds<T> for RangeFrom<T> {
507    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
508        (Included(self.start), Unbounded)
509    }
510}
511
512#[unstable(feature = "new_range_api", issue = "125687")]
513#[rustc_const_unstable(feature = "const_index", issue = "143775")]
514impl<T> const From<RangeFrom<T>> for legacy::RangeFrom<T> {
515    #[inline]
516    fn from(value: RangeFrom<T>) -> Self {
517        Self { start: value.start }
518    }
519}
520#[unstable(feature = "new_range_api", issue = "125687")]
521#[rustc_const_unstable(feature = "const_index", issue = "143775")]
522impl<T> const From<legacy::RangeFrom<T>> for RangeFrom<T> {
523    #[inline]
524    fn from(value: legacy::RangeFrom<T>) -> Self {
525        Self { start: value.start }
526    }
527}
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