1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
//! A `RangeInclusive` implementation that offers a separate iterator type.
//!
//! This `RangeInclusive` does not directly implement the `Iterator` trait,
//! allowing one to iterate over a copy of the range without mutating the original range.
//! This is accomplished by requiring that the generic type `Idx` implements `Clone`;
//! in the future we can remove this trait bound by using references, though most users
//! of a range type typically do so with numeric types that are cheap to copy/clone.
//!
//! All behavior except iteration matches that of `std::ops::RangeInclusive`.
//! Due to the iterator behavior, there is no need to waste space tracking
//! whether the range has been `exhausted`, meaning that this `RangeInclusive`
//! is exactly the size of its two bounds.
#![no_std]
#![feature(step_trait)]
#[cfg(test)]
mod test;
use core::fmt;
use core::iter::Step;
use core::ops::{RangeBounds, Bound, Bound::Included};
/// A range bounded inclusively below and above (`start..=end`).
///
/// The `RangeInclusive` `start..=end` contains all values with `x >= start`
/// and `x <= end`. It is empty unless `start <= end`.
///
/// See the crate-level docs for more information.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct RangeInclusive<Idx: Clone + PartialOrd> {
pub(crate) start: Idx,
pub(crate) end: Idx
}
impl<Idx: Clone + PartialOrd + fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}..={:?}", self.start, self.end)
}
}
impl<Idx: Clone + PartialOrd> RangeInclusive<Idx> {
/// Creates a new inclusive range.
#[inline]
pub const fn new(start: Idx, end: Idx) -> Self {
Self{ start, end }
}
/// Returns the lower bound of the range (inclusive).
#[inline]
pub const fn start(&self) -> &Idx {
&self.start
}
/// Returns the upper bound of the range (inclusive).
#[inline]
pub const fn end(&self) -> &Idx {
&self.end
}
/// Destructures the `RangeInclusive` into (lower bound, upper (inclusive) bound).
#[inline]
pub fn into_inner(self) -> (Idx, Idx) {
(self.start, self.end)
}
/// Returns `true` if the range contains no items.
pub fn is_empty(&self) -> bool {
!(self.start <= self.end)
}
/// Returns an iterator with the same `start` and `end` values as the range.
pub fn iter(&self) -> RangeInclusiveIterator<Idx> {
RangeInclusiveIterator { current: self.start.clone(), end: self.end.clone() }
}
/// Returns `true` if `item` is contained in the range.
pub fn contains<U>(&self, item: &U) -> bool
where
Idx: PartialOrd<U>,
U: ?Sized + PartialOrd<Idx>,
{
<Self as RangeBounds<Idx>>::contains(self, item)
}
}
impl<T: Clone + PartialOrd> RangeBounds<T> for RangeInclusive<T> {
fn start_bound(&self) -> Bound<&T> {
Included(&self.start)
}
fn end_bound(&self) -> Bound<&T> {
Included(&self.end)
}
}
impl<'a, Idx: Clone + PartialOrd + Step> IntoIterator for &'a RangeInclusive<Idx> {
type Item = Idx;
type IntoIter = RangeInclusiveIterator<Idx>;
fn into_iter(self) -> RangeInclusiveIterator<Idx> {
self.iter()
}
}
/// An iterator for the `RangeInclusive` type.
///
/// By creating a separate iterator, the original range is not mutated.
pub struct RangeInclusiveIterator<Idx> {
/// The current value of the iterator which is returned by `next()`.
current: Idx,
/// The end value of the iterator.
end: Idx
}
impl<A: Step> Iterator for RangeInclusiveIterator<A> {
type Item = A;
fn next(&mut self) -> Option<Self::Item> {
if self.current > self.end {
None
} else {
let n = Step::forward_checked(self.current.clone(), 1).expect("`Step` invariants not upheld");
Some(core::mem::replace(&mut self.current, n))
}
}
}
impl<A: Step> ExactSizeIterator for RangeInclusiveIterator<A> {
fn len(&self) -> usize {
Step::steps_between(&self.current, &self.end).map(|x| x+1).unwrap_or(0)
}
}
impl<A: Step> DoubleEndedIterator for RangeInclusiveIterator<A> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.current > self.end {
None
} else {
let n = Step::backward_checked(self.end.clone(), 1).expect("`Step` invariants not upheld");
Some(core::mem::replace(&mut self.end, n))
}
}
}