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
use std::future::{Future, IntoFuture};

// use either::Either;
// use futures::future;

use crate::requests::{HasPayload, Output};

/// A ready-to-send Telegram request.
// FIXME(waffle): Write better doc for the trait
///
/// ## Implementation notes
///
/// It is not recommended to do any kind of _work_ in `send` or `send_ref`.
/// Instead it's recommended to do all the (possible) stuff in the returned
/// future. In other words — keep it lazy.
///
/// This is crucial for request wrappers which may want to cancel and/or never
/// send the underlying request. E.g.: [`Throttle<B>`]'s `send_ref` calls
/// `B::send_ref` while _not_ meaning to really send the request at the moment.
///
/// [`Throttle<B>`]: crate::adaptors::Throttle
#[cfg_attr(all(any(docsrs, dep_docsrs), feature = "nightly"), doc(notable_trait))]
pub trait Request
where
    Self: HasPayload,
    Self: IntoFuture<Output = Result<Output<Self>, Self::Err>, IntoFuture = Self::Send>,
{
    /// The type of an error that may happen while sending a request to
    /// Telegram.
    type Err: std::error::Error + Send;

    /// The type of the future returned by the [`send`](Request::send) method.
    type Send: Future<Output = Result<Output<Self>, Self::Err>> + Send;

    /// A type of the future returned by the [`send_ref`](Request::send_ref)
    /// method.
    // Note: it intentionally forbids borrowing from `self` though we couldn't allow
    // borrowing without GATs anyway.
    type SendRef: Future<Output = Result<Output<Self>, Self::Err>> + Send;

    /// Send this request.
    ///
    /// ## Examples
    ///
    /// ```
    /// # async {
    /// use teloxide_core::{
    ///     payloads::GetMe,
    ///     requests::{JsonRequest, Request},
    ///     types::Me,
    ///     Bot,
    /// };
    ///
    /// let bot = Bot::new("TOKEN");
    ///
    /// // Note: it's recommended to `Requester` instead of creating requests directly
    /// let method = GetMe::new();
    /// let request = JsonRequest::new(bot, method);
    /// let request_clone = request.clone();
    /// let _: Me = request.send().await.unwrap();
    ///
    /// // You can also just await requests, without calling `send`:
    /// let _: Me = request_clone.await.unwrap();
    /// # };
    /// ```
    #[must_use = "Futures are lazy and do nothing unless polled or awaited"]
    fn send(self) -> Self::Send;

    /// Send this request by reference.
    ///
    /// This method is analogous to [`send`](Request::send), but it doesn't take
    /// the ownership of `self`. This allows to send the same (or slightly
    /// different) requests over and over.
    ///
    /// Also, it is expected that calling this method is better than just
    /// cloning requests. (Because instead of copying all the data
    /// and then serializing it, this method should just serialize the data.)
    ///
    /// ## Examples
    ///
    /// ```
    /// # async {
    /// use teloxide_core::{prelude::*, requests::Request, types::ChatId, Bot};
    ///
    /// let bot = Bot::new("TOKEN");
    /// # let chat_ids = vec![1i64, 2, 3, 4].into_iter().map(ChatId).map(Into::into).collect::<Vec<_>>();
    ///
    /// let mut req = bot.send_message(ChatId(0xAAAAAAAA), "Hi there!");
    /// for chat_id in chat_ids {
    ///     req.chat_id = chat_id;
    ///     req.send_ref().await.unwrap();
    /// }
    /// # };
    /// ```
    #[must_use = "Futures are lazy and do nothing unless polled or awaited"]
    fn send_ref(&self) -> Self::SendRef;

    #[cfg(feature = "erased")]
    fn erase<'a>(self) -> crate::adaptors::erased::ErasedRequest<'a, Self::Payload, Self::Err>
    where
        Self: Sized + 'a,
    {
        crate::adaptors::erased::ErasedRequest::erase(self)
    }
}

// FIXME: re-introduce `Either` impls once `Either: IntoFuture` (or make out own
// `Either`) (same for `Requester`)

// impl<L, R> Request for Either<L, R>
// where
//     L: Request,
//     R: Request<Payload = L::Payload, Err = L::Err>,
// {
//     type Err = L::Err;

//     type Send = future::Either<L::Send, R::Send>;

//     type SendRef = future::Either<L::SendRef, R::SendRef>;

//     fn send(self) -> Self::Send {
//         self.map_left(<_>::send)
//             .map_right(<_>::send)
//             .either(future::Either::Left, future::Either::Right)
//     }

//     fn send_ref(&self) -> Self::SendRef {
//         self.as_ref()
//             .map_left(<_>::send_ref)
//             .map_right(<_>::send_ref)
//             .either(future::Either::Left, future::Either::Right)
//     }
// }