1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Map adapters.
use core::{
    ops::{Generator, GeneratorState},
    pin::Pin,
};
use pin_project::pin_project;

/// Generator adapter that applies provided function to each yielded value.
#[pin_project]
pub struct MapYield<G, F> {
    #[pin]
    pub(crate) gen: G,
    pub(crate) func: F,
}
impl<R, G, F, T> Generator<R> for MapYield<G, F>
where
    G: Generator<R>,
    F: FnMut(G::Yield) -> T,
{
    type Yield = T;
    type Return = G::Return;

    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
        let this = self.project();
        match this.gen.resume(arg) {
            GeneratorState::Complete(c) => GeneratorState::Complete(c),
            GeneratorState::Yielded(y) => GeneratorState::Yielded((this.func)(y)),
        }
    }
}

/// Generator adapter that applies provided function to return value.
#[pin_project]
pub struct MapReturn<G, F> {
    #[pin]
    pub(crate) gen: G,
    pub(crate) func: F,
}

impl<R, G, F, T> Generator<R> for MapReturn<G, F>
where
    G: Generator<R>,
    F: FnMut(G::Return) -> T,
{
    type Yield = G::Yield;
    type Return = T;

    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
        let this = self.project();
        match this.gen.resume(arg) {
            GeneratorState::Complete(c) => GeneratorState::Complete((this.func)(c)),
            GeneratorState::Yielded(y) => GeneratorState::Yielded(y),
        }
    }
}

/// Generator adapter that applies provided function to resume arguments.
#[pin_project]
pub struct MapResume<G, F> {
    #[pin]
    pub(crate) gen: G,
    pub(crate) func: F,
}

impl<ResumeInner, ResumeOuter, G, F> Generator<ResumeOuter> for MapResume<G, F>
where
    G: Generator<ResumeInner>,
    F: FnMut(ResumeOuter) -> ResumeInner,
{
    type Yield = G::Yield;
    type Return = G::Return;

    fn resume(self: Pin<&mut Self>, arg: ResumeOuter) -> GeneratorState<Self::Yield, Self::Return> {
        let this = self.project();
        let arg = (this.func)(arg);
        this.gen.resume(arg)
    }
}