Skip to content

Commit a822aad

Browse files
committed
Go back to separate iterators
1 parent 67d01d5 commit a822aad

File tree

4 files changed

+139
-69
lines changed

4 files changed

+139
-69
lines changed

library/core/src/iter/adapters/dedup.rs

+129-59
Original file line numberDiff line numberDiff line change
@@ -2,127 +2,195 @@
22

33
use crate::iter::{InPlaceIterable, SourceIter};
44

5-
/// A wrapper type around a key function.
6-
///
7-
/// This struct acts like a function which given a key function returns true
8-
/// if and only if both arguments evaluate to the same key.
5+
/// An iterator that removes all but the first of consecutive elements in a
6+
/// given iterator according to the [`PartialEq`] trait implementation.
97
///
10-
/// This `struct` is created by [`Iterator::dedup_by_key`].
8+
/// This `struct` is created by [`Iterator::dedup`].
119
/// See its documentation for more.
1210
///
13-
/// [`Iterator::dedup_by_key`]: Iterator::dedup_by_key
14-
#[derive(Debug, Clone, Copy)]
15-
pub struct ByKey<F> {
16-
key: F,
11+
/// [`Iterator::dedup`]: Iterator::dedup
12+
#[derive(Debug, Clone)]
13+
pub struct Dedup<I>
14+
where
15+
I: Iterator,
16+
{
17+
inner: I,
18+
last: Option<Option<I::Item>>,
1719
}
1820

19-
impl<F> ByKey<F> {
21+
impl<I> Dedup<I>
22+
where
23+
I: Iterator,
24+
{
2025
#[inline]
21-
pub(crate) fn new(key: F) -> Self {
22-
Self { key }
26+
pub(crate) fn new(inner: I) -> Self {
27+
Self { inner, last: None }
2328
}
2429
}
2530

26-
impl<F, T, K> FnOnce<(&T, &T)> for ByKey<F>
31+
impl<I> Iterator for Dedup<I>
2732
where
28-
F: FnMut(&T) -> K,
29-
K: PartialEq,
33+
I: Iterator,
34+
I::Item: PartialEq,
3035
{
31-
type Output = bool;
36+
type Item = I::Item;
37+
3238
#[inline]
33-
extern "rust-call" fn call_once(mut self, args: (&T, &T)) -> Self::Output {
34-
(self.key)(args.0) == (self.key)(args.1)
39+
fn next(&mut self) -> Option<Self::Item> {
40+
let Self { inner, last } = self;
41+
let last = last.get_or_insert_with(|| inner.next());
42+
let last_item = last.as_ref()?;
43+
let next = inner.find(|next_item| next_item != last_item);
44+
crate::mem::replace(last, next)
45+
}
46+
47+
#[inline]
48+
fn size_hint(&self) -> (usize, Option<usize>) {
49+
let min = matches!(self.last, Some(Some(_))).into();
50+
let max = self.inner.size_hint().1.map(|max| max + min);
51+
(min, max)
3552
}
3653
}
3754

38-
impl<F, T, K> FnMut<(&T, &T)> for ByKey<F>
55+
#[unstable(issue = "none", feature = "inplace_iteration")]
56+
unsafe impl<I> SourceIter for Dedup<I>
3957
where
40-
F: FnMut(&T) -> K,
41-
K: PartialEq,
58+
I: SourceIter + Iterator,
4259
{
60+
type Source = I::Source;
61+
4362
#[inline]
44-
extern "rust-call" fn call_mut(&mut self, args: (&T, &T)) -> Self::Output {
45-
(self.key)(args.0) == (self.key)(args.1)
63+
unsafe fn as_inner(&mut self) -> &mut I::Source {
64+
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
65+
unsafe { SourceIter::as_inner(&mut self.inner) }
4666
}
4767
}
4868

49-
/// A zero-sized type for checking partial equality.
50-
///
51-
/// This struct acts exactly like the function [`PartialEq::eq`], but its
52-
/// type is always known during compile time.
69+
#[unstable(issue = "none", feature = "inplace_iteration")]
70+
unsafe impl<I> InPlaceIterable for Dedup<I>
71+
where
72+
I: Iterator,
73+
I: InPlaceIterable,
74+
I::Item: PartialEq,
75+
{
76+
}
77+
78+
/// An iterator that removes all but the first of consecutive elements in a
79+
/// given iterator satisfying a given equality relation.
5380
///
54-
/// This `struct` is created by [`Iterator::dedup`].
81+
/// This `struct` is created by [`Iterator::dedup_by`].
5582
/// See its documentation for more.
5683
///
57-
/// [`Iterator::dedup`]: Iterator::dedup
58-
#[derive(Debug, Clone, Copy)]
59-
#[non_exhaustive]
60-
pub struct ByPartialEq;
84+
/// [`Iterator::dedup_by`]: Iterator::dedup_by
85+
#[derive(Debug, Clone)]
86+
pub struct DedupBy<I, F>
87+
where
88+
I: Iterator,
89+
{
90+
inner: I,
91+
same_bucket: F,
92+
last: Option<Option<I::Item>>,
93+
}
6194

62-
impl ByPartialEq {
95+
impl<I, F> DedupBy<I, F>
96+
where
97+
I: Iterator,
98+
{
6399
#[inline]
64-
pub(crate) fn new() -> Self {
65-
Self
100+
pub(crate) fn new(inner: I, same_bucket: F) -> Self {
101+
Self { inner, same_bucket, last: None }
66102
}
67103
}
68104

69-
impl<T: PartialEq> FnOnce<(&T, &T)> for ByPartialEq {
70-
type Output = bool;
105+
impl<I, F> Iterator for DedupBy<I, F>
106+
where
107+
I: Iterator,
108+
F: FnMut(&I::Item, &I::Item) -> bool,
109+
{
110+
type Item = I::Item;
111+
112+
#[inline]
113+
fn next(&mut self) -> Option<Self::Item> {
114+
let Self { inner, last, same_bucket } = self;
115+
let last = last.get_or_insert_with(|| inner.next());
116+
let last_item = last.as_ref()?;
117+
let next = inner.find(|next_item| !(same_bucket)(next_item, last_item));
118+
crate::mem::replace(last, next)
119+
}
120+
71121
#[inline]
72-
extern "rust-call" fn call_once(self, args: (&T, &T)) -> Self::Output {
73-
args.0 == args.1
122+
fn size_hint(&self) -> (usize, Option<usize>) {
123+
let min = matches!(self.last, Some(Some(_))).into();
124+
let max = self.inner.size_hint().1.map(|max| max + min);
125+
(min, max)
74126
}
75127
}
76128

77-
impl<T: PartialEq> FnMut<(&T, &T)> for ByPartialEq {
129+
#[unstable(issue = "none", feature = "inplace_iteration")]
130+
unsafe impl<I, F> SourceIter for DedupBy<I, F>
131+
where
132+
I: SourceIter + Iterator,
133+
{
134+
type Source = I::Source;
135+
78136
#[inline]
79-
extern "rust-call" fn call_mut(&mut self, args: (&T, &T)) -> Self::Output {
80-
args.0 == args.1
137+
unsafe fn as_inner(&mut self) -> &mut I::Source {
138+
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
139+
unsafe { SourceIter::as_inner(&mut self.inner) }
81140
}
82141
}
83142

143+
#[unstable(issue = "none", feature = "inplace_iteration")]
144+
unsafe impl<I, F> InPlaceIterable for DedupBy<I, F>
145+
where
146+
I: InPlaceIterable,
147+
F: FnMut(&I::Item, &I::Item) -> bool,
148+
{
149+
}
150+
84151
/// An iterator that removes all but the first of consecutive elements in a
85-
/// given iterator satisfying a given equality relation.
152+
/// given iterator that resolve to the same key.
86153
///
87-
/// This `struct` is created by [`Iterator::dedup`], [`Iterator::dedup_by`]
88-
/// and [`Iterator::dedup_by_key`]. See its documentation for more.
154+
/// This `struct` is created by [`Iterator::dedup_by_key`].
155+
/// See its documentation for more.
89156
///
90-
/// [`Iterator::dedup`]: Iterator::dedup
91-
/// [`Iterator::dedup_by`]: Iterator::dedup_by
92157
/// [`Iterator::dedup_by_key`]: Iterator::dedup_by_key
93158
#[derive(Debug, Clone)]
94-
pub struct Dedup<I, F>
159+
pub struct DedupByKey<I, F, K>
95160
where
96161
I: Iterator,
162+
F: FnMut(&I::Item) -> K,
97163
{
98164
inner: I,
99-
same_bucket: F,
165+
key: F,
100166
last: Option<Option<I::Item>>,
101167
}
102168

103-
impl<I, F> Dedup<I, F>
169+
impl<I, F, K> DedupByKey<I, F, K>
104170
where
105171
I: Iterator,
172+
F: FnMut(&I::Item) -> K,
106173
{
107174
#[inline]
108-
pub(crate) fn new(inner: I, same_bucket: F) -> Self {
109-
Self { inner, same_bucket, last: None }
175+
pub(crate) fn new(inner: I, key: F) -> Self {
176+
Self { inner, key, last: None }
110177
}
111178
}
112179

113-
impl<I, F> Iterator for Dedup<I, F>
180+
impl<I, F, K> Iterator for DedupByKey<I, F, K>
114181
where
115182
I: Iterator,
116-
F: FnMut(&I::Item, &I::Item) -> bool,
183+
F: FnMut(&I::Item) -> K,
184+
K: PartialEq,
117185
{
118186
type Item = I::Item;
119187

120188
#[inline]
121189
fn next(&mut self) -> Option<Self::Item> {
122-
let Self { inner, last, same_bucket } = self;
190+
let Self { inner, last, key } = self;
123191
let last = last.get_or_insert_with(|| inner.next());
124192
let last_item = last.as_ref()?;
125-
let next = inner.find(|next_item| !(same_bucket)(next_item, last_item));
193+
let next = inner.find(|next_item| key(next_item) != key(last_item));
126194
crate::mem::replace(last, next)
127195
}
128196

@@ -135,9 +203,10 @@ where
135203
}
136204

137205
#[unstable(issue = "none", feature = "inplace_iteration")]
138-
unsafe impl<I, F> SourceIter for Dedup<I, F>
206+
unsafe impl<I, F, K> SourceIter for DedupByKey<I, F, K>
139207
where
140208
I: SourceIter + Iterator,
209+
F: FnMut(&I::Item) -> K,
141210
{
142211
type Source = I::Source;
143212

@@ -149,9 +218,10 @@ where
149218
}
150219

151220
#[unstable(issue = "none", feature = "inplace_iteration")]
152-
unsafe impl<I, F> InPlaceIterable for Dedup<I, F>
221+
unsafe impl<I, F, K> InPlaceIterable for DedupByKey<I, F, K>
153222
where
154223
I: InPlaceIterable,
155-
F: FnMut(&I::Item, &I::Item) -> bool,
224+
F: FnMut(&I::Item) -> K,
225+
K: PartialEq,
156226
{
157227
}

library/core/src/iter/adapters/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub use self::zip::TrustedRandomAccessNoCoerce;
6868
pub use self::zip::zip;
6969

7070
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
71-
pub use self::dedup::{ByKey, ByPartialEq, Dedup};
71+
pub use self::dedup::{Dedup, DedupBy, DedupByKey};
7272

7373
/// This trait provides transitive access to source-stage in an interator-adapter pipeline
7474
/// under the conditions that

library/core/src/iter/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -418,13 +418,13 @@ pub use self::adapters::StepBy;
418418
pub use self::adapters::TrustedRandomAccess;
419419
#[unstable(feature = "trusted_random_access", issue = "none")]
420420
pub use self::adapters::TrustedRandomAccessNoCoerce;
421-
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
422-
pub use self::adapters::{ByKey, ByPartialEq, Dedup};
423421
#[stable(feature = "rust1", since = "1.0.0")]
424422
pub use self::adapters::{
425423
Chain, Cycle, Enumerate, Filter, FilterMap, FlatMap, Fuse, Inspect, Map, Peekable, Rev, Scan,
426424
Skip, SkipWhile, Take, TakeWhile, Zip,
427425
};
426+
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
427+
pub use self::adapters::{Dedup, DedupBy, DedupByKey};
428428
#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")]
429429
pub use self::adapters::{Intersperse, IntersperseWith};
430430

library/core/src/iter/traits/iterator.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
55
use super::super::try_process;
66
use super::super::ByRefSized;
77
use super::super::TrustedRandomAccessNoCoerce;
8-
use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
9-
use super::super::{ByKey, ByPartialEq, Dedup};
8+
use super::super::{ArrayChunks, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
9+
use super::super::{Dedup, DedupBy, DedupByKey};
1010
use super::super::{FlatMap, Flatten};
1111
use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip};
1212
use super::super::{
@@ -1726,12 +1726,12 @@ pub trait Iterator {
17261726
/// ```
17271727
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
17281728
#[inline]
1729-
fn dedup(self) -> Dedup<Self, ByPartialEq>
1729+
fn dedup(self) -> Dedup<Self>
17301730
where
17311731
Self: Sized,
17321732
Self::Item: PartialEq,
17331733
{
1734-
Dedup::new(self, ByPartialEq::new())
1734+
Dedup::new(self)
17351735
}
17361736

17371737
/// Removes all but the first of consecutive elements in the iterator
@@ -1773,7 +1773,7 @@ pub trait Iterator {
17731773
/// ```
17741774
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
17751775
#[inline]
1776-
fn dedup_by<F>(self, same_bucket: F) -> Dedup<Self, F>
1776+
fn dedup_by<F>(self, same_bucket: F) -> DedupBy<Self, F>
17771777
where
17781778
Self: Sized,
17791779
F: FnMut(&Self::Item, &Self::Item) -> bool,
@@ -1817,13 +1817,13 @@ pub trait Iterator {
18171817
/// ```
18181818
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
18191819
#[inline]
1820-
fn dedup_by_key<F, K>(self, key: F) -> Dedup<Self, ByKey<F>>
1820+
fn dedup_by_key<F, K>(self, key: F) -> DedupByKey<Self, F, K>
18211821
where
18221822
Self: Sized,
18231823
F: FnMut(&Self::Item) -> K,
18241824
K: PartialEq,
18251825
{
1826-
Dedup::new(self, ByKey::new(key))
1826+
Dedup::new(self, key)
18271827
}
18281828

18291829
/// Borrows an iterator, rather than consuming it.

0 commit comments

Comments
 (0)