Skip to main content

lender/fallible_adapters/
intersperse.rs

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