1use crate::fmt;
19use crate::hash::Hash;
20
21mod iter;
22
23#[stable(feature = "new_range_api_legacy", since = "CURRENT_RUSTC_VERSION")]
24pub mod legacy;
25
26use core::ops::Bound::{self, Excluded, Included, Unbounded};
27
28#[doc(inline)]
29#[stable(feature = "new_range_from_api", since = "1.96.0")]
30pub use iter::RangeFromIter;
31#[doc(inline)]
32#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
33pub use iter::RangeInclusiveIter;
34#[doc(inline)]
35#[stable(feature = "new_range_api", since = "1.96.0")]
36pub use iter::RangeIter;
37
38use crate::iter::Step;
39use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
42#[doc(inline)]
43#[stable(feature = "new_range_api_exports", since = "CURRENT_RUSTC_VERSION")]
44pub use crate::ops::{RangeFull, RangeTo};
45
46#[lang = "RangeCopy"]
65#[derive(Copy, Hash)]
66#[derive_const(Clone, Default, PartialEq, Eq)]
67#[stable(feature = "new_range_api", since = "1.96.0")]
68pub struct Range<Idx> {
69 #[stable(feature = "new_range_api", since = "1.96.0")]
71 pub start: Idx,
72 #[stable(feature = "new_range_api", since = "1.96.0")]
74 pub end: Idx,
75}
76
77#[stable(feature = "new_range_api", since = "1.96.0")]
78impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
79 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80 self.start.fmt(fmt)?;
81 write!(fmt, "..")?;
82 self.end.fmt(fmt)?;
83 Ok(())
84 }
85}
86
87impl<Idx: Step> Range<Idx> {
88 #[stable(feature = "new_range_api", since = "1.96.0")]
103 #[inline]
104 pub fn iter(&self) -> RangeIter<Idx> {
105 self.clone().into_iter()
106 }
107}
108
109impl<Idx: PartialOrd<Idx>> Range<Idx> {
110 #[inline]
131 #[stable(feature = "new_range_api", since = "1.96.0")]
132 #[rustc_const_unstable(feature = "const_range", issue = "none")]
133 pub const fn contains<U>(&self, item: &U) -> bool
134 where
135 Idx: [const] PartialOrd<U>,
136 U: ?Sized + [const] PartialOrd<Idx>,
137 {
138 <Self as RangeBounds<Idx>>::contains(self, item)
139 }
140
141 #[inline]
163 #[stable(feature = "new_range_api", since = "1.96.0")]
164 #[rustc_const_unstable(feature = "const_range", issue = "none")]
165 pub const fn is_empty(&self) -> bool
166 where
167 Idx: [const] PartialOrd,
168 {
169 !(self.start < self.end)
170 }
171}
172
173#[stable(feature = "new_range_api", since = "1.96.0")]
174#[rustc_const_unstable(feature = "const_range", issue = "none")]
175const impl<T> RangeBounds<T> for Range<T> {
176 fn start_bound(&self) -> Bound<&T> {
177 Included(&self.start)
178 }
179 fn end_bound(&self) -> Bound<&T> {
180 Excluded(&self.end)
181 }
182}
183
184#[stable(feature = "new_range_api", since = "1.96.0")]
191#[rustc_const_unstable(feature = "const_range", issue = "none")]
192const impl<T> RangeBounds<T> for Range<&T> {
193 fn start_bound(&self) -> Bound<&T> {
194 Included(self.start)
195 }
196 fn end_bound(&self) -> Bound<&T> {
197 Excluded(self.end)
198 }
199}
200
201#[unstable(feature = "range_into_bounds", issue = "136903")]
202#[rustc_const_unstable(feature = "const_range", issue = "none")]
203const impl<T> IntoBounds<T> for Range<T> {
204 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
205 (Included(self.start), Excluded(self.end))
206 }
207}
208
209#[stable(feature = "new_range_api", since = "1.96.0")]
210#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
211const impl<T> From<Range<T>> for legacy::Range<T> {
212 #[inline]
213 fn from(value: Range<T>) -> Self {
214 Self { start: value.start, end: value.end }
215 }
216}
217#[stable(feature = "new_range_api", since = "1.96.0")]
218#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
219const impl<T> From<legacy::Range<T>> for Range<T> {
220 #[inline]
221 fn from(value: legacy::Range<T>) -> Self {
222 Self { start: value.start, end: value.end }
223 }
224}
225
226#[lang = "RangeInclusiveCopy"]
245#[derive(Clone, Copy, PartialEq, Eq, Hash)]
246#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
247pub struct RangeInclusive<Idx> {
248 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
250 pub start: Idx,
251 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
253 pub last: Idx,
254}
255
256#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
257impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
258 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
259 self.start.fmt(fmt)?;
260 write!(fmt, "..=")?;
261 self.last.fmt(fmt)?;
262 Ok(())
263 }
264}
265
266impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
267 #[inline]
289 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
290 #[rustc_const_unstable(feature = "const_range", issue = "none")]
291 pub const fn contains<U>(&self, item: &U) -> bool
292 where
293 Idx: [const] PartialOrd<U>,
294 U: ?Sized + [const] PartialOrd<Idx>,
295 {
296 <Self as RangeBounds<Idx>>::contains(self, item)
297 }
298
299 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
321 #[inline]
322 #[rustc_const_unstable(feature = "const_range", issue = "none")]
323 pub const fn is_empty(&self) -> bool
324 where
325 Idx: [const] PartialOrd,
326 {
327 !(self.start <= self.last)
328 }
329}
330
331impl<Idx: Step> RangeInclusive<Idx> {
332 #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
347 #[inline]
348 pub fn iter(&self) -> RangeInclusiveIter<Idx> {
349 self.clone().into_iter()
350 }
351}
352
353#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
354#[rustc_const_unstable(feature = "const_range", issue = "none")]
355const impl<T> RangeBounds<T> for RangeInclusive<T> {
356 fn start_bound(&self) -> Bound<&T> {
357 Included(&self.start)
358 }
359 fn end_bound(&self) -> Bound<&T> {
360 Included(&self.last)
361 }
362}
363
364#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
371#[rustc_const_unstable(feature = "const_range", issue = "none")]
372const impl<T> RangeBounds<T> for RangeInclusive<&T> {
373 fn start_bound(&self) -> Bound<&T> {
374 Included(self.start)
375 }
376 fn end_bound(&self) -> Bound<&T> {
377 Included(self.last)
378 }
379}
380
381#[unstable(feature = "range_into_bounds", issue = "136903")]
383#[rustc_const_unstable(feature = "const_range", issue = "none")]
384const impl<T> IntoBounds<T> for RangeInclusive<T> {
385 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
386 (Included(self.start), Included(self.last))
387 }
388}
389
390#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
391#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
392const impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
393 #[inline]
394 fn from(value: RangeInclusive<T>) -> Self {
395 Self::new(value.start, value.last)
396 }
397}
398#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
399#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
400const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
401 #[inline]
402 fn from(value: legacy::RangeInclusive<T>) -> Self {
403 assert!(
404 !value.exhausted,
405 "attempted to convert from an exhausted `legacy::RangeInclusive` (unspecified behavior)"
406 );
407
408 let (start, last) = value.into_inner();
409 RangeInclusive { start, last }
410 }
411}
412
413#[lang = "RangeFromCopy"]
441#[derive(Copy, Hash)]
442#[derive_const(Clone, PartialEq, Eq)]
443#[stable(feature = "new_range_from_api", since = "1.96.0")]
444pub struct RangeFrom<Idx> {
445 #[stable(feature = "new_range_from_api", since = "1.96.0")]
447 pub start: Idx,
448}
449
450#[stable(feature = "new_range_from_api", since = "1.96.0")]
451impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
452 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
453 self.start.fmt(fmt)?;
454 write!(fmt, "..")?;
455 Ok(())
456 }
457}
458
459impl<Idx: Step> RangeFrom<Idx> {
460 #[stable(feature = "new_range_from_api", since = "1.96.0")]
475 #[inline]
476 pub fn iter(&self) -> RangeFromIter<Idx> {
477 self.clone().into_iter()
478 }
479}
480
481impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
482 #[inline]
498 #[stable(feature = "new_range_from_api", since = "1.96.0")]
499 #[rustc_const_unstable(feature = "const_range", issue = "none")]
500 pub const fn contains<U>(&self, item: &U) -> bool
501 where
502 Idx: [const] PartialOrd<U>,
503 U: ?Sized + [const] PartialOrd<Idx>,
504 {
505 <Self as RangeBounds<Idx>>::contains(self, item)
506 }
507}
508
509#[stable(feature = "new_range_from_api", since = "1.96.0")]
510#[rustc_const_unstable(feature = "const_range", issue = "none")]
511const impl<T> RangeBounds<T> for RangeFrom<T> {
512 fn start_bound(&self) -> Bound<&T> {
513 Included(&self.start)
514 }
515 fn end_bound(&self) -> Bound<&T> {
516 Unbounded
517 }
518}
519
520#[stable(feature = "new_range_from_api", since = "1.96.0")]
527#[rustc_const_unstable(feature = "const_range", issue = "none")]
528const impl<T> RangeBounds<T> for RangeFrom<&T> {
529 fn start_bound(&self) -> Bound<&T> {
530 Included(self.start)
531 }
532 fn end_bound(&self) -> Bound<&T> {
533 Unbounded
534 }
535}
536
537#[unstable(feature = "range_into_bounds", issue = "136903")]
538#[rustc_const_unstable(feature = "const_range", issue = "none")]
539const impl<T> IntoBounds<T> for RangeFrom<T> {
540 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
541 (Included(self.start), Unbounded)
542 }
543}
544
545#[unstable(feature = "one_sided_range", issue = "69780")]
546#[rustc_const_unstable(feature = "const_range", issue = "none")]
547const impl<T> OneSidedRange<T> for RangeFrom<T>
548where
549 Self: RangeBounds<T>,
550{
551 fn bound(self) -> (OneSidedRangeBound, T) {
552 (OneSidedRangeBound::StartInclusive, self.start)
553 }
554}
555
556#[stable(feature = "new_range_from_api", since = "1.96.0")]
557#[rustc_const_unstable(feature = "const_index", issue = "143775")]
558const impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
559 #[inline]
560 fn from(value: RangeFrom<T>) -> Self {
561 Self { start: value.start }
562 }
563}
564#[stable(feature = "new_range_from_api", since = "1.96.0")]
565#[rustc_const_unstable(feature = "const_index", issue = "143775")]
566const impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
567 #[inline]
568 fn from(value: legacy::RangeFrom<T>) -> Self {
569 Self { start: value.start }
570 }
571}
572
573#[lang = "RangeToInclusiveCopy"]
616#[doc(alias = "..=")]
617#[derive(Copy, Clone, PartialEq, Eq, Hash)]
618#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
619pub struct RangeToInclusive<Idx> {
620 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
622 pub last: Idx,
623}
624
625#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
626impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
627 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
628 write!(fmt, "..=")?;
629 self.last.fmt(fmt)?;
630 Ok(())
631 }
632}
633
634impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
635 #[inline]
649 #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
650 #[rustc_const_unstable(feature = "const_range", issue = "none")]
651 pub const fn contains<U>(&self, item: &U) -> bool
652 where
653 Idx: [const] PartialOrd<U>,
654 U: ?Sized + [const] PartialOrd<Idx>,
655 {
656 <Self as RangeBounds<Idx>>::contains(self, item)
657 }
658}
659
660#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
661impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
662 fn from(value: legacy::RangeToInclusive<T>) -> Self {
663 Self { last: value.end }
664 }
665}
666#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
667impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
668 fn from(value: RangeToInclusive<T>) -> Self {
669 Self { end: value.last }
670 }
671}
672
673#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
677#[rustc_const_unstable(feature = "const_range", issue = "none")]
678const impl<T> RangeBounds<T> for RangeToInclusive<T> {
679 fn start_bound(&self) -> Bound<&T> {
680 Unbounded
681 }
682 fn end_bound(&self) -> Bound<&T> {
683 Included(&self.last)
684 }
685}
686
687#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
688#[rustc_const_unstable(feature = "const_range", issue = "none")]
689const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
690 fn start_bound(&self) -> Bound<&T> {
691 Unbounded
692 }
693 fn end_bound(&self) -> Bound<&T> {
694 Included(self.last)
695 }
696}
697
698#[unstable(feature = "range_into_bounds", issue = "136903")]
699#[rustc_const_unstable(feature = "const_range", issue = "none")]
700const impl<T> IntoBounds<T> for RangeToInclusive<T> {
701 fn into_bounds(self) -> (Bound<T>, Bound<T>) {
702 (Unbounded, Included(self.last))
703 }
704}
705
706#[unstable(feature = "one_sided_range", issue = "69780")]
707#[rustc_const_unstable(feature = "const_range", issue = "none")]
708const impl<T> OneSidedRange<T> for RangeToInclusive<T>
709where
710 Self: RangeBounds<T>,
711{
712 fn bound(self) -> (OneSidedRangeBound, T) {
713 (OneSidedRangeBound::EndInclusive, self.last)
714 }
715}