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
use std::future::Future;
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: HasPayload {
/*
* Could be mostly `core::future::IntoFuture` though there is no reason to
* use it before it's integrated in async/await
*/
/// 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 _: Me = request.send().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)
}
}
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)
}
}
