Skip to main content

lender/adapters/
mod.rs

1use core::{marker::PhantomData, ops::ControlFlow};
2
3mod chain;
4mod chunk;
5mod chunky;
6mod cloned;
7mod copied;
8mod cycle;
9mod enumerate;
10mod filter;
11mod filter_map;
12mod flatten;
13mod fuse;
14mod inspect;
15mod intersperse;
16mod iter;
17mod map;
18mod map_into_iter;
19mod map_while;
20mod mutate;
21mod owned;
22mod peekable;
23mod rev;
24mod scan;
25mod skip;
26mod skip_while;
27mod step_by;
28mod take;
29mod take_while;
30mod zip;
31
32pub use intersperse::{Intersperse, IntersperseWith};
33pub use zip::zip;
34
35pub use self::{
36    chain::Chain,
37    chunk::Chunk,
38    chunky::Chunky,
39    cloned::Cloned,
40    copied::Copied,
41    cycle::Cycle,
42    enumerate::Enumerate,
43    filter::Filter,
44    filter_map::FilterMap,
45    flatten::{FlatMap, Flatten},
46    fuse::Fuse,
47    inspect::Inspect,
48    iter::Iter,
49    map::Map,
50    map_into_iter::MapIntoIter,
51    map_while::MapWhile,
52    mutate::Mutate,
53    owned::Owned,
54    peekable::Peekable,
55    rev::Rev,
56    scan::Scan,
57    skip::Skip,
58    skip_while::SkipWhile,
59    step_by::StepBy,
60    take::Take,
61    take_while::TakeWhile,
62    zip::Zip,
63};
64
65use crate::{
66    Empty, ExtendLender, FallibleEmpty, FallibleLend, FallibleLender, FallibleLending,
67    IntoFallibleLender, IntoLender, Lend, Lender, Lending, NonFallibleAdapter, TupleLend, empty,
68    fallible_empty,
69    try_trait_v2::{ChangeOutputType, FromResidual, Residual, Try},
70};
71
72// pub use zip::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
73
74/// Private adapter. Turns a [`Lender`], where [`Lend`] implements
75/// [`Try`], into a [`Lender`] of `<Lend as Try>::Output`.
76///
77/// # Safety
78///
79/// The residual of the lender cannot outlive it, otherwise UB.
80#[doc(hidden)]
81pub struct TryShunt<'this, L: Lender>
82where
83    for<'all> Lend<'all, L>: Try,
84{
85    lender: L,
86    residual: &'this mut Option<<Lend<'this, L> as Try>::Residual>,
87}
88
89impl<'lend, L: Lender> Lending<'lend> for TryShunt<'_, L>
90where
91    for<'all> Lend<'all, L>: Try,
92{
93    type Lend = <Lend<'lend, L> as Try>::Output;
94}
95
96impl<'this, L: Lender> Lender for TryShunt<'this, L>
97where
98    for<'all> Lend<'all, L>: Try,
99{
100    // SAFETY: the lend is the output of the Try type from L
101    crate::unsafe_assume_covariance!();
102    #[inline]
103    fn next(&mut self) -> Option<Lend<'_, Self>> {
104        if self.residual.is_some() {
105            return None;
106        }
107        if let Some(x) = self.lender.next() {
108            match x.branch() {
109                ControlFlow::Continue(x) => return Some(x),
110                ControlFlow::Break(x) => {
111                    // SAFETY: residual is manually guaranteed to be the only lend alive
112                    *self.residual = Some(unsafe {
113                        core::mem::transmute::<
114                            <Lend<'_, L> as Try>::Residual,
115                            <Lend<'this, L> as Try>::Residual,
116                        >(x)
117                    });
118                }
119            }
120        }
121        None
122    }
123
124    #[inline]
125    fn size_hint(&self) -> (usize, Option<usize>) {
126        let (_, upper) = self.lender.size_hint();
127        (0, upper)
128    }
129}
130
131#[inline]
132pub(crate) fn try_process<'a, L, F, U>(lender: L, mut f: F) -> ChangeOutputType<Lend<'a, L>, U>
133where
134    L: Lender + 'a,
135    for<'all> Lend<'all, L>: Try,
136    for<'all> <Lend<'all, L> as Try>::Residual: Residual<U>,
137    for<'all> F: FnMut(TryShunt<'all, L>) -> U,
138{
139    let _ = L::__check_covariance(crate::CovariantProof::new());
140    let mut residual = None;
141    // SAFETY: residual is manually guaranteed to be the only lend alive after `f`.
142    #[allow(clippy::deref_addrof)]
143    let reborrow = unsafe { &mut *(&raw mut residual) };
144    let shunt = TryShunt {
145        lender,
146        residual: reborrow,
147    };
148    let value = f(shunt);
149    match residual {
150        Some(r) => FromResidual::from_residual(r),
151        None => Try::from_output(value),
152    }
153}
154
155#[doc(hidden)]
156/// Private adapter. Marks a [`Lender`], where [`Lend`] implements
157/// [`TupleLend`], as a [`Lender`] of `<Lend as TupleLend>::First`.
158pub struct FirstShunt<L>(PhantomData<L>);
159
160#[doc(hidden)]
161/// Private adapter. Marks a [`Lender`], where [`Lend`] implements
162/// [`TupleLend`], as a [`Lender`] of `<Lend as TupleLend>::Second`.
163pub struct SecondShunt<L>(PhantomData<L>);
164
165impl<'lend, L: Lender> Lending<'lend> for FirstShunt<L>
166where
167    for<'all> Lend<'all, L>: TupleLend<'all>,
168{
169    type Lend = <Lend<'lend, L> as TupleLend<'lend>>::First;
170}
171
172impl<'lend, L: Lender> Lending<'lend> for SecondShunt<L>
173where
174    for<'all> Lend<'all, L>: TupleLend<'all>,
175{
176    type Lend = <Lend<'lend, L> as TupleLend<'lend>>::Second;
177}
178
179impl<L: Lender> IntoLender for FirstShunt<L>
180where
181    for<'all> Lend<'all, L>: TupleLend<'all>,
182{
183    type Lender = Empty<Self>;
184    #[inline(always)]
185    fn into_lender(self) -> <Self as IntoLender>::Lender {
186        empty()
187    }
188}
189
190impl<L: Lender> IntoLender for SecondShunt<L>
191where
192    for<'all> Lend<'all, L>: TupleLend<'all>,
193{
194    type Lender = Empty<Self>;
195    #[inline(always)]
196    fn into_lender(self) -> <Self as IntoLender>::Lender {
197        empty()
198    }
199}
200
201impl<'lend, L: FallibleLender> FallibleLending<'lend> for FirstShunt<L>
202where
203    for<'all> FallibleLend<'all, L>: TupleLend<'all>,
204{
205    type Lend = <FallibleLend<'lend, L> as TupleLend<'lend>>::First;
206}
207
208impl<'lend, L: FallibleLender> FallibleLending<'lend> for SecondShunt<L>
209where
210    for<'all> FallibleLend<'all, L>: TupleLend<'all>,
211{
212    type Lend = <FallibleLend<'lend, L> as TupleLend<'lend>>::Second;
213}
214
215impl<L: FallibleLender> IntoFallibleLender for FirstShunt<L>
216where
217    for<'all> FallibleLend<'all, L>: TupleLend<'all>,
218{
219    type Error = L::Error;
220
221    type FallibleLender = FallibleEmpty<Self, L::Error>;
222    #[inline(always)]
223    fn into_fallible_lender(self) -> <Self as IntoFallibleLender>::FallibleLender {
224        fallible_empty()
225    }
226}
227
228impl<L: FallibleLender> IntoFallibleLender for SecondShunt<L>
229where
230    for<'all> FallibleLend<'all, L>: TupleLend<'all>,
231{
232    type Error = L::Error;
233
234    type FallibleLender = FallibleEmpty<Self, L::Error>;
235    #[inline(always)]
236    fn into_fallible_lender(self) -> <Self as IntoFallibleLender>::FallibleLender {
237        fallible_empty()
238    }
239}
240
241#[inline]
242pub(crate) fn unzip<L, ExtA, ExtB>(mut lender: L) -> (ExtA, ExtB)
243where
244    L: Sized + Lender,
245    for<'all> Lend<'all, L>: TupleLend<'all>,
246    ExtA: Default + ExtendLender<FirstShunt<L>>,
247    ExtB: Default + ExtendLender<SecondShunt<L>>,
248{
249    let mut a = ExtA::default();
250    let mut b = ExtB::default();
251    let sz = lender.size_hint().0;
252    if sz > 0 {
253        a.extend_lender_reserve(sz);
254        b.extend_lender_reserve(sz);
255    }
256    while let Some(lend) = lender.next() {
257        let (x, y) = lend.tuple_lend();
258        a.extend_lender_one(x);
259        b.extend_lender_one(y);
260    }
261    (a, b)
262}
263
264#[inline]
265pub(crate) fn fallible_unzip<L, ExtA, ExtB>(mut lender: L) -> Result<(ExtA, ExtB), L::Error>
266where
267    L: Sized + FallibleLender,
268    for<'all> FallibleLend<'all, L>: TupleLend<'all>,
269    ExtA: Default
270        + for<'this> ExtendLender<
271            NonFallibleAdapter<'this, <FirstShunt<L> as IntoFallibleLender>::FallibleLender>,
272        >,
273    ExtB: Default
274        + for<'this> ExtendLender<
275            NonFallibleAdapter<'this, <SecondShunt<L> as IntoFallibleLender>::FallibleLender>,
276        >,
277{
278    let mut a = ExtA::default();
279    let mut b = ExtB::default();
280    let sz = lender.size_hint().0;
281    if sz > 0 {
282        a.extend_lender_reserve(sz);
283        b.extend_lender_reserve(sz);
284    }
285    while let Some(lend) = lender.next()? {
286        let (x, y) = lend.tuple_lend();
287        a.extend_lender_one(x);
288        b.extend_lender_one(y);
289    }
290    Ok((a, b))
291}