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};
64use crate::{
65    empty,
66    try_trait_v2::{ChangeOutputType, FromResidual, Residual, Try},
67    Empty, ExtendLender, IntoLender, Lend, Lender, Lending, TupleLend,
68};
69
70// pub use zip::{TrustedRandomAccess, TrustedRandomAccessNoCoerce};
71
72/// Private adapter. Turns a `Lender`, where `Lend` implements `Try`, into a `Lender` of `<Lend as Try>::Output`.
73/// # Safety
74/// The residual of the lender cannot outlive it, otherwise UB.
75pub struct TryShunt<'this, L: Lender>
76where
77    for<'all> Lend<'all, L>: Try,
78{
79    lender: L,
80    residual: &'this mut Option<<Lend<'this, L> as Try>::Residual>,
81}
82impl<'lend, L: Lender> Lending<'lend> for TryShunt<'_, L>
83where
84    for<'all> Lend<'all, L>: Try,
85{
86    type Lend = <Lend<'lend, L> as Try>::Output;
87}
88impl<'this, L: Lender> Lender for TryShunt<'this, L>
89where
90    for<'all> Lend<'all, L>: Try,
91{
92    fn next(&mut self) -> Option<Lend<'_, Self>> {
93        if let Some(x) = self.lender.next() {
94            match x.branch() {
95                ControlFlow::Continue(x) => return Some(x),
96                ControlFlow::Break(x) => {
97                    // SAFETY: residual is manually guaranteed to be the only lend alive
98                    *self.residual = Some(unsafe {
99                        core::mem::transmute::<<Lend<'_, L> as Try>::Residual, <Lend<'this, L> as Try>::Residual>(x)
100                    });
101                }
102            }
103        }
104        None
105    }
106    fn size_hint(&self) -> (usize, Option<usize>) {
107        let (_, upper) = self.lender.size_hint();
108        (0, upper)
109    }
110}
111pub(crate) fn try_process<'a, L, F, U>(lender: L, mut f: F) -> ChangeOutputType<Lend<'a, L>, U>
112where
113    L: Lender + 'a,
114    for<'all> Lend<'all, L>: Try,
115    for<'all> <Lend<'all, L> as Try>::Residual: Residual<U>,
116    F: FnMut(TryShunt<'a, L>) -> U,
117{
118    let mut residual = None;
119    // SAFETY: residual is manually guaranteed to be the only lend alive after `f`.
120    let reborrow = unsafe { &mut *(&mut residual as *mut _) };
121    let shunt = TryShunt { lender, residual: reborrow };
122    let value = f(shunt);
123    match residual {
124        Some(r) => FromResidual::from_residual(r),
125        None => Try::from_output(value),
126    }
127}
128
129/// Private adapter. Marks a `Lender`, where `Lend` implements `TupleLend`, as a `Lender` of `<Lend as TupleLend>::First`.
130pub struct FirstShunt<L>(PhantomData<L>);
131/// Private adapter. Marks a `Lender`, where `Lend` implements `TupleLend`, as a `Lender` of `<Lend as TupleLend>::Second`.
132pub struct SecondShunt<L>(PhantomData<L>);
133impl<'lend, L: Lender> Lending<'lend> for FirstShunt<L>
134where
135    for<'all> Lend<'all, L>: TupleLend<'all>,
136{
137    type Lend = <Lend<'lend, L> as TupleLend<'lend>>::First;
138}
139impl<'lend, L: Lender> Lending<'lend> for SecondShunt<L>
140where
141    for<'all> Lend<'all, L>: TupleLend<'all>,
142{
143    type Lend = <Lend<'lend, L> as TupleLend<'lend>>::Second;
144}
145impl<L: Lender> IntoLender for FirstShunt<L>
146where
147    for<'all> Lend<'all, L>: TupleLend<'all>,
148{
149    type Lender = Empty<Self>;
150    fn into_lender(self) -> <Self as IntoLender>::Lender {
151        empty()
152    }
153}
154impl<L: Lender> IntoLender for SecondShunt<L>
155where
156    for<'all> Lend<'all, L>: TupleLend<'all>,
157{
158    type Lender = Empty<Self>;
159    fn into_lender(self) -> <Self as IntoLender>::Lender {
160        empty()
161    }
162}
163
164pub(crate) fn unzip<L, ExtA, ExtB>(mut lender: L) -> (ExtA, ExtB)
165where
166    L: Sized + Lender,
167    for<'all> Lend<'all, L>: TupleLend<'all>,
168    ExtA: Default + ExtendLender<FirstShunt<L>>,
169    ExtB: Default + ExtendLender<SecondShunt<L>>,
170{
171    let mut a = ExtA::default();
172    let mut b = ExtB::default();
173    let sz = lender.size_hint().0;
174    if sz > 0 {
175        a.extend_lender_reserve(sz);
176        b.extend_lender_reserve(sz);
177    }
178    while let Some(lend) = lender.next() {
179        let (x, y) = lend.tuple_lend();
180        a.extend_lender_one(x);
181        b.extend_lender_one(y);
182    }
183    (a, b)
184}