use mem;
use ops::{self, Add, Sub};
use usize;
use super::{FusedIterator, TrustedLen};
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
issue = "27741")]
pub trait Step: PartialOrd + Sized {
fn step(&self, by: &Self) -> Option<Self>;
fn steps_between(start: &Self, end: &Self, by: &Self) -> Option<usize>;
fn steps_between_by_one(start: &Self, end: &Self) -> Option<usize>;
fn is_negative(&self) -> bool;
fn replace_one(&mut self) -> Self;
fn replace_zero(&mut self) -> Self;
fn add_one(&self) -> Self;
fn sub_one(&self) -> Self;
}
macro_rules! step_impl_unsigned {
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
issue = "27741")]
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
(*self).checked_add(*by)
}
#[inline]
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
if *by == 0 { return None; }
if *start < *end {
let diff = (*end - *start) as usize;
let by = *by as usize;
if diff % by > 0 {
Some(diff / by + 1)
} else {
Some(diff / by)
}
} else {
Some(0)
}
}
#[inline]
fn is_negative(&self) -> bool {
false
}
#[inline]
fn replace_one(&mut self) -> Self {
mem::replace(self, 0)
}
#[inline]
fn replace_zero(&mut self) -> Self {
mem::replace(self, 1)
}
#[inline]
fn add_one(&self) -> Self {
Add::add(*self, 1)
}
#[inline]
fn sub_one(&self) -> Self {
Sub::sub(*self, 1)
}
#[inline]
fn steps_between_by_one(start: &Self, end: &Self) -> Option<usize> {
Self::steps_between(start, end, &1)
}
}
)*)
}
macro_rules! step_impl_signed {
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
issue = "27741")]
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
(*self).checked_add(*by)
}
#[inline]
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
if *by == 0 { return None; }
let diff: usize;
let by_u: usize;
if *by > 0 {
if *start >= *end {
return Some(0);
}
diff = (*end as isize).wrapping_sub(*start as isize) as usize;
by_u = *by as usize;
} else {
if *start <= *end {
return Some(0);
}
diff = (*start as isize).wrapping_sub(*end as isize) as usize;
by_u = (*by as isize).wrapping_mul(-1) as usize;
}
if diff % by_u > 0 {
Some(diff / by_u + 1)
} else {
Some(diff / by_u)
}
}
#[inline]
fn is_negative(&self) -> bool {
*self < 0
}
#[inline]
fn replace_one(&mut self) -> Self {
mem::replace(self, 0)
}
#[inline]
fn replace_zero(&mut self) -> Self {
mem::replace(self, 1)
}
#[inline]
fn add_one(&self) -> Self {
Add::add(*self, 1)
}
#[inline]
fn sub_one(&self) -> Self {
Sub::sub(*self, 1)
}
#[inline]
fn steps_between_by_one(start: &Self, end: &Self) -> Option<usize> {
Self::steps_between(start, end, &1)
}
}
)*)
}
macro_rules! step_impl_no_between {
($($t:ty)*) => ($(
#[unstable(feature = "step_trait",
reason = "likely to be replaced by finer-grained traits",
issue = "27741")]
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
(*self).checked_add(*by)
}
#[inline]
fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option<usize> {
None
}
#[inline]
#[allow(unused_comparisons)]
fn is_negative(&self) -> bool {
*self < 0
}
#[inline]
fn replace_one(&mut self) -> Self {
mem::replace(self, 0)
}
#[inline]
fn replace_zero(&mut self) -> Self {
mem::replace(self, 1)
}
#[inline]
fn add_one(&self) -> Self {
Add::add(*self, 1)
}
#[inline]
fn sub_one(&self) -> Self {
Sub::sub(*self, 1)
}
#[inline]
fn steps_between_by_one(start: &Self, end: &Self) -> Option<usize> {
Self::steps_between(start, end, &1)
}
}
)*)
}
step_impl_unsigned!(usize u8 u16 u32);
step_impl_signed!(isize i8 i16 i32);
#[cfg(target_pointer_width = "64")]
step_impl_unsigned!(u64);
#[cfg(target_pointer_width = "64")]
step_impl_signed!(i64);
#[cfg(not(target_pointer_width = "64"))]
step_impl_no_between!(u64 i64);
#[derive(Clone, Debug)]
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
pub struct StepBy<A, R> {
step_by: A,
range: R,
}
impl<A: Step> ops::RangeFrom<A> {
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
pub fn step_by(self, by: A) -> StepBy<A, Self> {
StepBy {
step_by: by,
range: self
}
}
}
impl<A: Step> ops::Range<A> {
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
pub fn step_by(self, by: A) -> StepBy<A, Self> {
StepBy {
step_by: by,
range: self
}
}
}
impl<A: Step> ops::RangeInclusive<A> {
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
pub fn step_by(self, by: A) -> StepBy<A, Self> {
StepBy {
step_by: by,
range: self
}
}
}
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where
A: Clone,
for<'a> &'a A: Add<&'a A, Output = A>
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
let mut n = &self.range.start + &self.step_by;
mem::swap(&mut n, &mut self.range.start);
Some(n)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::MAX, None) }
}
#[unstable(feature = "fused", issue = "35602")]
impl<A> FusedIterator for StepBy<A, ops::RangeFrom<A>>
where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {}
#[unstable(feature = "step_by", reason = "recent addition",
issue = "27741")]
impl<A: Step + Clone> Iterator for StepBy<A, ops::Range<A>> {
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
let rev = self.step_by.is_negative();
if (rev && self.range.start > self.range.end) ||
(!rev && self.range.start < self.range.end)
{
match self.range.start.step(&self.step_by) {
Some(mut n) => {
mem::swap(&mut self.range.start, &mut n);
Some(n)
},
None => {
let mut n = self.range.end.clone();
mem::swap(&mut self.range.start, &mut n);
Some(n)
}
}
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match Step::steps_between(&self.range.start,
&self.range.end,
&self.step_by) {
Some(hint) => (hint, Some(hint)),
None => (0, None)
}
}
}
#[unstable(feature = "fused", issue = "35602")]
impl<A: Step + Clone> FusedIterator for StepBy<A, ops::Range<A>> {}
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
impl<A: Step + Clone> Iterator for StepBy<A, ops::RangeInclusive<A>> {
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
use ops::RangeInclusive::*;
let (finishing, n) = match self.range {
Empty { .. } => return None,
NonEmpty { ref mut start, ref mut end } => {
let rev = self.step_by.is_negative();
if (rev && start >= end) ||
(!rev && start <= end)
{
match start.step(&self.step_by) {
Some(mut n) => {
mem::swap(start, &mut n);
(None, Some(n)) },
None => {
let mut n = end.clone();
mem::swap(start, &mut n);
(None, Some(n)) }
}
} else {
(Some(end.replace_zero()), None)
}
}
};
if let Some(end) = finishing {
self.range = Empty { at: end };
}
n
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
use ops::RangeInclusive::*;
match self.range {
Empty { .. } => (0, Some(0)),
NonEmpty { ref start, ref end } =>
match Step::steps_between(start,
end,
&self.step_by) {
Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
None => (0, None)
}
}
}
}
#[unstable(feature = "fused", issue = "35602")]
impl<A: Step + Clone> FusedIterator for StepBy<A, ops::RangeInclusive<A>> {}
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
impl ExactSizeIterator for ops::Range<$t> { }
)*)
}
macro_rules! range_incl_exact_iter_impl {
($($t:ty)*) => ($(
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
impl ExactSizeIterator for ops::RangeInclusive<$t> { }
)*)
}
macro_rules! range_trusted_len_impl {
($($t:ty)*) => ($(
#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl TrustedLen for ops::Range<$t> { }
)*)
}
macro_rules! range_incl_trusted_len_impl {
($($t:ty)*) => ($(
#[unstable(feature = "inclusive_range",
reason = "recently added, follows RFC",
issue = "28237")]
unsafe impl TrustedLen for ops::RangeInclusive<$t> { }
)*)
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> Iterator for ops::Range<A> where
for<'a> &'a A: Add<&'a A, Output = A>
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
if self.start < self.end {
let mut n = self.start.add_one();
mem::swap(&mut n, &mut self.start);
Some(n)
} else {
None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
match Step::steps_between_by_one(&self.start, &self.end) {
Some(hint) => (hint, Some(hint)),
None => (0, None)
}
}
}
range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
range_incl_exact_iter_impl!(u8 u16 i8 i16);
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step + Clone> DoubleEndedIterator for ops::Range<A> where
for<'a> &'a A: Add<&'a A, Output = A>,
for<'a> &'a A: Sub<&'a A, Output = A>
{
#[inline]
fn next_back(&mut self) -> Option<A> {
if self.start < self.end {
self.end = self.end.sub_one();
Some(self.end.clone())
} else {
None
}
}
}
#[unstable(feature = "fused", issue = "35602")]
impl<A> FusedIterator for ops::Range<A>
where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> Iterator for ops::RangeFrom<A> where
for<'a> &'a A: Add<&'a A, Output = A>
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
let mut n = self.start.add_one();
mem::swap(&mut n, &mut self.start);
Some(n)
}
}
#[unstable(feature = "fused", issue = "35602")]
impl<A> FusedIterator for ops::RangeFrom<A>
where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<A: Step> Iterator for ops::RangeInclusive<A> where
for<'a> &'a A: Add<&'a A, Output = A>
{
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
use ops::RangeInclusive::*;
let (finishing, n) = match *self {
Empty { .. } => (None, None),
NonEmpty { ref mut start, ref mut end } => {
if start == end {
(Some(end.replace_one()), Some(start.replace_one()))
} else if start < end {
let mut n = start.add_one();
mem::swap(&mut n, start);
(if n == *end { Some(end.replace_one()) } else { None },
Some(n)) } else {
(Some(start.replace_one()), None)
}
}
};
if let Some(end) = finishing {
*self = Empty { at: end };
}
n
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
use ops::RangeInclusive::*;
match *self {
Empty { .. } => (0, Some(0)),
NonEmpty { ref start, ref end } =>
match Step::steps_between_by_one(start, end) {
Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
None => (0, None),
}
}
}
}
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> where
for<'a> &'a A: Add<&'a A, Output = A>,
for<'a> &'a A: Sub<&'a A, Output = A>
{
#[inline]
fn next_back(&mut self) -> Option<A> {
use ops::RangeInclusive::*;
let (finishing, n) = match *self {
Empty { .. } => return None,
NonEmpty { ref mut start, ref mut end } => {
if start == end {
(Some(start.replace_one()), Some(end.replace_one()))
} else if start < end {
let mut n = end.sub_one();
mem::swap(&mut n, end);
(if n == *start { Some(start.replace_one()) } else { None },
Some(n))
} else {
(Some(end.replace_one()), None)
}
}
};
if let Some(start) = finishing {
*self = Empty { at: start };
}
n
}
}
#[unstable(feature = "fused", issue = "35602")]
impl<A> FusedIterator for ops::RangeInclusive<A>
where A: Step, for<'a> &'a A: Add<&'a A, Output = A> {}