Skip to content

Commit bb5f624

Browse files
committed
Merged upstream
2 parents 8be9300 + a2b3aef commit bb5f624

32 files changed

+386
-223
lines changed

.travis.yml

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,28 @@ language: rust
22
sudo: false
33
matrix:
44
include:
5-
- rust: 1.32.0
5+
- rust: 1.36.0
66
script:
77
- |
88
cargo build --verbose --no-default-features &&
9+
cargo build --verbose --no-default-features --features "use_alloc" &&
910
cargo build --verbose --features "$FEATURES"
1011
- rust: stable
1112
script:
1213
- |
1314
cargo build --verbose --no-default-features &&
15+
cargo build --verbose --no-default-features --features "use_alloc" &&
1416
cargo build --verbose --features "$FEATURES" &&
1517
cargo test --verbose --features "$FEATURES" &&
1618
cargo bench --no-run --verbose --features "$FEATURES"
1719
- rust: beta
1820
script:
1921
- |
2022
cargo build --verbose --no-default-features &&
23+
cargo build --verbose --no-default-features --features "use_alloc" &&
2124
cargo build --verbose --features "$FEATURES" &&
2225
cargo test --verbose --features "$FEATURES" &&
2326
cargo bench --no-run --verbose --features "$FEATURES"
24-
- rust: nightly
25-
script:
26-
- |
27-
cargo build --verbose --no-default-features &&
28-
cargo build --verbose --features "$FEATURES" &&
29-
cargo test --verbose --features "$FEATURES" &&
30-
cargo bench --no-run --verbose --features "$FEATURES"
31-
cache: cargo # https://docs.travis-ci.com/user/languages/rust/#dependency-management
3227
branches:
3328
only:
3429
- master

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ version = "0.2"
3838

3939
[features]
4040
default = ["use_std"]
41-
use_std = []
41+
use_std = ["use_alloc"]
42+
use_alloc = []
4243

4344
[profile]
4445
bench = { debug = true }

src/adaptors/map.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ where
6868
pub type MapOk<I, F> = MapSpecialCase<I, MapSpecialCaseFnOk<F>>;
6969

7070
/// See [`MapOk`](struct.MapOk.html).
71-
#[deprecated(note = "Use MapOk instead", since = "0.10")]
71+
#[deprecated(note = "Use MapOk instead", since = "0.10.0")]
7272
pub type MapResults<I, F> = MapOk<I, F>;
7373

7474
impl<F, T, U, E> MapSpecialCaseFn<Result<T, E>> for MapSpecialCaseFnOk<F>

src/adaptors/mod.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use self::coalesce::*;
1111
pub use self::map::{map_into, map_ok, MapInto, MapOk};
1212
#[allow(deprecated)]
1313
pub use self::map::MapResults;
14-
#[cfg(feature = "use_std")]
14+
#[cfg(feature = "use_alloc")]
1515
pub use self::multi_product::*;
1616

1717
use std::fmt;
@@ -113,22 +113,11 @@ impl<I, J> Iterator for InterleaveShortest<I, J>
113113

114114
#[inline]
115115
fn next(&mut self) -> Option<Self::Item> {
116-
match self.phase {
117-
false => match self.it0.next() {
118-
None => None,
119-
e => {
120-
self.phase = true;
121-
e
122-
}
123-
},
124-
true => match self.it1.next() {
125-
None => None,
126-
e => {
127-
self.phase = false;
128-
e
129-
}
130-
},
116+
let e = if self.phase { self.it1.next() } else { self.it0.next() };
117+
if e.is_some() {
118+
self.phase = !self.phase;
131119
}
120+
e
132121
}
133122

134123
#[inline]
@@ -412,7 +401,7 @@ impl<B, F, I> Iterator for Batching<I, F>
412401
/// then skipping forward *n-1* elements.
413402
///
414403
/// See [`.step()`](../trait.Itertools.html#method.step) for more information.
415-
#[deprecated(note="Use std .step_by() instead", since="0.8")]
404+
#[deprecated(note="Use std .step_by() instead", since="0.8.0")]
416405
#[allow(deprecated)]
417406
#[derive(Clone, Debug)]
418407
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
@@ -806,9 +795,30 @@ macro_rules! impl_tuple_combination {
806795
)
807796
}
808797

