]> git.proxmox.com Git - rustc.git/blame - src/libcore/ops/range.rs
New upstream version 1.28.0+dfsg1
[rustc.git] / src / libcore / ops / range.rs
CommitLineData
041b39d2
XL
1// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use fmt;
12
3b2f2976 13/// An unbounded range (`..`).
041b39d2 14///
3b2f2976
XL
15/// `RangeFull` is primarily used as a [slicing index], its shorthand is `..`.
16/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
041b39d2
XL
17///
18/// # Examples
19///
20/// The `..` syntax is a `RangeFull`:
21///
22/// ```
23/// assert_eq!((..), std::ops::RangeFull);
24/// ```
25///
3b2f2976
XL
26/// It does not have an [`IntoIterator`] implementation, so you can't use it in
27/// a `for` loop directly. This won't compile:
041b39d2
XL
28///
29/// ```compile_fail,E0277
30/// for i in .. {
31/// // ...
32/// }
33/// ```
34///
3b2f2976 35/// Used as a [slicing index], `RangeFull` produces the full array as a slice.
041b39d2
XL
36///
37/// ```
38/// let arr = [0, 1, 2, 3];
39/// assert_eq!(arr[ .. ], [0,1,2,3]); // RangeFull
40/// assert_eq!(arr[ ..3], [0,1,2 ]);
41/// assert_eq!(arr[1.. ], [ 1,2,3]);
42/// assert_eq!(arr[1..3], [ 1,2 ]);
43/// ```
3b2f2976
XL
44///
45/// [`IntoIterator`]: ../iter/trait.Iterator.html
46/// [`Iterator`]: ../iter/trait.IntoIterator.html
47/// [slicing index]: ../slice/trait.SliceIndex.html
83c7162d 48#[doc(alias = "..")]
041b39d2
XL
49#[derive(Copy, Clone, PartialEq, Eq, Hash)]
50#[stable(feature = "rust1", since = "1.0.0")]
51pub struct RangeFull;
52
53#[stable(feature = "rust1", since = "1.0.0")]
54impl fmt::Debug for RangeFull {
55 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
56 write!(fmt, "..")
57 }
58}
59
3b2f2976
XL
60/// A (half-open) range bounded inclusively below and exclusively above
61/// (`start..end`).
041b39d2 62///
3b2f2976 63/// The `Range` `start..end` contains all values with `x >= start` and
0531ce1d 64/// `x < end`. It is empty unless `start < end`.
041b39d2
XL
65///
66/// # Examples
67///
68/// ```
3b2f2976
XL
69/// assert_eq!((3..5), std::ops::Range { start: 3, end: 5 });
70/// assert_eq!(3 + 4 + 5, (3..6).sum());
71///
0531ce1d
XL
72/// let arr = ['a', 'b', 'c', 'd'];
73/// assert_eq!(arr[ .. ], ['a', 'b', 'c', 'd']);
74/// assert_eq!(arr[ ..3], ['a', 'b', 'c', ]);
75/// assert_eq!(arr[1.. ], [ 'b', 'c', 'd']);
76/// assert_eq!(arr[1..3], [ 'b', 'c' ]); // Range
041b39d2 77/// ```
83c7162d 78#[doc(alias = "..")]
041b39d2
XL
79#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
80#[stable(feature = "rust1", since = "1.0.0")]
81pub struct Range<Idx> {
82 /// The lower bound of the range (inclusive).
83 #[stable(feature = "rust1", since = "1.0.0")]
84 pub start: Idx,
85 /// The upper bound of the range (exclusive).
86 #[stable(feature = "rust1", since = "1.0.0")]
87 pub end: Idx,
88}
89
90#[stable(feature = "rust1", since = "1.0.0")]
91impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
92 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
93 write!(fmt, "{:?}..{:?}", self.start, self.end)
94 }
95}
96
041b39d2 97impl<Idx: PartialOrd<Idx>> Range<Idx> {
3b2f2976
XL
98 /// Returns `true` if `item` is contained in the range.
99 ///
041b39d2
XL
100 /// # Examples
101 ///
102 /// ```
103 /// #![feature(range_contains)]
041b39d2 104 ///
83c7162d 105 /// use std::f32;
3b2f2976 106 ///
83c7162d
XL
107 /// assert!(!(3..5).contains(&2));
108 /// assert!( (3..5).contains(&3));
109 /// assert!( (3..5).contains(&4));
110 /// assert!(!(3..5).contains(&5));
111 ///
112 /// assert!(!(3..3).contains(&3));
113 /// assert!(!(3..2).contains(&3));
114 ///
115 /// assert!( (0.0..1.0).contains(&0.5));
116 /// assert!(!(0.0..1.0).contains(&f32::NAN));
117 /// assert!(!(0.0..f32::NAN).contains(&0.5));
118 /// assert!(!(f32::NAN..1.0).contains(&0.5));
041b39d2 119 /// ```
0531ce1d 120 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
83c7162d
XL
121 pub fn contains<U>(&self, item: &U) -> bool
122 where
123 Idx: PartialOrd<U>,
124 U: ?Sized + PartialOrd<Idx>,
125 {
126 <Self as RangeBounds<Idx>>::contains(self, item)
041b39d2 127 }
0531ce1d
XL
128
129 /// Returns `true` if the range contains no items.
130 ///
131 /// # Examples
132 ///
133 /// ```
134 /// #![feature(range_is_empty)]
135 ///
136 /// assert!(!(3..5).is_empty());
137 /// assert!( (3..3).is_empty());
138 /// assert!( (3..2).is_empty());
139 /// ```
140 ///
141 /// The range is empty if either side is incomparable:
142 ///
143 /// ```
144 /// #![feature(range_is_empty)]
145 ///
146 /// use std::f32::NAN;
147 /// assert!(!(3.0..5.0).is_empty());
148 /// assert!( (3.0..NAN).is_empty());
149 /// assert!( (NAN..5.0).is_empty());
150 /// ```
151 #[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
152 pub fn is_empty(&self) -> bool {
153 !(self.start < self.end)
154 }
041b39d2
XL
155}
156
3b2f2976 157/// A range only bounded inclusively below (`start..`).
041b39d2 158///
3b2f2976 159/// The `RangeFrom` `start..` contains all values with `x >= start`.
041b39d2 160///
3b2f2976 161/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
041b39d2 162/// implementation; if you use an integer range and the integer overflows, it
3b2f2976
XL
163/// might panic in debug mode or create an endless loop in release mode. **This
164/// overflow behavior might change in the future.**
041b39d2
XL
165///
166/// # Examples
167///
168/// ```
3b2f2976
XL
169/// assert_eq!((2..), std::ops::RangeFrom { start: 2 });
170/// assert_eq!(2 + 3 + 4, (2..).take(3).sum());
171///
172/// let arr = [0, 1, 2, 3];
173/// assert_eq!(arr[ .. ], [0,1,2,3]);
174/// assert_eq!(arr[ ..3], [0,1,2 ]);
175/// assert_eq!(arr[1.. ], [ 1,2,3]); // RangeFrom
176/// assert_eq!(arr[1..3], [ 1,2 ]);
041b39d2 177/// ```
3b2f2976
XL
178///
179/// [`Iterator`]: ../iter/trait.IntoIterator.html
83c7162d 180#[doc(alias = "..")]
041b39d2
XL
181#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
182#[stable(feature = "rust1", since = "1.0.0")]
183pub struct RangeFrom<Idx> {
184 /// The lower bound of the range (inclusive).
185 #[stable(feature = "rust1", since = "1.0.0")]
186 pub start: Idx,
187}
188
189#[stable(feature = "rust1", since = "1.0.0")]
190impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
191 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
192 write!(fmt, "{:?}..", self.start)
193 }
194}
195
041b39d2 196impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
3b2f2976
XL
197 /// Returns `true` if `item` is contained in the range.
198 ///
041b39d2
XL
199 /// # Examples
200 ///
201 /// ```
202 /// #![feature(range_contains)]
3b2f2976 203 ///
83c7162d
XL
204 /// use std::f32;
205 ///
206 /// assert!(!(3..).contains(&2));
207 /// assert!( (3..).contains(&3));
208 /// assert!( (3..).contains(&1_000_000_000));
209 ///
210 /// assert!( (0.0..).contains(&0.5));
211 /// assert!(!(0.0..).contains(&f32::NAN));
212 /// assert!(!(f32::NAN..).contains(&0.5));
041b39d2 213 /// ```
83c7162d
XL
214 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
215 pub fn contains<U>(&self, item: &U) -> bool
216 where
217 Idx: PartialOrd<U>,
218 U: ?Sized + PartialOrd<Idx>,
219 {
220 <Self as RangeBounds<Idx>>::contains(self, item)
041b39d2
XL
221 }
222}
223
3b2f2976 224/// A range only bounded exclusively above (`..end`).
041b39d2 225///
3b2f2976
XL
226/// The `RangeTo` `..end` contains all values with `x < end`.
227/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
041b39d2
XL
228///
229/// # Examples
230///
3b2f2976 231/// The `..end` syntax is a `RangeTo`:
041b39d2
XL
232///
233/// ```
3b2f2976 234/// assert_eq!((..5), std::ops::RangeTo { end: 5 });
041b39d2
XL
235/// ```
236///
3b2f2976
XL
237/// It does not have an [`IntoIterator`] implementation, so you can't use it in
238/// a `for` loop directly. This won't compile:
041b39d2
XL
239///
240/// ```compile_fail,E0277
3b2f2976
XL
241/// // error[E0277]: the trait bound `std::ops::RangeTo<{integer}>:
242/// // std::iter::Iterator` is not satisfied
041b39d2
XL
243/// for i in ..5 {
244/// // ...
245/// }
246/// ```
247///
3b2f2976 248/// When used as a [slicing index], `RangeTo` produces a slice of all array
041b39d2
XL
249/// elements before the index indicated by `end`.
250///
251/// ```
252/// let arr = [0, 1, 2, 3];
253/// assert_eq!(arr[ .. ], [0,1,2,3]);
254/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo
255/// assert_eq!(arr[1.. ], [ 1,2,3]);
256/// assert_eq!(arr[1..3], [ 1,2 ]);
257/// ```
3b2f2976
XL
258///
259/// [`IntoIterator`]: ../iter/trait.Iterator.html
260/// [`Iterator`]: ../iter/trait.IntoIterator.html
261/// [slicing index]: ../slice/trait.SliceIndex.html
83c7162d 262#[doc(alias = "..")]
041b39d2
XL
263#[derive(Copy, Clone, PartialEq, Eq, Hash)]
264#[stable(feature = "rust1", since = "1.0.0")]
265pub struct RangeTo<Idx> {
266 /// The upper bound of the range (exclusive).
267 #[stable(feature = "rust1", since = "1.0.0")]
268 pub end: Idx,
269}
270
271#[stable(feature = "rust1", since = "1.0.0")]
272impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
273 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
274 write!(fmt, "..{:?}", self.end)
275 }
276}
277
041b39d2 278impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
3b2f2976
XL
279 /// Returns `true` if `item` is contained in the range.
280 ///
041b39d2
XL
281 /// # Examples
282 ///
283 /// ```
284 /// #![feature(range_contains)]
3b2f2976 285 ///
83c7162d
XL
286 /// use std::f32;
287 ///
288 /// assert!( (..5).contains(&-1_000_000_000));
289 /// assert!( (..5).contains(&4));
290 /// assert!(!(..5).contains(&5));
291 ///
292 /// assert!( (..1.0).contains(&0.5));
293 /// assert!(!(..1.0).contains(&f32::NAN));
294 /// assert!(!(..f32::NAN).contains(&0.5));
041b39d2 295 /// ```
83c7162d
XL
296 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
297 pub fn contains<U>(&self, item: &U) -> bool
298 where
299 Idx: PartialOrd<U>,
300 U: ?Sized + PartialOrd<Idx>,
301 {
302 <Self as RangeBounds<Idx>>::contains(self, item)
041b39d2
XL
303 }
304}
305
ea8adc8c 306/// An range bounded inclusively below and above (`start..=end`).
041b39d2 307///
ea8adc8c 308/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
0531ce1d
XL
309/// and `x <= end`. It is empty unless `start <= end`.
310///
311/// This iterator is [fused], but the specific values of `start` and `end` after
312/// iteration has finished are **unspecified** other than that [`.is_empty()`]
313/// will return `true` once no more values will be produced.
314///
315/// [fused]: ../iter/trait.FusedIterator.html
316/// [`.is_empty()`]: #method.is_empty
041b39d2
XL
317///
318/// # Examples
319///
320/// ```
83c7162d 321/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5));
ea8adc8c 322/// assert_eq!(3 + 4 + 5, (3..=5).sum());
3b2f2976
XL
323///
324/// let arr = [0, 1, 2, 3];
ea8adc8c
XL
325/// assert_eq!(arr[ ..=2], [0,1,2 ]);
326/// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive
041b39d2 327/// ```
83c7162d 328#[doc(alias = "..=")]
041b39d2 329#[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186
0531ce1d 330#[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2 331pub struct RangeInclusive<Idx> {
83c7162d
XL
332 // FIXME: The current representation follows RFC 1980,
333 // but it is known that LLVM is not able to optimize loops following that RFC.
334 // Consider adding an extra `bool` field to indicate emptiness of the range.
335 // See #45222 for performance test cases.
83c7162d 336 pub(crate) start: Idx,
83c7162d 337 pub(crate) end: Idx,
041b39d2
XL
338}
339
83c7162d
XL
340impl<Idx> RangeInclusive<Idx> {
341 /// Creates a new inclusive range. Equivalent to writing `start..=end`.
342 ///
343 /// # Examples
344 ///
345 /// ```
346 /// use std::ops::RangeInclusive;
347 ///
348 /// assert_eq!(3..=5, RangeInclusive::new(3, 5));
349 /// ```
350 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
351 #[inline]
352 pub const fn new(start: Idx, end: Idx) -> Self {
353 Self { start, end }
354 }
355
356 /// Returns the lower bound of the range (inclusive).
357 ///
358 /// When using an inclusive range for iteration, the values of `start()` and
359 /// [`end()`] are unspecified after the iteration ended. To determine
360 /// whether the inclusive range is empty, use the [`is_empty()`] method
361 /// instead of comparing `start() > end()`.
362 ///
363 /// Note: the value returned by this method is unspecified after the range
364 /// has been iterated to exhaustion.
365 ///
366 /// [`end()`]: #method.end
367 /// [`is_empty()`]: #method.is_empty
368 ///
369 /// # Examples
370 ///
371 /// ```
372 /// assert_eq!((3..=5).start(), &3);
373 /// ```
374 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
375 #[inline]
376 pub fn start(&self) -> &Idx {
377 &self.start
378 }
379
380 /// Returns the upper bound of the range (inclusive).
381 ///
382 /// When using an inclusive range for iteration, the values of [`start()`]
383 /// and `end()` are unspecified after the iteration ended. To determine
384 /// whether the inclusive range is empty, use the [`is_empty()`] method
385 /// instead of comparing `start() > end()`.
386 ///
387 /// Note: the value returned by this method is unspecified after the range
388 /// has been iterated to exhaustion.
389 ///
390 /// [`start()`]: #method.start
391 /// [`is_empty()`]: #method.is_empty
392 ///
393 /// # Examples
394 ///
395 /// ```
396 /// assert_eq!((3..=5).end(), &5);
397 /// ```
398 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
399 #[inline]
400 pub fn end(&self) -> &Idx {
401 &self.end
402 }
403
404 /// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound).
405 ///
406 /// Note: the value returned by this method is unspecified after the range
407 /// has been iterated to exhaustion.
408 ///
409 /// # Examples
410 ///
411 /// ```
412 /// assert_eq!((3..=5).into_inner(), (3, 5));
413 /// ```
414 #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
415 #[inline]
416 pub fn into_inner(self) -> (Idx, Idx) {
417 (self.start, self.end)
418 }
419}
420
0531ce1d 421#[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2
XL
422impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
423 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
ea8adc8c 424 write!(fmt, "{:?}..={:?}", self.start, self.end)
041b39d2
XL
425 }
426}
427
041b39d2 428impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
3b2f2976
XL
429 /// Returns `true` if `item` is contained in the range.
430 ///
041b39d2
XL
431 /// # Examples
432 ///
433 /// ```
0531ce1d 434 /// #![feature(range_contains)]
041b39d2 435 ///
83c7162d
XL
436 /// use std::f32;
437 ///
438 /// assert!(!(3..=5).contains(&2));
439 /// assert!( (3..=5).contains(&3));
440 /// assert!( (3..=5).contains(&4));
441 /// assert!( (3..=5).contains(&5));
442 /// assert!(!(3..=5).contains(&6));
443 ///
444 /// assert!( (3..=3).contains(&3));
445 /// assert!(!(3..=2).contains(&3));
3b2f2976 446 ///
83c7162d
XL
447 /// assert!( (0.0..=1.0).contains(&1.0));
448 /// assert!(!(0.0..=1.0).contains(&f32::NAN));
449 /// assert!(!(0.0..=f32::NAN).contains(&0.0));
450 /// assert!(!(f32::NAN..=1.0).contains(&1.0));
041b39d2 451 /// ```
0531ce1d 452 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
83c7162d
XL
453 pub fn contains<U>(&self, item: &U) -> bool
454 where
455 Idx: PartialOrd<U>,
456 U: ?Sized + PartialOrd<Idx>,
457 {
458 <Self as RangeBounds<Idx>>::contains(self, item)
041b39d2 459 }
0531ce1d
XL
460
461 /// Returns `true` if the range contains no items.
462 ///
463 /// # Examples
464 ///
465 /// ```
466 /// #![feature(range_is_empty)]
467 ///
468 /// assert!(!(3..=5).is_empty());
469 /// assert!(!(3..=3).is_empty());
470 /// assert!( (3..=2).is_empty());
471 /// ```
472 ///
473 /// The range is empty if either side is incomparable:
474 ///
475 /// ```
476 /// #![feature(range_is_empty)]
477 ///
478 /// use std::f32::NAN;
479 /// assert!(!(3.0..=5.0).is_empty());
480 /// assert!( (3.0..=NAN).is_empty());
481 /// assert!( (NAN..=5.0).is_empty());
482 /// ```
483 ///
484 /// This method returns `true` after iteration has finished:
485 ///
486 /// ```
487 /// #![feature(range_is_empty)]
488 ///
489 /// let mut r = 3..=5;
490 /// for _ in r.by_ref() {}
491 /// // Precise field values are unspecified here
492 /// assert!(r.is_empty());
493 /// ```
494 #[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
495 pub fn is_empty(&self) -> bool {
496 !(self.start <= self.end)
497 }
041b39d2
XL
498}
499
ea8adc8c 500/// A range only bounded inclusively above (`..=end`).
041b39d2 501///
ea8adc8c 502/// The `RangeToInclusive` `..=end` contains all values with `x <= end`.
3b2f2976 503/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
041b39d2
XL
504///
505/// # Examples
506///
ea8adc8c 507/// The `..=end` syntax is a `RangeToInclusive`:
041b39d2
XL
508///
509/// ```
ea8adc8c 510/// assert_eq!((..=5), std::ops::RangeToInclusive{ end: 5 });
041b39d2
XL
511/// ```
512///
3b2f2976 513/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
041b39d2
XL
514/// `for` loop directly. This won't compile:
515///
516/// ```compile_fail,E0277
3b2f2976
XL
517/// // error[E0277]: the trait bound `std::ops::RangeToInclusive<{integer}>:
518/// // std::iter::Iterator` is not satisfied
ea8adc8c 519/// for i in ..=5 {
041b39d2
XL
520/// // ...
521/// }
522/// ```
523///
3b2f2976 524/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
041b39d2
XL
525/// array elements up to and including the index indicated by `end`.
526///
527/// ```
041b39d2 528/// let arr = [0, 1, 2, 3];
ea8adc8c
XL
529/// assert_eq!(arr[ ..=2], [0,1,2 ]); // RangeToInclusive
530/// assert_eq!(arr[1..=2], [ 1,2 ]);
041b39d2 531/// ```
3b2f2976
XL
532///
533/// [`IntoIterator`]: ../iter/trait.Iterator.html
534/// [`Iterator`]: ../iter/trait.IntoIterator.html
535/// [slicing index]: ../slice/trait.SliceIndex.html
83c7162d 536#[doc(alias = "..=")]
041b39d2 537#[derive(Copy, Clone, PartialEq, Eq, Hash)]
0531ce1d 538#[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2
XL
539pub struct RangeToInclusive<Idx> {
540 /// The upper bound of the range (inclusive)
0531ce1d 541 #[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2
XL
542 pub end: Idx,
543}
544
0531ce1d 545#[stable(feature = "inclusive_range", since = "1.26.0")]
041b39d2
XL
546impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
547 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
ea8adc8c 548 write!(fmt, "..={:?}", self.end)
041b39d2
XL
549 }
550}
551
552#[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
553impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
3b2f2976
XL
554 /// Returns `true` if `item` is contained in the range.
555 ///
041b39d2
XL
556 /// # Examples
557 ///
558 /// ```
0531ce1d 559 /// #![feature(range_contains)]
3b2f2976 560 ///
83c7162d
XL
561 /// use std::f32;
562 ///
563 /// assert!( (..=5).contains(&-1_000_000_000));
564 /// assert!( (..=5).contains(&5));
565 /// assert!(!(..=5).contains(&6));
566 ///
567 /// assert!( (..=1.0).contains(&1.0));
568 /// assert!(!(..=1.0).contains(&f32::NAN));
569 /// assert!(!(..=f32::NAN).contains(&0.5));
041b39d2 570 /// ```
83c7162d
XL
571 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
572 pub fn contains<U>(&self, item: &U) -> bool
573 where
574 Idx: PartialOrd<U>,
575 U: ?Sized + PartialOrd<Idx>,
576 {
577 <Self as RangeBounds<Idx>>::contains(self, item)
041b39d2
XL
578 }
579}
580
581// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
582// because underflow would be possible with (..0).into()
0531ce1d
XL
583
584/// An endpoint of a range of keys.
585///
586/// # Examples
587///
588/// `Bound`s are range endpoints:
589///
590/// ```
0531ce1d
XL
591/// use std::ops::Bound::*;
592/// use std::ops::RangeBounds;
593///
94b46f34
XL
594/// assert_eq!((..100).start_bound(), Unbounded);
595/// assert_eq!((1..12).start_bound(), Included(&1));
596/// assert_eq!((1..12).end_bound(), Excluded(&12));
0531ce1d
XL
597/// ```
598///
599/// Using a tuple of `Bound`s as an argument to [`BTreeMap::range`].
600/// Note that in most cases, it's better to use range syntax (`1..5`) instead.
601///
602/// ```
603/// use std::collections::BTreeMap;
604/// use std::ops::Bound::{Excluded, Included, Unbounded};
605///
606/// let mut map = BTreeMap::new();
607/// map.insert(3, "a");
608/// map.insert(5, "b");
609/// map.insert(8, "c");
610///
611/// for (key, value) in map.range((Excluded(3), Included(8))) {
612/// println!("{}: {}", key, value);
613/// }
614///
615/// assert_eq!(Some((&3, &"a")), map.range((Unbounded, Included(5))).next());
616/// ```
617///
618/// [`BTreeMap::range`]: ../../std/collections/btree_map/struct.BTreeMap.html#method.range
619#[stable(feature = "collections_bound", since = "1.17.0")]
620#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
621pub enum Bound<T> {
622 /// An inclusive bound.
623 #[stable(feature = "collections_bound", since = "1.17.0")]
624 Included(#[stable(feature = "collections_bound", since = "1.17.0")] T),
625 /// An exclusive bound.
626 #[stable(feature = "collections_bound", since = "1.17.0")]
627 Excluded(#[stable(feature = "collections_bound", since = "1.17.0")] T),
628 /// An infinite endpoint. Indicates that there is no bound in this direction.
629 #[stable(feature = "collections_bound", since = "1.17.0")]
630 Unbounded,
631}
632
94b46f34 633#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d
XL
634/// `RangeBounds` is implemented by Rust's built-in range types, produced
635/// by range syntax like `..`, `a..`, `..b` or `c..d`.
636pub trait RangeBounds<T: ?Sized> {
637 /// Start index bound.
638 ///
639 /// Returns the start value as a `Bound`.
640 ///
641 /// # Examples
642 ///
643 /// ```
0531ce1d
XL
644 /// # fn main() {
645 /// use std::ops::Bound::*;
646 /// use std::ops::RangeBounds;
647 ///
94b46f34
XL
648 /// assert_eq!((..10).start_bound(), Unbounded);
649 /// assert_eq!((3..10).start_bound(), Included(&3));
0531ce1d
XL
650 /// # }
651 /// ```
94b46f34
XL
652 #[stable(feature = "collections_range", since = "1.28.0")]
653 fn start_bound(&self) -> Bound<&T>;
0531ce1d
XL
654
655 /// End index bound.
656 ///
657 /// Returns the end value as a `Bound`.
658 ///
659 /// # Examples
660 ///
661 /// ```
0531ce1d
XL
662 /// # fn main() {
663 /// use std::ops::Bound::*;
664 /// use std::ops::RangeBounds;
665 ///
94b46f34
XL
666 /// assert_eq!((3..).end_bound(), Unbounded);
667 /// assert_eq!((3..10).end_bound(), Excluded(&10));
0531ce1d
XL
668 /// # }
669 /// ```
94b46f34
XL
670 #[stable(feature = "collections_range", since = "1.28.0")]
671 fn end_bound(&self) -> Bound<&T>;
83c7162d
XL
672
673
674 /// Returns `true` if `item` is contained in the range.
675 ///
676 /// # Examples
677 ///
678 /// ```
679 /// #![feature(range_contains)]
680 ///
681 /// use std::f32;
682 ///
683 /// assert!( (3..5).contains(&4));
684 /// assert!(!(3..5).contains(&2));
685 ///
686 /// assert!( (0.0..1.0).contains(&0.5));
687 /// assert!(!(0.0..1.0).contains(&f32::NAN));
688 /// assert!(!(0.0..f32::NAN).contains(&0.5));
689 /// assert!(!(f32::NAN..1.0).contains(&0.5));
690 #[unstable(feature = "range_contains", reason = "recently added as per RFC", issue = "32311")]
691 fn contains<U>(&self, item: &U) -> bool
692 where
693 T: PartialOrd<U>,
694 U: ?Sized + PartialOrd<T>,
695 {
94b46f34 696 (match self.start_bound() {
83c7162d
XL
697 Included(ref start) => *start <= item,
698 Excluded(ref start) => *start < item,
699 Unbounded => true,
700 })
701 &&
94b46f34 702 (match self.end_bound() {
83c7162d
XL
703 Included(ref end) => item <= *end,
704 Excluded(ref end) => item < *end,
705 Unbounded => true,
706 })
707 }
0531ce1d
XL
708}
709
710use self::Bound::{Excluded, Included, Unbounded};
711
94b46f34 712#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 713impl<T: ?Sized> RangeBounds<T> for RangeFull {
94b46f34 714 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
715 Unbounded
716 }
94b46f34 717 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
718 Unbounded
719 }
720}
721
94b46f34 722#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 723impl<T> RangeBounds<T> for RangeFrom<T> {
94b46f34 724 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
725 Included(&self.start)
726 }
94b46f34 727 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
728 Unbounded
729 }
730}
731
94b46f34 732#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 733impl<T> RangeBounds<T> for RangeTo<T> {
94b46f34 734 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
735 Unbounded
736 }
94b46f34 737 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
738 Excluded(&self.end)
739 }
740}
741
94b46f34 742#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 743impl<T> RangeBounds<T> for Range<T> {
94b46f34 744 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
745 Included(&self.start)
746 }
94b46f34 747 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
748 Excluded(&self.end)
749 }
750}
751
94b46f34 752#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 753impl<T> RangeBounds<T> for RangeInclusive<T> {
94b46f34 754 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
755 Included(&self.start)
756 }
94b46f34 757 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
758 Included(&self.end)
759 }
760}
761
94b46f34 762#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 763impl<T> RangeBounds<T> for RangeToInclusive<T> {
94b46f34 764 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
765 Unbounded
766 }
94b46f34 767 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
768 Included(&self.end)
769 }
770}
771
94b46f34 772#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 773impl<T> RangeBounds<T> for (Bound<T>, Bound<T>) {
94b46f34 774 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
775 match *self {
776 (Included(ref start), _) => Included(start),
777 (Excluded(ref start), _) => Excluded(start),
778 (Unbounded, _) => Unbounded,
779 }
780 }
781
94b46f34 782 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
783 match *self {
784 (_, Included(ref end)) => Included(end),
785 (_, Excluded(ref end)) => Excluded(end),
786 (_, Unbounded) => Unbounded,
787 }
788 }
789}
790
94b46f34 791#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 792impl<'a, T: ?Sized + 'a> RangeBounds<T> for (Bound<&'a T>, Bound<&'a T>) {
94b46f34 793 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
794 self.0
795 }
796
94b46f34 797 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
798 self.1
799 }
800}
801
94b46f34 802#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 803impl<'a, T> RangeBounds<T> for RangeFrom<&'a T> {
94b46f34 804 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
805 Included(self.start)
806 }
94b46f34 807 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
808 Unbounded
809 }
810}
811
94b46f34 812#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 813impl<'a, T> RangeBounds<T> for RangeTo<&'a T> {
94b46f34 814 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
815 Unbounded
816 }
94b46f34 817 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
818 Excluded(self.end)
819 }
820}
821
94b46f34 822#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 823impl<'a, T> RangeBounds<T> for Range<&'a T> {
94b46f34 824 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
825 Included(self.start)
826 }
94b46f34 827 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
828 Excluded(self.end)
829 }
830}
831
94b46f34 832#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 833impl<'a, T> RangeBounds<T> for RangeInclusive<&'a T> {
94b46f34 834 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
835 Included(self.start)
836 }
94b46f34 837 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
838 Included(self.end)
839 }
840}
841
94b46f34 842#[stable(feature = "collections_range", since = "1.28.0")]
0531ce1d 843impl<'a, T> RangeBounds<T> for RangeToInclusive<&'a T> {
94b46f34 844 fn start_bound(&self) -> Bound<&T> {
0531ce1d
XL
845 Unbounded
846 }
94b46f34 847 fn end_bound(&self) -> Bound<&T> {
0531ce1d
XL
848 Included(self.end)
849 }
850}