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