809-
impl_tuple_combination!(Tuple2Combination Tuple1Combination ; A, A, A ; a);
810-
impl_tuple_combination!(Tuple3Combination Tuple2Combination ; A, A, A, A ; a b);
811-
impl_tuple_combination!(Tuple4Combination Tuple3Combination ; A, A, A, A, A; a b c);
798+
// This snippet generates the twelve `impl_tuple_combination!` invocations:
799+
// use core::iter;
800+
// use itertools::Itertools;
801+
//
802+
// for i in 2..=12 {
803+
// println!("impl_tuple_combination!(Tuple{arity}Combination Tuple{prev}Combination; {tys}; {idents});",
804+
// arity = i,
805+
// prev = i - 1,
806+
// tys = iter::repeat("A").take(i + 1).join(", "),
807+
// idents = ('a'..'z').take(i - 1).join(" "),
808+
// );
809+
// }
810+
// It could probably be replaced by a bit more macro cleverness.
811+
impl_tuple_combination!(Tuple2Combination Tuple1Combination; A, A, A; a);
812+
impl_tuple_combination!(Tuple3Combination Tuple2Combination; A, A, A, A; a b);
813+
impl_tuple_combination!(Tuple4Combination Tuple3Combination; A, A, A, A, A; a b c);
814+
impl_tuple_combination!(Tuple5Combination Tuple4Combination; A, A, A, A, A, A; a b c d);
815+
impl_tuple_combination!(Tuple6Combination Tuple5Combination; A, A, A, A, A, A, A; a b c d e);
816+
impl_tuple_combination!(Tuple7Combination Tuple6Combination; A, A, A, A, A, A, A, A; a b c d e f);
817+
impl_tuple_combination!(Tuple8Combination Tuple7Combination; A, A, A, A, A, A, A, A, A; a b c d e f g);
818+
impl_tuple_combination!(Tuple9Combination Tuple8Combination; A, A, A, A, A, A, A, A, A, A; a b c d e f g h);
819+
impl_tuple_combination!(Tuple10Combination Tuple9Combination; A, A, A, A, A, A, A, A, A, A, A; a b c d e f g h i);
820+
impl_tuple_combination!(Tuple11Combination Tuple10Combination; A, A, A, A, A, A, A, A, A, A, A, A; a b c d e f g h i j);
821+
impl_tuple_combination!(Tuple12Combination Tuple11Combination; A, A, A, A, A, A, A, A, A, A, A, A, A; a b c d e f g h i j k);
812822

813823
/// An iterator adapter to filter values within a nested `Result::Ok`.
814824
///

src/adaptors/multi_product.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
#![cfg(feature = "use_std")]
1+
#![cfg(feature = "use_alloc")]
22

33
use crate::size_hint;
44
use crate::Itertools;
55

6+
use alloc::vec::Vec;
7+
68
#[derive(Clone)]
79
/// An iterator adaptor that iterates over the cartesian product of
810
/// multiple iterators of type `I`.
@@ -161,7 +163,7 @@ impl<I> Iterator for MultiProduct<I>
161163
}
162164

