Skip to content

Commit d1e6d27

Browse files
committed
Reduced code duplication and added impl for SourceIter and InPlaceIterable
1 parent d0f9feb commit d1e6d27

File tree

4 files changed

+97
-127
lines changed

4 files changed

+97
-127
lines changed
Lines changed: 88 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,121 @@
1-
use crate::mem::swap;
1+
use crate::{
2+
iter::{InPlaceIterable, SourceIter},
3+
mem::swap,
4+
};
25

3-
/// An iterator that removes all but the first of consecutive elements in a
4-
/// given iterator according to the [`PartialEq`] trait implementation.
6+
/// A wrapper type around a key function.
57
///
6-
/// This `struct` is created by [`Iterator::dedup`].
8+
/// This struct acts like a function which given a key function returns true
9+
/// if and only if both arguments evaluate to the same key.
10+
///
11+
/// This `struct` is created by [`Iterator::dedup_by_key`].
712
/// See its documentation for more.
813
///
9-
/// [`Iterator::dedup`]: Iterator::dedup
14+
/// [`Iterator::dedup_by_key`]: Iterator::dedup_by_key
1015
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
1116
#[derive(Debug, Clone, Copy)]
12-
pub struct Dedup<I, T> {
13-
inner: I,
14-
last: Option<T>,
17+
pub struct ByKey<F> {
18+
key: F,
19+
}
20+
21+
impl<F> ByKey<F> {
22+
pub(crate) fn new(key: F) -> Self {
23+
Self { key }
24+
}
1525
}
1626

17-
impl<I, T> Dedup<I, T>
27+
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
28+
impl<F, T, K> FnOnce<(&T, &T)> for ByKey<F>
1829
where
19-
I: Iterator<Item = T>,
30+
F: FnMut(&T) -> K,
31+
K: PartialEq,
2032
{
21-
pub(crate) fn new(inner: I) -> Self {
22-
let mut inner = inner;
23-
Self { last: inner.next(), inner }
33+
type Output = bool;
34+
35+
extern "rust-call" fn call_once(mut self, args: (&T, &T)) -> Self::Output {
36+
(self.key)(args.0) == (self.key)(args.1)
2437
}
2538
}
2639

2740
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
28-
impl<I, T> Iterator for Dedup<I, T>
41+
impl<F, T, K> FnMut<(&T, &T)> for ByKey<F>
2942
where
30-
I: Iterator<Item = T>,
31-
T: PartialEq,
43+
F: FnMut(&T) -> K,
44+
K: PartialEq,
3245
{
33-
type Item = T;
46+
extern "rust-call" fn call_mut(&mut self, args: (&T, &T)) -> Self::Output {
47+
(self.key)(args.0) == (self.key)(args.1)
48+
}
49+
}
3450

35-
fn next(&mut self) -> Option<Self::Item> {
36-
let last_item = self.last.as_ref()?;
37-
let mut next = loop {
38-
let curr = self.inner.next();
39-
if let Some(curr_item) = &curr {
40-
if last_item != curr_item {
41-
break curr;
42-
}
43-
} else {
44-
break None;
45-
}
46-
};
51+
/// A zero-sized type for checking partial equality.
52+
///
53+
/// This struct acts exactly like the function [`PartialEq::eq`], but its
54+
/// type is always known during compile time.
55+
///
56+
/// This `struct` is created by [`Iterator::dedup`].
57+
/// See its documentation for more.
58+
///
59+
/// [`Iterator::dedup`]: Iterator::dedup
60+
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
61+
#[derive(Debug, Clone, Copy)]
62+
pub struct ByPartialEq;
4763

48-
swap(&mut self.last, &mut next);
49-
next
64+
impl ByPartialEq {
65+
pub(crate) fn new() -> Self {
66+
Self
5067
}
68+
}
5169

52-
fn size_hint(&self) -> (usize, Option<usize>) {
53-
if self.last.is_some() {
54-
// If we have a last item stored, the iterator can yield at most
55-
// as many items at the inner iterator plus the stored one. Yet we
56-
// can only guarantee that the iterator yields at least one more item
57-
// since all other items in the inner iterator might be duplicates.
58-
let (_, max) = self.inner.size_hint();
59-
(1, max.and_then(|k| k.checked_add(1)))
60-
} else {
61-
// If the last item we got from the inner iterator is `None`,
62-
// the iterator is empty.
63-
(0, Some(0))
64-
}
70+
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
71+
impl<T: PartialEq> FnOnce<(&T, &T)> for ByPartialEq {
72+
type Output = bool;
73+
74+
extern "rust-call" fn call_once(self, args: (&T, &T)) -> Self::Output {
75+
args.0 == args.1
76+
}
77+
}
78+
79+
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
80+
impl<T: PartialEq> FnMut<(&T, &T)> for ByPartialEq {
81+
extern "rust-call" fn call_mut(&mut self, args: (&T, &T)) -> Self::Output {
82+
args.0 == args.1
6583
}
6684
}
6785

6886
/// An iterator that removes all but the first of consecutive elements in a
6987
/// given iterator satisfying a given equality relation.
7088
///
71-
/// This `struct` is created by [`Iterator::dedup_by`].
72-
/// See its documentation for more.
89+
/// This `struct` is created by [`Iterator::dedup`], [`Iterator::dedup_by`]
90+
/// and [`Iterator::dedup_by_key`]. See its documentation for more.
7391
///
92+
/// [`Iterator::dedup`]: Iterator::dedup
7493
/// [`Iterator::dedup_by`]: Iterator::dedup_by
94+
/// [`Iterator::dedup_by_key`]: Iterator::dedup_by_key
7595
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
7696
#[derive(Debug, Clone, Copy)]
77-
pub struct DedupBy<I, F, T> {
97+
pub struct Dedup<I, F, T> {
7898
inner: I,
7999
same_bucket: F,
80100
last: Option<T>,
81101
}
82102

83-
impl<I, F, T> DedupBy<I, F, T>
103+
impl<I, F, T> Dedup<I, F, T>
84104
where
85105
I: Iterator<Item = T>,
86106
{
87107
pub(crate) fn new(inner: I, same_bucket: F) -> Self {
88108
let mut inner = inner;
89-
Self { last: inner.next(), inner, same_bucket }
109+
Self {
110+
last: inner.next(),
111+
inner,
112+
same_bucket,
113+
}
90114
}
91115
}
92116

93117
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
94-
impl<I, F, T> Iterator for DedupBy<I, F, T>
118+
impl<I, F, T> Iterator for Dedup<I, F, T>
95119
where
96120
I: Iterator<Item = T>,
97121
F: FnMut(&T, &T) -> bool,
@@ -116,84 +140,30 @@ where
116140
}
117141

118142
fn size_hint(&self) -> (usize, Option<usize>) {
119-
if self.last.is_some() {
120-
// If we have a last item stored, the iterator can yield at most
121-
// as many items at the inner iterator plus the stored one. Yet we
122-
// can only guarantee that the iterator yields at least one more item
123-
// since all other items in the inner iterator might be duplicates.
124-
let (_, max) = self.inner.size_hint();
125-
(1, max.and_then(|k| k.checked_add(1)))
126-
} else {
127-
// If the last item we got from the inner iterator is `None`,
128-
// the iterator is empty.
129-
(0, Some(0))
130-
}
143+
let min = self.last.as_ref().map(|_| 1).unwrap_or(0);
144+
let max = self.inner.size_hint().1;
145+
(min, max)
131146
}
132147
}
133148

134-
/// An iterator that removes all but the first of consecutive elements in a
135-
/// given iterator that resolve to the same key.
136-
///
137-
/// This `struct` is created by [`Iterator::dedup_by_key`].
138-
/// See its documentation for more.
139-
///
140-
/// [`Iterator::dedup_by_key`]: Iterator::dedup_by_key
141149
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
142-
#[derive(Debug, Clone, Copy)]
143-
pub struct DedupByKey<I, F, T> {
144-
inner: I,
145-
key: F,
146-
last: Option<T>,
147-
}
148-
149-
impl<I, F, T> DedupByKey<I, F, T>
150+
unsafe impl<S, I, F, T> SourceIter for Dedup<I, F, T>
150151
where
151-
I: Iterator<Item = T>,
152+
S: Iterator,
153+
I: Iterator + SourceIter<Source = S>,
152154
{
153-
pub(crate) fn new(inner: I, key: F) -> Self {
154-
let mut inner = inner;
155-
Self { last: inner.next(), inner, key }
155+
type Source = S;
156+
157+
unsafe fn as_inner(&mut self) -> &mut Self::Source {
158+
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
159+
unsafe { SourceIter::as_inner(&mut self.inner) }
156160
}
157161
}
158162

159163
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
160-
impl<I, F, K, T> Iterator for DedupByKey<I, F, T>
164+
unsafe impl<I, F, T> InPlaceIterable for Dedup<I, F, T>
161165
where
162-
I: Iterator<Item = T>,
163-
F: FnMut(&T) -> K,
164-
K: PartialEq,
166+
I: InPlaceIterable<Item = T>,
167+
F: FnMut(&T, &T) -> bool,
165168
{
166-
type Item = T;
167-
168-
fn next(&mut self) -> Option<Self::Item> {
169-
let last_item = self.last.as_ref()?;
170-
let mut next = loop {
171-
let curr = self.inner.next();
172-
if let Some(curr_item) = &curr {
173-
if (self.key)(last_item) != (self.key)(curr_item) {
174-
break curr;
175-
}
176-
} else {
177-
break None;
178-
}
179-
};
180-
181-
swap(&mut self.last, &mut next);
182-
next
183-
}
184-
185-
fn size_hint(&self) -> (usize, Option<usize>) {
186-
if self.last.is_some() {
187-
// If we have a last item stored, the iterator can yield at most
188-
// as many items at the inner iterator plus the stored one. Yet we
189-
// can only guarantee that the iterator yields at least one more item
190-
// since all other items in the inner iterator might be duplicates.
191-
let (_, max) = self.inner.size_hint();
192-
(1, max.and_then(|k| k.checked_add(1)))
193-
} else {
194-
// If the last item we got from the inner iterator is `None`,
195-
// the iterator is empty.
196-
(0, Some(0))
197-
}
198-
}
199169
}

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

Lines changed: 1 addition & 1 deletion
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::{Dedup, DedupBy, DedupByKey};
71+
pub use self::dedup::{Dedup, ByKey, ByPartialEq};
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ pub use self::adapters::{
424424
Skip, SkipWhile, Take, TakeWhile, Zip,
425425
};
426426
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
427-
pub use self::adapters::{Dedup, DedupBy, DedupByKey};
427+
pub use self::adapters::{Dedup, ByKey, ByPartialEq};
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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use super::super::try_process;
66
use super::super::ByRefSized;
77
use super::super::TrustedRandomAccessNoCoerce;
88
use super::super::{ArrayChunks, Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
9-
use super::super::{Dedup, DedupBy, DedupByKey};
9+
use super::super::{Dedup, ByKey, ByPartialEq};
1010
use super::super::{FlatMap, Flatten};
1111
use super::super::{FromIterator, Intersperse, IntersperseWith, Product, Sum, Zip};
1212
use super::super::{
@@ -1715,12 +1715,12 @@ pub trait Iterator {
17151715
/// ```
17161716
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
17171717
#[inline]
1718-
fn dedup(self) -> Dedup<Self, Self::Item>
1718+
fn dedup(self) -> Dedup<Self, ByPartialEq, Self::Item>
17191719
where
17201720
Self: Sized,
17211721
Self::Item: PartialEq,
17221722
{
1723-
Dedup::new(self)
1723+
Dedup::new(self, ByPartialEq::new())
17241724
}
17251725

17261726
/// Removes all but the first of consecutive elements in the iterator satisfying a given equality
@@ -1751,12 +1751,12 @@ pub trait Iterator {
17511751
/// ```
17521752
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
17531753
#[inline]
1754-
fn dedup_by<F>(self, same_bucket: F) -> DedupBy<Self, F, Self::Item>
1754+
fn dedup_by<F>(self, same_bucket: F) -> Dedup<Self, F, Self::Item>
17551755
where
17561756
Self: Sized,
17571757
F: FnMut(&Self::Item, &Self::Item) -> bool,
17581758
{
1759-
DedupBy::new(self, same_bucket)
1759+
Dedup::new(self, same_bucket)
17601760
}
17611761

17621762
/// Removes all but the first of consecutive elements in the iterator that
@@ -1784,13 +1784,13 @@ pub trait Iterator {
17841784
/// ```
17851785
#[unstable(feature = "iter_dedup", reason = "recently added", issue = "83748")]
17861786
#[inline]
1787-
fn dedup_by_key<F, K>(self, key: F) -> DedupByKey<Self, F, Self::Item>
1787+
fn dedup_by_key<F, K>(self, key: F) -> Dedup<Self, ByKey<F>, Self::Item>
17881788
where
17891789
Self: Sized,
17901790
F: FnMut(&Self::Item) -> K,
17911791
K: PartialEq,
17921792
{
1793-
DedupByKey::new(self, key)
1793+
Dedup::new(self, ByKey::new(key))
17941794
}
17951795

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

0 commit comments

Comments
 (0)