Skip to main content

lender/adapters/
intersperse.rs

1use core::fmt;
2
3use crate::{FusedLender, Lend, Lender, Lending, Peekable};
4
5/// A lender that inserts a separator between adjacent elements of the
6/// underlying lender.
7///
8/// This `struct` is created by the
9/// [`intersperse()`](crate::Lender::intersperse) method on
10/// [`Lender`].
11// Clone is not implemented because the inner Peekable is not Clone.
12#[must_use = "lenders are lazy and do nothing unless consumed"]
13pub struct Intersperse<'this, L>
14where
15    for<'all> Lend<'all, L>: Clone,
16    L: Lender,
17{
18    // Field order ensures lender drops last
19    separator: Lend<'this, L>,
20    needs_sep: bool,
21    lender: Peekable<'this, L>,
22}
23
24impl<'this, L> Intersperse<'this, L>
25where
26    for<'all> Lend<'all, L>: Clone,
27    L: Lender,
28{
29    #[inline(always)]
30    pub(crate) fn new(lender: L, separator: Lend<'this, L>) -> Self {
31        let _ = L::__check_covariance(crate::CovariantProof::new());
32        Self {
33            separator,
34            needs_sep: false,
35            lender: lender.peekable(),
36        }
37    }
38
39    /// Returns the inner lender.
40    #[inline(always)]
41    pub fn into_inner(self) -> L {
42        self.lender.into_inner()
43    }
44
45    /// Returns the inner lender and the separator value.
46    #[inline(always)]
47    pub fn into_parts(self) -> (L, Lend<'this, L>) {
48        (self.lender.into_inner(), self.separator)
49    }
50}
51
52impl<L: fmt::Debug> fmt::Debug for Intersperse<'_, L>
53where
54    for<'all> Lend<'all, L>: Clone + fmt::Debug,
55    L: Lender,
56{
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        f.debug_struct("Intersperse")
59            .field("lender", &self.lender)
60            .field("separator", &self.separator)
61            .field("needs_sep", &self.needs_sep)
62            .finish()
63    }
64}
65
66impl<'lend, L> Lending<'lend> for Intersperse<'_, L>
67where
68    for<'all> Lend<'all, L>: Clone,
69    L: Lender,
70{
71    type Lend = Lend<'lend, L>;
72}
73
74impl<'this, L> Lender for Intersperse<'this, L>
75where
76    for<'all> Lend<'all, L>: Clone,
77    L: Lender,
78{
79    // SAFETY: the lend is that of L
80    crate::unsafe_assume_covariance!();
81    #[inline]
82    fn next(&mut self) -> Option<Lend<'_, Self>> {
83        if self.needs_sep && self.lender.peek().is_some() {
84            self.needs_sep = false;
85            // SAFETY: 'this: 'lend
86            Some(unsafe {
87                core::mem::transmute::<Lend<'this, Self>, Lend<'_, Self>>(self.separator.clone())
88            })
89        } else {
90            self.needs_sep = true;
91            self.lender.next()
92        }
93    }
94
95    #[inline]
96    fn fold<B, F>(mut self, init: B, mut f: F) -> B
97    where
98        Self: Sized,
99        F: FnMut(B, Lend<'_, Self>) -> B,
100    {
101        let mut acc = init;
102        if !self.needs_sep {
103            if let Some(x) = self.lender.next() {
104                acc = f(acc, x);
105            } else {
106                return acc;
107            }
108        }
109        self.lender.fold(acc, |mut acc, x| {
110            acc = f(acc, self.separator.clone());
111            acc = f(acc, x);
112            acc
113        })
114    }
115
116    #[inline(always)]
117    fn size_hint(&self) -> (usize, Option<usize>) {
118        intersperse_size_hint(&self.lender, self.needs_sep)
119    }
120}
121
122/// A lender that inserts an element computed by a closure between adjacent
123/// elements of the underlying lender.
124///
125/// This `struct` is created by the
126/// [`intersperse_with()`](crate::Lender::intersperse_with)
127/// method on [`Lender`].
128// Clone is not implemented because the inner Peekable is not Clone.
129#[must_use = "lenders are lazy and do nothing unless consumed"]
130pub struct IntersperseWith<'this, L, G>
131where
132    L: Lender,
133{
134    separator: G,
135    lender: Peekable<'this, L>,
136    needs_sep: bool,
137}
138
139impl<'this, L, G> IntersperseWith<'this, L, G>
140where
141    L: Lender,
142    G: FnMut() -> Lend<'this, L>,
143{
144    #[inline(always)]
145    pub(crate) fn new(lender: L, separator: G) -> Self {
146        let _ = L::__check_covariance(crate::CovariantProof::new());
147        Self {
148            lender: Peekable::new(lender),
149            separator,
150            needs_sep: false,
151        }
152    }
153
154    /// Returns the inner lender.
155    #[inline(always)]
156    pub fn into_inner(self) -> L {
157        self.lender.into_inner()
158    }
159
160    /// Returns the inner lender and the separator function.
161    #[inline(always)]
162    pub fn into_parts(self) -> (L, G) {
163        (self.lender.into_inner(), self.separator)
164    }
165}
166
167impl<L: fmt::Debug, G> fmt::Debug for IntersperseWith<'_, L, G>
168where
169    L: Lender,
170    for<'all> Lend<'all, L>: fmt::Debug,
171{
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        f.debug_struct("IntersperseWith")
174            .field("lender", &self.lender)
175            .field("needs_sep", &self.needs_sep)
176            .finish_non_exhaustive()
177    }
178}
179
180impl<'lend, 'this, L, G> Lending<'lend> for IntersperseWith<'this, L, G>
181where
182    L: Lender,
183    G: FnMut() -> Lend<'this, L>,
184{
185    type Lend = Lend<'lend, L>;
186}
187
188impl<'this, L, G> Lender for IntersperseWith<'this, L, G>
189where
190    L: Lender,
191    G: FnMut() -> Lend<'this, L>,
192{
193    // SAFETY: the lend is that of L
194    crate::unsafe_assume_covariance!();
195    #[inline]
196    fn next(&mut self) -> Option<Lend<'_, Self>> {
197        if self.needs_sep && self.lender.peek().is_some() {
198            self.needs_sep = false;
199            // SAFETY: 'this: 'lend
200            Some(unsafe { core::mem::transmute::<Lend<'this, L>, Lend<'_, L>>((self.separator)()) })
201        } else {
202            self.needs_sep = true;
203            self.lender.next()
204        }
205    }
206
207    #[inline]
208    fn fold<B, F>(mut self, init: B, mut f: F) -> B
209    where
210        Self: Sized,
211        F: FnMut(B, Lend<'_, Self>) -> B,
212    {
213        let mut acc = init;
214        if !self.needs_sep {
215            if let Some(x) = self.lender.next() {
216                acc = f(acc, x);
217            } else {
218                return acc;
219            }
220        }
221        self.lender.fold(acc, |mut acc, x| {
222            acc = f(acc, (self.separator)());
223            acc = f(acc, x);
224            acc
225        })
226    }
227
228    #[inline(always)]
229    fn size_hint(&self) -> (usize, Option<usize>) {
230        intersperse_size_hint(&self.lender, self.needs_sep)
231    }
232}
233
234#[inline]
235fn intersperse_size_hint<L>(lender: &L, needs_sep: bool) -> (usize, Option<usize>)
236where
237    L: Lender,
238{
239    let (lo, hi) = lender.size_hint();
240    let next_is_elem = !needs_sep;
241    (
242        lo.saturating_sub(next_is_elem as usize).saturating_add(lo),
243        hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)),
244    )
245}
246
247impl<'this, L> FusedLender for Intersperse<'this, L>
248where
249    for<'all> Lend<'all, L>: Clone,
250    L: FusedLender,
251{
252}
253
254impl<'this, L, G> FusedLender for IntersperseWith<'this, L, G>
255where
256    L: FusedLender,
257    G: FnMut() -> Lend<'this, L>,
258{
259}