163165
fn count(self) -> usize {
164-
if self.0.len() == 0 {
166+
if self.0.is_empty() {
165167
return 0;
166168
}
167169

@@ -183,7 +185,7 @@ impl<I> Iterator for MultiProduct<I>
183185

184186
fn size_hint(&self) -> (usize, Option<usize>) {
185187
// Not ExactSizeIterator because size may be larger than usize
186-
if self.0.len() == 0 {
188+
if self.0.is_empty() {
187189
return (0, Some(0));
188190
}
189191

src/combinations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::fmt;
22

33
use super::lazy_buffer::LazyBuffer;
4+
use alloc::vec::Vec;
45

56
/// An iterator to iterate through all the `k`-length combinations in an iterator.
67
///
@@ -56,7 +57,7 @@ impl<I> Iterator for Combinations<I>
5657
return None;
5758
}
5859
self.first = false;
59-
} else if self.indices.len() == 0 {
60+
} else if self.indices.is_empty() {
6061
return None;
6162
} else {
6263
// Scan from the end, looking for an index to increment

src/combinations_with_replacement.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use alloc::vec::Vec;
12
use std::fmt;
23

34
use super::lazy_buffer::LazyBuffer;
@@ -11,10 +12,7 @@ where
1112
I: Iterator,
1213
I::Item: Clone,
1314
{
14-
k: usize,
1515
indices: Vec<usize>,
16-
// The current known max index value. This increases as pool grows.
17-
max_index: usize,
1816
pool: LazyBuffer<I>,
1917
first: bool,
2018
}
@@ -24,7 +22,7 @@ where
2422
I: Iterator + fmt::Debug,
2523
I::Item: fmt::Debug + Clone,
2624
{
27-
debug_fmt_fields!(Combinations, k, indices, max_index, pool, first);
25+
debug_fmt_fields!(Combinations, indices, pool, first);
2826
}
2927

3028
impl<I> CombinationsWithReplacement<I>
@@ -44,13 +42,11 @@ where
4442
I: Iterator,
4543
I::Item: Clone,
4644
{
47-
let indices: Vec<usize> = vec![0; k];
45+
let indices: Vec<usize> = alloc::vec![0; k];
4846
let pool: LazyBuffer<I> = LazyBuffer::new(iter);
4947

5048
CombinationsWithReplacement {
51-
k,
5249
indices,
53-
max_index: 0,
5450
pool,
5551
first: true,
5652
}
@@ -66,7 +62,7 @@ where
6662
// If this is the first iteration, return early
6763
if self.first {
6864
// In empty edge cases, stop iterating immediately
69-
return if self.k != 0 && !self.pool.get_next() {
65+
return if self.indices.len() != 0 && !self.pool.get_next() {
7066
None
7167
// Otherwise, yield the initial state
7268
} else {
@@ -77,14 +73,12 @@ where
7773

7874
// Check if we need to consume more from the iterator
7975
// This will run while we increment our first index digit
80-
if self.pool.get_next() {
81-
self.max_index = self.pool.len() - 1;
82-
}
76+
self.pool.get_next();
8377

8478
// Work out where we need to update our indices
8579
let mut increment: Option<(usize, usize)> = None;
8680
for (i, indices_int) in self.indices.iter().enumerate().rev() {
87-
if indices_int < &self.max_index {
81+
if *indices_int < self.pool.len()-1 {
8882
increment = Some((i, indices_int + 1));
8983
break;
9084
}

src/concat_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ pub fn concat<I>(iterable: I) -> I::Item
1818
where I: IntoIterator,
1919
I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default
2020
{
21-
iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(|| <_>::default())
21+
iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(<_>::default)
2222
}

src/cons_tuples_impl.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ macro_rules! impl_cons_iter(
3535
);
3636
);
3737

38-
impl_cons_iter!(A, B, C, D, E, F, G, H,);
38+
impl_cons_iter!(A, B, C, D, E, F, G, H, I, J, K, L,);
3939

4040
/// An iterator that maps an iterator of tuples like
4141
/// `((A, B), C)` to an iterator of `(A, B, C)`.
@@ -57,8 +57,8 @@ impl<I, J> Clone for ConsTuples<I, J>
5757

5858
/// Create an iterator that maps for example iterators of
5959
/// `((A, B), C)` to `(A, B, C)`.
60-
pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I, J>
61-
where I: Iterator<Item=J>
60+
pub fn cons_tuples<I, J>(iterable: I) -> ConsTuples<I::IntoIter, J>
61+
where I: IntoIterator<Item=J>
6262
{
6363
ConsTuples { iter: iterable.into_iter() }
6464
}

src/exactly_one_err.rs

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
#[cfg(feature = "use_std")]
2+
use std::error::Error;
3+
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
4+
15
use std::iter::ExactSizeIterator;
26

7+
use either::Either;
8+
39
use crate::size_hint;
410

511
/// Iterator returned for the error case of `IterTools::exactly_one()`
@@ -10,12 +16,12 @@ use crate::size_hint;
1016
///
1117
/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not
1218
/// use a `Vec`.
13-
#[derive(Debug, Clone)]
19+
#[derive(Clone)]
1420
pub struct ExactlyOneError<I>
1521
where
1622
I: Iterator,
1723
{
18-
first_two: (Option<I::Item>, Option<I::Item>),
24+
first_two: Option<Either<[I::Item; 2], I::Item>>,
1925
inner: I,
2026
}
2127

@@ -24,9 +30,17 @@ where
2430
I: Iterator,
2531
{
2632
/// Creates a new `ExactlyOneErr` iterator.
27-
pub(crate) fn new(first_two: (Option<I::Item>, Option<I::Item>), inner: I) -> Self {
33+
pub(crate) fn new(first_two: Option<Either<[I::Item; 2], I::Item>>, inner: I) -> Self {
2834
Self { first_two, inner }
2935
}
36+
37+
fn additional_len(&self) -> usize {
38+
match self.first_two {
39+
Some(Either::Left(_)) => 2,
40+
Some(Either::Right(_)) => 1,
41+
None => 0,
42+
}
43+
}
3044
}
3145

3246
impl<I> Iterator for ExactlyOneError<I>
@@ -36,23 +50,61 @@ where
3650
type Item = I::Item;
3751

3852
fn next(&mut self) -> Option<Self::Item> {
39-
self.first_two
40-
.0
41-
.take()
42-
.or_else(|| self.first_two.1.take())
43-
.or_else(|| self.inner.next())
53+
match self.first_two.take() {
54+
Some(Either::Left([first, second])) => {
55+
self.first_two = Some(Either::Right(second));
56+
Some(first)
57+
},
58+
Some(Either::Right(second)) => {
59+
Some(second)
60+
}
61+
None => {
62+
self.inner.next()
63+
}
64+
}
4465
}
4566

4667
fn size_hint(&self) -> (usize, Option<usize>) {
47-
let mut additional_len = 0;
48-
if self.first_two.0.is_some() {
49-
additional_len += 1;
68+
size_hint::add_scalar(self.inner.size_hint(), self.additional_len())
69+
}
70+
}
71+
72+
73+
impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {}
74+
75+
impl<I> Display for ExactlyOneError<I>
76+
where I: Iterator,
77+
{
78+
fn fmt(&self, f: &mut Formatter) -> FmtResult {
79+
let additional = self.additional_len();
80+
if additional > 0 {
81+
write!(f, "got at least 2 elements when exactly one was expected")
82+
} else {
83+
write!(f, "got zero elements when exactly one was expected")
5084
}
51-
if self.first_two.1.is_some() {
52-
additional_len += 1;
85+
}
86+
}
87+
88+
impl<I> Debug for ExactlyOneError<I>
89+
where I: Iterator + Debug,
90+
I::Item: Debug,
91+
{
92+
fn fmt(&self, f: &mut Formatter) -> FmtResult {
93+
match &self.first_two {
94+
Some(Either::Left([first, second])) => {
95+
write!(f, "ExactlyOneError[First: {:?}, Second: {:?}, RemainingIter: {:?}]", first, second, self.inner)
96+
},
97+
Some(Either::Right(second)) => {
98+
write!(f, "ExactlyOneError[Second: {:?}, RemainingIter: {:?}]", second, self.inner)
99+
}
100+
None => {
101+
write!(f, "ExactlyOneError[RemainingIter: {:?}]", self.inner)
102+
}
53103
}
54-
size_hint::add_scalar(self.inner.size_hint(), additional_len)
55104
}
56105
}
57106

58-
impl<I> ExactSizeIterator for ExactlyOneError<I> where I: ExactSizeIterator {}
107+
#[cfg(feature = "use_std")]
108+
impl<I> Error for ExactlyOneError<I> where I: Iterator + Debug, I::Item: Debug, {}
109+
110+

0 commit comments

Comments
 (0)