summaryrefslogtreecommitdiffstats
path: root/third_party/rust/num-iter/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/num-iter/src
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/num-iter/src')
-rw-r--r--third_party/rust/num-iter/src/lib.rs537
1 files changed, 537 insertions, 0 deletions
diff --git a/third_party/rust/num-iter/src/lib.rs b/third_party/rust/num-iter/src/lib.rs
new file mode 100644
index 0000000000..9c96b6e6f6
--- /dev/null
+++ b/third_party/rust/num-iter/src/lib.rs
@@ -0,0 +1,537 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! External iterators for generic mathematics
+//!
+//! ## Compatibility
+//!
+//! The `num-iter` crate is tested for rustc 1.8 and greater.
+
+#![doc(html_root_url = "https://docs.rs/num-iter/0.1")]
+#![no_std]
+#[cfg(feature = "std")]
+extern crate std;
+
+extern crate num_integer as integer;
+extern crate num_traits as traits;
+
+use core::ops::{Add, Sub};
+use core::usize;
+use integer::Integer;
+use traits::{CheckedAdd, One, ToPrimitive, Zero};
+
+/// An iterator over the range [start, stop)
+#[derive(Clone)]
+pub struct Range<A> {
+ state: A,
+ stop: A,
+ one: A,
+}
+
+/// Returns an iterator over the given range [start, stop) (that is, starting
+/// at start (inclusive), and ending at stop (exclusive)).
+///
+/// # Example
+///
+/// ```rust
+/// let array = [0, 1, 2, 3, 4];
+///
+/// for i in num_iter::range(0, 5) {
+/// println!("{}", i);
+/// assert_eq!(i, array[i]);
+/// }
+/// ```
+#[inline]
+pub fn range<A>(start: A, stop: A) -> Range<A>
+where
+ A: Add<A, Output = A> + PartialOrd + Clone + One,
+{
+ Range {
+ state: start,
+ stop: stop,
+ one: One::one(),
+ }
+}
+
+#[inline]
+#[cfg(has_i128)]
+fn unsigned<T: ToPrimitive>(x: &T) -> Option<u128> {
+ match x.to_u128() {
+ None => match x.to_i128() {
+ Some(i) => Some(i as u128),
+ None => None,
+ },
+ Some(u) => Some(u),
+ }
+}
+
+#[inline]
+#[cfg(not(has_i128))]
+fn unsigned<T: ToPrimitive>(x: &T) -> Option<u64> {
+ match x.to_u64() {
+ None => match x.to_i64() {
+ Some(i) => Some(i as u64),
+ None => None,
+ },
+ Some(u) => Some(u),
+ }
+}
+
+// FIXME: rust-lang/rust#10414: Unfortunate type bound
+impl<A> Iterator for Range<A>
+where
+ A: Add<A, Output = A> + PartialOrd + Clone + ToPrimitive,
+{
+ type Item = A;
+
+ #[inline]
+ fn next(&mut self) -> Option<A> {
+ if self.state < self.stop {
+ let result = self.state.clone();
+ self.state = self.state.clone() + self.one.clone();
+ Some(result)
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ // Check for empty ranges first.
+ if self.state >= self.stop {
+ return (0, Some(0));
+ }
+
+ // Try to cast both ends to the largest unsigned primitive.
+ // Note that negative values will wrap to a large positive.
+ if let Some(a) = unsigned(&self.state) {
+ if let Some(b) = unsigned(&self.stop) {
+ // We've lost signs, but we already know state < stop, so
+ // a `wrapping_sub` will give the correct unsigned delta.
+ return match b.wrapping_sub(a).to_usize() {
+ Some(len) => (len, Some(len)),
+ None => (usize::MAX, None),
+ };
+ }
+ }
+
+ // Standard fallback for unbounded/unrepresentable bounds
+ (0, None)
+ }
+}
+
+/// `Integer` is required to ensure the range will be the same regardless of
+/// the direction it is consumed.
+impl<A> DoubleEndedIterator for Range<A>
+where
+ A: Integer + Clone + ToPrimitive,
+{
+ #[inline]
+ fn next_back(&mut self) -> Option<A> {
+ if self.stop > self.state {
+ self.stop = self.stop.clone() - self.one.clone();
+ Some(self.stop.clone())
+ } else {
+ None
+ }
+ }
+}
+
+/// An iterator over the range [start, stop]
+#[derive(Clone)]
+pub struct RangeInclusive<A> {
+ range: Range<A>,
+ done: bool,
+}
+
+/// Return an iterator over the range [start, stop]
+#[inline]
+pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
+where
+ A: Add<A, Output = A> + PartialOrd + Clone + One,
+{
+ RangeInclusive {
+ range: range(start, stop),
+ done: false,
+ }
+}
+
+impl<A> Iterator for RangeInclusive<A>
+where
+ A: Add<A, Output = A> + PartialOrd + Clone + ToPrimitive,
+{
+ type Item = A;
+
+ #[inline]
+ fn next(&mut self) -> Option<A> {
+ match self.range.next() {
+ Some(x) => Some(x),
+ None => {
+ if !self.done && self.range.state == self.range.stop {
+ self.done = true;
+ Some(self.range.stop.clone())
+ } else {
+ None
+ }
+ }
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (lo, hi) = self.range.size_hint();
+ if self.done {
+ (lo, hi)
+ } else {
+ let lo = lo.saturating_add(1);
+ let hi = match hi {
+ Some(x) => x.checked_add(1),
+ None => None,
+ };
+ (lo, hi)
+ }
+ }
+}
+
+impl<A> DoubleEndedIterator for RangeInclusive<A>
+where
+ A: Sub<A, Output = A> + Integer + Clone + ToPrimitive,
+{
+ #[inline]
+ fn next_back(&mut self) -> Option<A> {
+ if self.range.stop > self.range.state {
+ let result = self.range.stop.clone();
+ self.range.stop = self.range.stop.clone() - self.range.one.clone();
+ Some(result)
+ } else if !self.done && self.range.state == self.range.stop {
+ self.done = true;
+ Some(self.range.stop.clone())
+ } else {
+ None
+ }
+ }
+}
+
+/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
+#[derive(Clone)]
+pub struct RangeStep<A> {
+ state: A,
+ stop: A,
+ step: A,
+ rev: bool,
+}
+
+/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
+#[inline]
+pub fn range_step<A>(start: A, stop: A, step: A) -> RangeStep<A>
+where
+ A: CheckedAdd + PartialOrd + Clone + Zero,
+{
+ let rev = step < Zero::zero();
+ RangeStep {
+ state: start,
+ stop: stop,
+ step: step,
+ rev: rev,
+ }
+}
+
+impl<A> Iterator for RangeStep<A>
+where
+ A: CheckedAdd + PartialOrd + Clone,
+{
+ type Item = A;
+
+ #[inline]
+ fn next(&mut self) -> Option<A> {
+ if (self.rev && self.state > self.stop) || (!self.rev && self.state < self.stop) {
+ let result = self.state.clone();
+ match self.state.checked_add(&self.step) {
+ Some(x) => self.state = x,
+ None => self.state = self.stop.clone(),
+ }
+ Some(result)
+ } else {
+ None
+ }
+ }
+}
+
+/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
+#[derive(Clone)]
+pub struct RangeStepInclusive<A> {
+ state: A,
+ stop: A,
+ step: A,
+ rev: bool,
+ done: bool,
+}
+
+/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
+#[inline]
+pub fn range_step_inclusive<A>(start: A, stop: A, step: A) -> RangeStepInclusive<A>
+where
+ A: CheckedAdd + PartialOrd + Clone + Zero,
+{
+ let rev = step < Zero::zero();
+ RangeStepInclusive {
+ state: start,
+ stop: stop,
+ step: step,
+ rev: rev,
+ done: false,
+ }
+}
+
+impl<A> Iterator for RangeStepInclusive<A>
+where
+ A: CheckedAdd + PartialOrd + Clone + PartialEq,
+{
+ type Item = A;
+
+ #[inline]
+ fn next(&mut self) -> Option<A> {
+ if !self.done
+ && ((self.rev && self.state >= self.stop) || (!self.rev && self.state <= self.stop))
+ {
+ let result = self.state.clone();
+ match self.state.checked_add(&self.step) {
+ Some(x) => self.state = x,
+ None => self.done = true,
+ }
+ Some(result)
+ } else {
+ None
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use core::cmp::Ordering;
+ use core::iter;
+ use core::ops::{Add, Mul};
+ use core::{isize, usize};
+ use traits::{One, ToPrimitive};
+
+ #[test]
+ fn test_range() {
+ /// A mock type to check Range when ToPrimitive returns None
+ struct Foo;
+
+ impl ToPrimitive for Foo {
+ fn to_i64(&self) -> Option<i64> {
+ None
+ }
+ fn to_u64(&self) -> Option<u64> {
+ None
+ }
+ }
+
+ impl Add<Foo> for Foo {
+ type Output = Foo;
+
+ fn add(self, _: Foo) -> Foo {
+ Foo
+ }
+ }
+
+ impl PartialEq for Foo {
+ fn eq(&self, _: &Foo) -> bool {
+ true
+ }
+ }
+
+ impl PartialOrd for Foo {
+ fn partial_cmp(&self, _: &Foo) -> Option<Ordering> {
+ None
+ }
+ }
+
+ impl Clone for Foo {
+ fn clone(&self) -> Foo {
+ Foo
+ }
+ }
+
+ impl Mul<Foo> for Foo {
+ type Output = Foo;
+
+ fn mul(self, _: Foo) -> Foo {
+ Foo
+ }
+ }
+
+ impl One for Foo {
+ fn one() -> Foo {
+ Foo
+ }
+ }
+
+ assert!(super::range(0, 5).eq([0, 1, 2, 3, 4].iter().cloned()));
+ assert!(super::range(-10, -1).eq([-10, -9, -8, -7, -6, -5, -4, -3, -2].iter().cloned()));
+ assert!(super::range(0, 5).rev().eq([4, 3, 2, 1, 0].iter().cloned()));
+ assert_eq!(super::range(200, -5).count(), 0);
+ assert_eq!(super::range(200, -5).rev().count(), 0);
+ assert_eq!(super::range(200, 200).count(), 0);
+ assert_eq!(super::range(200, 200).rev().count(), 0);
+
+ assert_eq!(super::range(0, 100).size_hint(), (100, Some(100)));
+ // this test is only meaningful when sizeof usize < sizeof u64
+ assert_eq!(
+ super::range(usize::MAX - 1, usize::MAX).size_hint(),
+ (1, Some(1))
+ );
+ assert_eq!(super::range(-10, -1).size_hint(), (9, Some(9)));
+ assert_eq!(
+ super::range(isize::MIN, isize::MAX).size_hint(),
+ (usize::MAX, Some(usize::MAX))
+ );
+ }
+
+ #[test]
+ #[cfg(has_i128)]
+ fn test_range_128() {
+ use core::{i128, u128};
+
+ assert!(super::range(0i128, 5).eq([0, 1, 2, 3, 4].iter().cloned()));
+ assert!(super::range(-10i128, -1).eq([-10, -9, -8, -7, -6, -5, -4, -3, -2].iter().cloned()));
+ assert!(super::range(0u128, 5)
+ .rev()
+ .eq([4, 3, 2, 1, 0].iter().cloned()));
+
+ assert_eq!(
+ super::range(i128::MIN, i128::MIN + 1).size_hint(),
+ (1, Some(1))
+ );
+ assert_eq!(
+ super::range(i128::MAX - 1, i128::MAX).size_hint(),
+ (1, Some(1))
+ );
+ assert_eq!(
+ super::range(i128::MIN, i128::MAX).size_hint(),
+ (usize::MAX, None)
+ );
+
+ assert_eq!(
+ super::range(u128::MAX - 1, u128::MAX).size_hint(),
+ (1, Some(1))
+ );
+ assert_eq!(
+ super::range(0, usize::MAX as u128).size_hint(),
+ (usize::MAX, Some(usize::MAX))
+ );
+ assert_eq!(
+ super::range(0, usize::MAX as u128 + 1).size_hint(),
+ (usize::MAX, None)
+ );
+ assert_eq!(super::range(0, i128::MAX).size_hint(), (usize::MAX, None));
+ }
+
+ #[test]
+ fn test_range_inclusive() {
+ assert!(super::range_inclusive(0, 5).eq([0, 1, 2, 3, 4, 5].iter().cloned()));
+ assert!(super::range_inclusive(0, 5)
+ .rev()
+ .eq([5, 4, 3, 2, 1, 0].iter().cloned()));
+ assert_eq!(super::range_inclusive(200, -5).count(), 0);
+ assert_eq!(super::range_inclusive(200, -5).rev().count(), 0);
+ assert!(super::range_inclusive(200, 200).eq(iter::once(200)));
+ assert!(super::range_inclusive(200, 200).rev().eq(iter::once(200)));
+ assert_eq!(
+ super::range_inclusive(isize::MIN, isize::MAX - 1).size_hint(),
+ (usize::MAX, Some(usize::MAX))
+ );
+ assert_eq!(
+ super::range_inclusive(isize::MIN, isize::MAX).size_hint(),
+ (usize::MAX, None)
+ );
+ }
+
+ #[test]
+ #[cfg(has_i128)]
+ fn test_range_inclusive_128() {
+ use core::i128;
+
+ assert!(super::range_inclusive(0u128, 5).eq([0, 1, 2, 3, 4, 5].iter().cloned()));
+ assert!(super::range_inclusive(0u128, 5)
+ .rev()
+ .eq([5, 4, 3, 2, 1, 0].iter().cloned()));
+ assert_eq!(super::range_inclusive(200i128, -5).count(), 0);
+ assert_eq!(super::range_inclusive(200i128, -5).rev().count(), 0);
+ assert!(super::range_inclusive(200u128, 200).eq(iter::once(200)));
+ assert!(super::range_inclusive(200u128, 200)
+ .rev()
+ .eq(iter::once(200)));
+ assert_eq!(
+ super::range_inclusive(isize::MIN as i128, isize::MAX as i128 - 1).size_hint(),
+ (usize::MAX, Some(usize::MAX))
+ );
+ assert_eq!(
+ super::range_inclusive(isize::MIN as i128, isize::MAX as i128).size_hint(),
+ (usize::MAX, None)
+ );
+ assert_eq!(
+ super::range_inclusive(isize::MIN as i128, isize::MAX as i128 + 1).size_hint(),
+ (usize::MAX, None)
+ );
+ assert_eq!(
+ super::range_inclusive(i128::MIN, i128::MAX).size_hint(),
+ (usize::MAX, None)
+ );
+ }
+
+ #[test]
+ fn test_range_step() {
+ assert!(super::range_step(0, 20, 5).eq([0, 5, 10, 15].iter().cloned()));
+ assert!(super::range_step(20, 0, -5).eq([20, 15, 10, 5].iter().cloned()));
+ assert!(super::range_step(20, 0, -6).eq([20, 14, 8, 2].iter().cloned()));
+ assert!(super::range_step(200u8, 255, 50).eq([200u8, 250].iter().cloned()));
+ assert!(super::range_step(200, -5, 1).eq(iter::empty()));
+ assert!(super::range_step(200, 200, 1).eq(iter::empty()));
+ }
+
+ #[test]
+ #[cfg(has_i128)]
+ fn test_range_step_128() {
+ use core::u128::MAX as UMAX;
+
+ assert!(super::range_step(0u128, 20, 5).eq([0, 5, 10, 15].iter().cloned()));
+ assert!(super::range_step(20i128, 0, -5).eq([20, 15, 10, 5].iter().cloned()));
+ assert!(super::range_step(20i128, 0, -6).eq([20, 14, 8, 2].iter().cloned()));
+ assert!(super::range_step(UMAX - 55, UMAX, 50).eq([UMAX - 55, UMAX - 5].iter().cloned()));
+ assert!(super::range_step(200i128, -5, 1).eq(iter::empty()));
+ assert!(super::range_step(200i128, 200, 1).eq(iter::empty()));
+ }
+
+ #[test]
+ fn test_range_step_inclusive() {
+ assert!(super::range_step_inclusive(0, 20, 5).eq([0, 5, 10, 15, 20].iter().cloned()));
+ assert!(super::range_step_inclusive(20, 0, -5).eq([20, 15, 10, 5, 0].iter().cloned()));
+ assert!(super::range_step_inclusive(20, 0, -6).eq([20, 14, 8, 2].iter().cloned()));
+ assert!(super::range_step_inclusive(200u8, 255, 50).eq([200u8, 250].iter().cloned()));
+ assert!(super::range_step_inclusive(200, -5, 1).eq(iter::empty()));
+ assert!(super::range_step_inclusive(200, 200, 1).eq(iter::once(200)));
+ }
+
+ #[test]
+ #[cfg(has_i128)]
+ fn test_range_step_inclusive_128() {
+ use core::u128::MAX as UMAX;
+
+ assert!(super::range_step_inclusive(0u128, 20, 5).eq([0, 5, 10, 15, 20].iter().cloned()));
+ assert!(super::range_step_inclusive(20i128, 0, -5).eq([20, 15, 10, 5, 0].iter().cloned()));
+ assert!(super::range_step_inclusive(20i128, 0, -6).eq([20, 14, 8, 2].iter().cloned()));
+ assert!(super::range_step_inclusive(UMAX - 55, UMAX, 50)
+ .eq([UMAX - 55, UMAX - 5].iter().cloned()));
+ assert!(super::range_step_inclusive(200i128, -5, 1).eq(iter::empty()));
+ assert!(super::range_step_inclusive(200i128, 200, 1).eq(iter::once(200)));
+ }
+}