teloxide_core_ng/requests/has_payload.rs
1use either::Either;
2
3use crate::requests::Payload;
4
5/// Represents types having payload inside.
6///
7/// This trait is something between [`DerefMut`] and [`BorrowMut`] — it allows
8/// only one implementation per type (the [output type] is associated, not
9/// generic), has implementations for all types `P` such `P: `[`Payload`], but
10/// has no magic compiler support like [`DerefMut`] does nor does it require
11/// any laws about `Eq`, `Ord` and `Hash` as [`BorrowMut`] does.
12///
13/// Also the [output type] is bounded by the [`Payload`] trait.
14///
15/// This trait is mostly used to implement payload setters (on both payloads &
16/// requests), so you probably won't find yourself using it directly.
17///
18/// [`DerefMut`]: std::ops::DerefMut
19/// [`BorrowMut`]: std::borrow::BorrowMut
20/// [`Payload`]: crate::requests::Payload
21/// [output type]: HasPayload::Payload
22pub trait HasPayload {
23 /// The type of the payload contained.
24 type Payload: Payload;
25
26 /// Gain mutable access to the underlying payload.
27 fn payload_mut(&mut self) -> &mut Self::Payload;
28
29 /// Gain immutable access to the underlying payload.
30 fn payload_ref(&self) -> &Self::Payload;
31
32 /// Update payload with a function
33 fn with_payload_mut<F>(mut self, f: F) -> Self
34 where
35 Self: Sized,
36 F: FnOnce(&mut Self::Payload),
37 {
38 f(self.payload_mut());
39 self
40 }
41}
42
43impl<P> HasPayload for P
44where
45 P: Payload,
46{
47 type Payload = Self;
48
49 fn payload_mut(&mut self) -> &mut Self::Payload {
50 self
51 }
52
53 fn payload_ref(&self) -> &Self::Payload {
54 self
55 }
56}
57
58impl<L, R> HasPayload for Either<L, R>
59where
60 L: HasPayload,
61 R: HasPayload<Payload = L::Payload>,
62{
63 type Payload = L::Payload;
64
65 fn payload_mut(&mut self) -> &mut Self::Payload {
66 self.as_mut().either(<_>::payload_mut, <_>::payload_mut)
67 }
68
69 fn payload_ref(&self) -> &Self::Payload {
70 self.as_ref().either(<_>::payload_ref, <_>::payload_ref)
71 }
72}