1use crate::fmt;
2
3#[unstable(feature = "iter_intersperse", issue = "79524")]
8#[derive(Debug, Clone)]
9pub struct Intersperse<I: Iterator>
10where
11 I::Item: Clone,
12{
13 started: bool,
14 separator: I::Item,
15 next_item: Option<I::Item>,
16 iter: I,
17}
18
19impl<I: Iterator> Intersperse<I>
20where
21 I::Item: Clone,
22{
23 pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self {
24 Self { started: false, separator, next_item: None, iter }
25 }
26}
27
28#[unstable(feature = "iter_intersperse", issue = "79524")]
29impl<I> Iterator for Intersperse<I>
30where
31 I: Iterator,
32 I::Item: Clone,
33{
34 type Item = I::Item;
35
36 #[inline]
37 fn next(&mut self) -> Option<Self::Item> {
38 if self.started {
39 if let Some(v) = self.next_item.take() {
40 Some(v)
41 } else {
42 let next_item = self.iter.next();
43 if next_item.is_some() {
44 self.next_item = next_item;
45 Some(self.separator.clone())
46 } else {
47 None
48 }
49 }
50 } else {
51 let item = self.iter.next();
52 self.started = item.is_some();
53 item
54 }
55 }
56
57 fn size_hint(&self) -> (usize, Option<usize>) {
58 intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
59 }
60
61 fn fold<B, F>(self, init: B, f: F) -> B
62 where
63 Self: Sized,
64 F: FnMut(B, Self::Item) -> B,
65 {
66 let separator = self.separator;
67 intersperse_fold(
68 self.iter,
69 init,
70 f,
71 move || separator.clone(),
72 self.started,
73 self.next_item,
74 )
75 }
76}
77
78#[unstable(feature = "iter_intersperse", issue = "79524")]
83pub struct IntersperseWith<I, G>
84where
85 I: Iterator,
86{
87 started: bool,
88 separator: G,
89 next_item: Option<I::Item>,
90 iter: I,
91}
92
93#[unstable(feature = "iter_intersperse", issue = "79524")]
94impl<I, G> fmt::Debug for IntersperseWith<I, G>
95where
96 I: Iterator + fmt::Debug,
97 I::Item: fmt::Debug,
98 G: fmt::Debug,
99{
100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101 f.debug_struct("IntersperseWith")
102 .field("started", &self.started)
103 .field("separator", &self.separator)
104 .field("iter", &self.iter)
105 .field("next_item", &self.next_item)
106 .finish()
107 }
108}
109
110#[unstable(feature = "iter_intersperse", issue = "79524")]
111impl<I, G> Clone for IntersperseWith<I, G>
112where
113 I: Iterator + Clone,
114 I::Item: Clone,
115 G: Clone,
116{
117 fn clone(&self) -> Self {
118 Self {
119 started: self.started,
120 separator: self.separator.clone(),
121 iter: self.iter.clone(),
122 next_item: self.next_item.clone(),
123 }
124 }
125}
126
127impl<I, G> IntersperseWith<I, G>
128where
129 I: Iterator,
130 G: FnMut() -> I::Item,
131{
132 pub(in crate::iter) fn new(iter: I, separator: G) -> Self {
133 Self { started: false, separator, next_item: None, iter }
134 }
135}
136
137#[unstable(feature = "iter_intersperse", issue = "79524")]
138impl<I, G> Iterator for IntersperseWith<I, G>
139where
140 I: Iterator,
141 G: FnMut() -> I::Item,
142{
143 type Item = I::Item;
144
145 #[inline]
146 fn next(&mut self) -> Option<Self::Item> {
147 if self.started {
148 if let Some(v) = self.next_item.take() {
149 Some(v)
150 } else {
151 let next_item = self.iter.next();
152 if next_item.is_some() {
153 self.next_item = next_item;
154 Some((self.separator)())
155 } else {
156 None
157 }
158 }
159 } else {
160 let item = self.iter.next();
161 self.started = item.is_some();
162 item
163 }
164 }
165
166 fn size_hint(&self) -> (usize, Option<usize>) {
167 intersperse_size_hint(&self.iter, self.started, self.next_item.is_some())
168 }
169
170 fn fold<B, F>(self, init: B, f: F) -> B
171 where
172 Self: Sized,
173 F: FnMut(B, Self::Item) -> B,
174 {
175 intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item)
176 }
177}
178
179fn intersperse_size_hint<I>(iter: &I, started: bool, next_is_some: bool) -> (usize, Option<usize>)
180where
181 I: Iterator,
182{
183 let (lo, hi) = iter.size_hint();
184 (
185 lo.saturating_sub(!started as usize)
186 .saturating_add(next_is_some as usize)
187 .saturating_add(lo),
188 hi.and_then(|hi| {
189 hi.saturating_sub(!started as usize)
190 .saturating_add(next_is_some as usize)
191 .checked_add(hi)
192 }),
193 )
194}
195
196fn intersperse_fold<I, B, F, G>(
197 mut iter: I,
198 init: B,
199 mut f: F,
200 mut separator: G,
201 started: bool,
202 mut next_item: Option<I::Item>,
203) -> B
204where
205 I: Iterator,
206 F: FnMut(B, I::Item) -> B,
207 G: FnMut() -> I::Item,
208{
209 let mut accum = init;
210
211 let first = if started {
212 next_item.take()
213 } else {
214 let n = iter.next();
215 if n.is_none() {
217 return accum;
218 }
219 n
220 };
221 if let Some(x) = first {
222 accum = f(accum, x);
223 }
224
225 iter.fold(accum, |mut accum, x| {
226 accum = f(accum, separator());
227 accum = f(accum, x);
228 accum
229 })
230}