• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::fmt;
2 use std::iter::FusedIterator;
3 
4 use crate::size_hint;
5 
6 pub struct CoalesceBy<I, F, T>
7 where
8     I: Iterator,
9 {
10     iter: I,
11     last: Option<T>,
12     f: F,
13 }
14 
15 impl<I: Clone, F: Clone, T: Clone> Clone for CoalesceBy<I, F, T>
16 where
17     I: Iterator,
18 {
19     clone_fields!(last, iter, f);
20 }
21 
22 impl<I, F, T> fmt::Debug for CoalesceBy<I, F, T>
23 where
24     I: Iterator + fmt::Debug,
25     T: fmt::Debug,
26 {
27     debug_fmt_fields!(CoalesceBy, iter);
28 }
29 
30 pub trait CoalescePredicate<Item, T> {
coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)>31     fn coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)>;
32 }
33 
34 impl<I, F, T> Iterator for CoalesceBy<I, F, T>
35 where
36     I: Iterator,
37     F: CoalescePredicate<I::Item, T>,
38 {
39     type Item = T;
40 
next(&mut self) -> Option<Self::Item>41     fn next(&mut self) -> Option<Self::Item> {
42         // this fuses the iterator
43         let mut last = match self.last.take() {
44             None => return None,
45             Some(x) => x,
46         };
47         for next in &mut self.iter {
48             match self.f.coalesce_pair(last, next) {
49                 Ok(joined) => last = joined,
50                 Err((last_, next_)) => {
51                     self.last = Some(next_);
52                     return Some(last_);
53                 }
54             }
55         }
56         Some(last)
57     }
58 
size_hint(&self) -> (usize, Option<usize>)59     fn size_hint(&self) -> (usize, Option<usize>) {
60         let (low, hi) = size_hint::add_scalar(self.iter.size_hint(), self.last.is_some() as usize);
61         ((low > 0) as usize, hi)
62     }
63 
fold<Acc, FnAcc>(self, acc: Acc, mut fn_acc: FnAcc) -> Acc where FnAcc: FnMut(Acc, Self::Item) -> Acc,64     fn fold<Acc, FnAcc>(self, acc: Acc, mut fn_acc: FnAcc) -> Acc
65     where
66         FnAcc: FnMut(Acc, Self::Item) -> Acc,
67     {
68         if let Some(last) = self.last {
69             let mut f = self.f;
70             let (last, acc) = self.iter.fold((last, acc), |(last, acc), elt| {
71                 match f.coalesce_pair(last, elt) {
72                     Ok(joined) => (joined, acc),
73                     Err((last_, next_)) => (next_, fn_acc(acc, last_)),
74                 }
75             });
76             fn_acc(acc, last)
77         } else {
78             acc
79         }
80     }
81 }
82 
83 impl<I: Iterator, F: CoalescePredicate<I::Item, T>, T> FusedIterator for CoalesceBy<I, F, T> {}
84 
85 /// An iterator adaptor that may join together adjacent elements.
86 ///
87 /// See [`.coalesce()`](../trait.Itertools.html#method.coalesce) for more information.
88 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
89 pub type Coalesce<I, F> = CoalesceBy<I, F, <I as Iterator>::Item>;
90 
91 impl<F, Item, T> CoalescePredicate<Item, T> for F
92 where
93     F: FnMut(T, Item) -> Result<T, (T, T)>,
94 {
coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)>95     fn coalesce_pair(&mut self, t: T, item: Item) -> Result<T, (T, T)> {
96         self(t, item)
97     }
98 }
99 
100 /// Create a new `Coalesce`.
coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F> where I: Iterator,101 pub fn coalesce<I, F>(mut iter: I, f: F) -> Coalesce<I, F>
102 where
103     I: Iterator,
104 {
105     Coalesce {
106         last: iter.next(),
107         iter,
108         f,
109     }
110 }
111 
112 /// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function.
113 ///
114 /// See [`.dedup_by()`](../trait.Itertools.html#method.dedup_by) or [`.dedup()`](../trait.Itertools.html#method.dedup) for more information.
115 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
116 pub type DedupBy<I, Pred> = CoalesceBy<I, DedupPred2CoalescePred<Pred>, <I as Iterator>::Item>;
117 
118 #[derive(Clone)]
119 pub struct DedupPred2CoalescePred<DP>(DP);
120 
121 pub trait DedupPredicate<T> {
122     // TODO replace by Fn(&T, &T)->bool once Rust supports it
dedup_pair(&mut self, a: &T, b: &T) -> bool123     fn dedup_pair(&mut self, a: &T, b: &T) -> bool;
124 }
125 
126 impl<DP, T> CoalescePredicate<T, T> for DedupPred2CoalescePred<DP>
127 where
128     DP: DedupPredicate<T>,
129 {
coalesce_pair(&mut self, t: T, item: T) -> Result<T, (T, T)>130     fn coalesce_pair(&mut self, t: T, item: T) -> Result<T, (T, T)> {
131         if self.0.dedup_pair(&t, &item) {
132             Ok(t)
133         } else {
134             Err((t, item))
135         }
136     }
137 }
138 
139 #[derive(Clone)]
140 pub struct DedupEq;
141 
142 impl<T: PartialEq> DedupPredicate<T> for DedupEq {
dedup_pair(&mut self, a: &T, b: &T) -> bool143     fn dedup_pair(&mut self, a: &T, b: &T) -> bool {
144         a == b
145     }
146 }
147 
148 impl<T, F: FnMut(&T, &T) -> bool> DedupPredicate<T> for F {
dedup_pair(&mut self, a: &T, b: &T) -> bool149     fn dedup_pair(&mut self, a: &T, b: &T) -> bool {
150         self(a, b)
151     }
152 }
153 
154 /// Create a new `DedupBy`.
dedup_by<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupBy<I, Pred> where I: Iterator,155 pub fn dedup_by<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupBy<I, Pred>
156 where
157     I: Iterator,
158 {
159     DedupBy {
160         last: iter.next(),
161         iter,
162         f: DedupPred2CoalescePred(dedup_pred),
163     }
164 }
165 
166 /// An iterator adaptor that removes repeated duplicates.
167 ///
168 /// See [`.dedup()`](../trait.Itertools.html#method.dedup) for more information.
169 pub type Dedup<I> = DedupBy<I, DedupEq>;
170 
171 /// Create a new `Dedup`.
dedup<I>(iter: I) -> Dedup<I> where I: Iterator,172 pub fn dedup<I>(iter: I) -> Dedup<I>
173 where
174     I: Iterator,
175 {
176     dedup_by(iter, DedupEq)
177 }
178 
179 /// An iterator adaptor that removes repeated duplicates, while keeping a count of how many
180 /// repeated elements were present. This will determine equality using a comparison function.
181 ///
182 /// See [`.dedup_by_with_count()`](../trait.Itertools.html#method.dedup_by_with_count) or
183 /// [`.dedup_with_count()`](../trait.Itertools.html#method.dedup_with_count) for more information.
184 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
185 pub type DedupByWithCount<I, Pred> =
186     CoalesceBy<I, DedupPredWithCount2CoalescePred<Pred>, (usize, <I as Iterator>::Item)>;
187 
188 #[derive(Clone)]
189 pub struct DedupPredWithCount2CoalescePred<DP>(DP);
190 
191 impl<DP, T> CoalescePredicate<T, (usize, T)> for DedupPredWithCount2CoalescePred<DP>
192 where
193     DP: DedupPredicate<T>,
194 {
coalesce_pair( &mut self, (c, t): (usize, T), item: T, ) -> Result<(usize, T), ((usize, T), (usize, T))>195     fn coalesce_pair(
196         &mut self,
197         (c, t): (usize, T),
198         item: T,
199     ) -> Result<(usize, T), ((usize, T), (usize, T))> {
200         if self.0.dedup_pair(&t, &item) {
201             Ok((c + 1, t))
202         } else {
203             Err(((c, t), (1, item)))
204         }
205     }
206 }
207 
208 /// An iterator adaptor that removes repeated duplicates, while keeping a count of how many
209 /// repeated elements were present.
210 ///
211 /// See [`.dedup_with_count()`](../trait.Itertools.html#method.dedup_with_count) for more information.
212 pub type DedupWithCount<I> = DedupByWithCount<I, DedupEq>;
213 
214 /// Create a new `DedupByWithCount`.
dedup_by_with_count<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupByWithCount<I, Pred> where I: Iterator,215 pub fn dedup_by_with_count<I, Pred>(mut iter: I, dedup_pred: Pred) -> DedupByWithCount<I, Pred>
216 where
217     I: Iterator,
218 {
219     DedupByWithCount {
220         last: iter.next().map(|v| (1, v)),
221         iter,
222         f: DedupPredWithCount2CoalescePred(dedup_pred),
223     }
224 }
225 
226 /// Create a new `DedupWithCount`.
dedup_with_count<I>(iter: I) -> DedupWithCount<I> where I: Iterator,227 pub fn dedup_with_count<I>(iter: I) -> DedupWithCount<I>
228 where
229     I: Iterator,
230 {
231     dedup_by_with_count(iter, DedupEq)
232 }
233