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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use std::{
    pin::Pin,
    task::{Context, Poll},
};

use crate::{actor::Actor, fut::future::ActorFuture};

mod and_then;
mod map_err;
mod map_ok;

pub use and_then::AndThen;
pub use map_err::MapErr;
pub use map_ok::MapOk;

mod private_try_act_future {
    use super::{Actor, ActorFuture};

    pub trait Sealed<A> {}

    impl<A, F, T, E> Sealed<A> for F
    where
        A: Actor,
        F: ?Sized + ActorFuture<A, Output = Result<T, E>>,
    {
    }
}

/// A convenience for actor futures that return `Result` values that includes
/// a variety of adapters tailored to such actor futures.
pub trait ActorTryFuture<A: Actor>: ActorFuture<A> + private_try_act_future::Sealed<A> {
    /// The type of successful values yielded by this actor future
    type Ok;

    /// The type of failures yielded by this actor  future
    type Error;

    /// Poll this `ActorTryFuture` as if it were a `ActorFuture`.
    ///
    /// This method is a stopgap for a compiler limitation that prevents us from
    /// directly inheriting from the `ActorFuture` trait; in the actor future it
    /// won't be needed.
    fn try_poll(
        self: Pin<&mut Self>,
        srv: &mut A,
        ctx: &mut A::Context,
        task: &mut Context<'_>,
    ) -> Poll<Result<Self::Ok, Self::Error>>;
}

impl<A, F, T, E> ActorTryFuture<A> for F
where
    A: Actor,
    F: ActorFuture<A, Output = Result<T, E>> + ?Sized,
{
    type Ok = T;
    type Error = E;

    fn try_poll(
        self: Pin<&mut Self>,
        srv: &mut A,
        ctx: &mut A::Context,
        task: &mut Context<'_>,
    ) -> Poll<F::Output> {
        self.poll(srv, ctx, task)
    }
}

/// Adapters specific to [`Result`]-returning actor futures
pub trait ActorTryFutureExt<A: Actor>: ActorTryFuture<A> {
    /// Executes another actor future after this one resolves successfully.
    /// The success value is passed to a closure to create this subsequent
    /// actor future.
    ///
    /// The provided closure `f` will only be called if this actor future is
    /// resolved to an [`Ok`]. If this actor future resolves to an  [`Err`],
    /// panics, or is dropped, then the provided closure will never
    /// be invoked. The [`Error`](ActorTryFuture::Error) type of
    /// this actor future and the actor future returned by `f` have to match.
    ///
    /// Note that this method consumes the actor future it is called on and
    /// returns a wrapped version of it.
    fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
    where
        F: FnOnce(Self::Ok, &mut A, &mut A::Context) -> Fut,
        Fut: ActorTryFuture<A, Error = Self::Error>,
        Self: Sized,
    {
        and_then::new(self, f)
    }

    /// Maps this actor future's success value to a different value.
    ///
    /// This method can be used to change the [`Ok`](ActorTryFuture::Ok) type
    /// of the actor future into a different type. It is similar to the
    /// [`Result::map`]  method. You can use this method to chain along a
    /// computation once the actor future has been resolved.
    ///
    /// The provided closure `f` will only be called if this actor future is
    /// resolved to an [`Ok`]. If it resolves to an [`Err`], panics, or is
    /// dropped, then the provided closure will never be invoked.
    ///
    /// Note that this method consumes the actor future it is called on and
    /// returns a wrapped version of it.
    fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
    where
        F: FnOnce(Self::Ok, &mut A, &mut A::Context) -> T,
        Self: Sized,
    {
        MapOk::new(self, f)
    }

    /// Maps this actor future's error value to a different value.
    ///
    /// This method can be used to change the [`Error`](ActorTryFuture::Error)
    /// type of the actor future into a different type. It is similar to the
    /// [`Result::map_err`] method.
    ///
    /// The provided closure `f` will only be called if this actor future is
    /// resolved to an [`Err`]. If it resolves to an [`Ok`], panics, or is
    /// dropped, then the provided closure will never be invoked.
    ///
    /// Note that this method consumes the actor future it is called on and
    /// returns a wrapped version of it.
    fn map_err<T, F>(self, f: F) -> MapErr<Self, F>
    where
        F: FnOnce(Self::Error, &mut A, &mut A::Context) -> T,
        Self: Sized,
    {
        MapErr::new(self, f)
    }
}

impl<A, F> ActorTryFutureExt<A> for F
where
    A: Actor,
    F: ActorTryFuture<A> + ?Sized,
{
}