asynciter/iterimpl/
intersperse.rs

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