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
use either::Either;
use crate::requests::Payload;
/// Represents types having payload inside.
///
/// This trait is something between [`DerefMut`] and [`BorrowMut`] — it allows
/// only one implementation per type (the [output type] is associated, not
/// generic), has implementations for all types `P` such `P: `[`Payload`], but
/// has no magic compiler support like [`DerefMut`] does nor does it require
/// any laws about `Eq`, `Ord` and `Hash` as [`BorrowMut`] does.
///
/// Also the [output type] is bounded by the [`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 type]: HasPayload::Payload
pub trait HasPayload {
/// The 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;
/// Update payload with a function
fn with_payload_mut<F>(mut self, f: F) -> Self
where
Self: Sized,
F: FnOnce(&mut Self::Payload),
{
f(self.payload_mut());
self
}
}
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
}
}
impl<L, R> HasPayload for Either<L, R>
where
L: HasPayload,
R: HasPayload<Payload = L::Payload>,
{
type Payload = L::Payload;
fn payload_mut(&mut self) -> &mut Self::Payload {
self.as_mut().either(<_>::payload_mut, <_>::payload_mut)
}
fn payload_ref(&self) -> &Self::Payload {
self.as_ref().either(<_>::payload_ref, <_>::payload_ref)
}
}