mirror of
https://github.com/teloxide/teloxide.git
synced 2025-03-13 11:18:17 +01:00
requests redesign part 0
This commit introduces 3 traits mentioned in requests redesign proposal: - `Payload` - `HasPayload` - `Request` Also it adds `Output<T>` alias to `<<T as HasPayload>::Payload as Payload>::Output`
This commit is contained in:
parent
45a55c66de
commit
76d47276f6
5 changed files with 146 additions and 1 deletions
|
@ -7,7 +7,8 @@
|
|||
// ```console
|
||||
// $ RUSTDOCFLAGS="--cfg docsrs" cargo doc --open --all-features
|
||||
// ```
|
||||
#![cfg_attr(all(docsrs, feature = "nightly"), feature(doc_cfg))]
|
||||
#![cfg_attr(all(docsrs, feature = "nightly"), feature(doc_cfg, doc_spotlight))]
|
||||
#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))]
|
||||
#![forbid(unsafe_code)]
|
||||
//#![deny(missing_docs)]
|
||||
|
||||
|
|
45
src/requests/has_payload.rs
Normal file
45
src/requests/has_payload.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
use crate::requests::Payload;
|
||||
|
||||
/// Represent types that have payload inside it. E.g.: the payload itself or a
|
||||
/// `Request`.
|
||||
///
|
||||
/// This trait is something between [`DerefMut`] and [`BorrowMut`] — it allows
|
||||
/// only one implementation per type (the [output] is associated type, not a
|
||||
/// generic), have implementations for all types `P` such `P: `[`Payload`], but
|
||||
/// have no magic compiler support like [`DerefMut`] does nor does it require
|
||||
/// any laws about `Eq`, `Ord` and `Hash` as [`BorrowMut`] does.
|
||||
///
|
||||
/// Also [output] type is bounded by [`Payload`] trait.
|
||||
///
|
||||
/// This trait is mostly used to implement payload setters (on both payloads &
|
||||
/// requests), so you probably won't find yourself using it directly.
|
||||
///
|
||||
/// [`DerefMut`]: std::ops::DerefMut
|
||||
/// [`BorrowMut`]: std::borrow::BorrowMut
|
||||
/// [`Payload`]: crate::requests::Payload
|
||||
/// [output]: HasPayload::Payload
|
||||
pub trait HasPayload {
|
||||
/// Type of the payload contained.
|
||||
type Payload: Payload;
|
||||
|
||||
/// Gain mutable access to the underlying payload.
|
||||
fn payload_mut(&mut self) -> &mut Self::Payload;
|
||||
|
||||
/// Gain immutable access to the underlying payload.
|
||||
fn payload_ref(&self) -> &Self::Payload;
|
||||
}
|
||||
|
||||
impl<P> HasPayload for P
|
||||
where
|
||||
P: Payload,
|
||||
{
|
||||
type Payload = Self;
|
||||
|
||||
fn payload_mut(&mut self) -> &mut Self::Payload {
|
||||
self
|
||||
}
|
||||
|
||||
fn payload_ref(&self) -> &Self::Payload {
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,5 +1,11 @@
|
|||
//! API requests.
|
||||
|
||||
mod has_payload;
|
||||
mod payload;
|
||||
mod request;
|
||||
|
||||
pub use self::{has_payload::HasPayload, payload::Payload, request::Request};
|
||||
|
||||
mod all;
|
||||
mod utils;
|
||||
|
||||
|
@ -8,6 +14,10 @@ pub use all::*;
|
|||
/// A type that is returned after making a request to Telegram.
|
||||
pub type ResponseResult<T> = Result<T, crate::RequestError>;
|
||||
|
||||
/// Output of a [`Payload`] in [`HasPayload`]. Alias to
|
||||
/// `<<T as HasPayload>::Payload as Payload>::Output`.
|
||||
pub type Output<T> = <<T as HasPayload>::Payload as Payload>::Output;
|
||||
|
||||
/// Designates an API request.
|
||||
#[async_trait::async_trait]
|
||||
pub trait RequestOld {
|
||||
|
|
20
src/requests/payload.rs
Normal file
20
src/requests/payload.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
/// Payload of a request.
|
||||
///
|
||||
/// Simply speaking structs implementing this trait represent arguments of
|
||||
/// a telegram bot API method.
|
||||
///
|
||||
/// This trait provides some additional information needed for sending request
|
||||
/// to the telegram.
|
||||
#[cfg_attr(all(docsrs, feature = "nightly"), doc(spotlight))]
|
||||
pub trait Payload {
|
||||
/// Return type of the telegram method.
|
||||
///
|
||||
/// Note: that should not include result wrappers (e.g. it should be simply
|
||||
/// `Message`, `True` or something else)
|
||||
type Output;
|
||||
|
||||
/// Name of the telegram method. Case insensitive, though must not include
|
||||
/// underscores. (e.g.: `GetMe`, `GETME`, `getme`, `getMe` are ok, but
|
||||
/// `get_me` is not ok)
|
||||
const NAME: &'static str;
|
||||
}
|
69
src/requests/request.rs
Normal file
69
src/requests/request.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use std::future::Future;
|
||||
|
||||
use crate::requests::{HasPayload, Output};
|
||||
|
||||
/// A ready-to-send telegram request.
|
||||
// FIXME(waffle): Write better doc for the trait
|
||||
#[cfg_attr(all(docsrs, feature = "nightly"), doc(spotlight))]
|
||||
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
|
||||
*/
|
||||
|
||||
/// Type of error that may happen during sending the request to telegram.
|
||||
type Err;
|
||||
|
||||
/// Type of future returned by [`send`](Request::send) method.
|
||||
type Send: Future<Output = Result<Output<Self>, Self::Err>>;
|
||||
|
||||
/// Type of future returned by [`send_ref`](Request::send_ref) method.
|
||||
///
|
||||
/// NOTE: it intentionally forbids borrowing from self
|
||||
// though anyway we couldn't allow borrowing without GATs :sob:
|
||||
type SendRef: Future<Output = Result<Output<Self>, Self::Err>>;
|
||||
|
||||
/// Send the request.
|
||||
///
|
||||
/// ## Examples
|
||||
// FIXME(waffle): ignored until full request redesign lands
|
||||
/// ```ignore
|
||||
/// # async {
|
||||
/// use teloxide_core::{methods::GetMe, requests::{Request, RequestJson}, types::User, bot::Bot};
|
||||
///
|
||||
/// let bot = Bot::new("TOKEN");
|
||||
/// let method = GetMe::new();
|
||||
/// let request = JsonRequest::new(bot, method);
|
||||
/// let _: User = request.send().await.unwrap();
|
||||
/// # }
|
||||
/// ```
|
||||
fn send(self) -> Self::Send;
|
||||
|
||||
/// Send the request.
|
||||
///
|
||||
/// 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
|
||||
/// `clone`ing the requests. (because instead of copying all the data
|
||||
/// and then serializing it, this method should just serialize the data)
|
||||
///
|
||||
/// ## Examples
|
||||
// FIXME(waffle): ignored until full request redisign lands
|
||||
/// ```ignore
|
||||
/// # async {
|
||||
/// use teloxide_core::prelude::*;
|
||||
///
|
||||
/// let bot = Bot::new("TOKEN");
|
||||
/// # let chat_ids = vec![1, 2, 3, 4].into_iter().map(Into::into);
|
||||
///
|
||||
/// let mut req = bot.send_message(0, "Hi there!");
|
||||
/// for chat_id in chat_ids {
|
||||
/// req.chat_id = chat_id;
|
||||
/// req.send_ref().await.unwrap();
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
fn send_ref(&self) -> Self::SendRef;
|
||||
}
|
Loading…
Add table
Reference in a new issue