channels_packet/
payload.rs

1//! [`Payload`] and helper types.
2
3use core::fmt;
4
5use crate::util::Error;
6
7/// Error returned when creating a payload.
8#[derive(Clone, Copy, PartialEq, Eq, Hash)]
9pub struct PayloadError<T> {
10	payload: T,
11}
12
13impl<T> PayloadError<T> {
14	/// Get back the payload that caused the error.
15	#[inline]
16	pub fn into_payload(self) -> T {
17		self.payload
18	}
19}
20
21impl<T> fmt::Debug for PayloadError<T> {
22	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23		f.debug_tuple("PayloadError").finish()
24	}
25}
26
27impl<T> fmt::Display for PayloadError<T> {
28	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29		f.write_str("payload too large")
30	}
31}
32
33impl<T> Error for PayloadError<T> {}
34
35/// A payload for a frame.
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
37pub struct Payload<T>(T);
38
39impl<T> Payload<T> {
40	/// The maximum length, in bytes, of any payload.
41	pub const MAX_LENGTH: usize = max_payload_length();
42
43	/// Create a new [`Payload`] without checking its length.
44	///
45	/// # Safety
46	///
47	/// The caller must ensure that the length of payload is not greater than
48	/// [`Payload::MAX_LENGTH`].
49	#[inline]
50	pub const unsafe fn new_unchecked(payload: T) -> Self {
51		Self(payload)
52	}
53
54	/// Get a reference to the payload.
55	#[inline]
56	pub fn get(&self) -> &T {
57		&self.0
58	}
59
60	/// Get a mutable reference to the payload.
61	#[inline]
62	pub fn get_mut(&mut self) -> &mut T {
63		&mut self.0
64	}
65
66	/// Destruct this [`Payload`].
67	#[inline]
68	pub fn into_inner(self) -> T {
69		self.0
70	}
71
72	/// Convert a [`&Payload<T>`] to a [`Payload<&T>`].
73	///
74	/// [`&Payload<T>`]: Payload
75	/// [`Payload<&T>`]: Payload
76	#[inline]
77	pub fn as_ref(&self) -> Payload<&T> {
78		Payload(&self.0)
79	}
80
81	/// Convert a [`&mut Payload<T>`] to a [`Payload<&mut T>`].
82	///
83	/// [`&mut Payload<T>`]: Payload
84	/// [`Payload<&mut T>`]: Payload
85	#[inline]
86	pub fn as_mut(&mut self) -> Payload<&mut T> {
87		Payload(&mut self.0)
88	}
89}
90
91impl<T: AsRef<[u8]>> Payload<T> {
92	/// Create a new [`Payload`].
93	///
94	/// Returns [`Err`] if the length of `payload` exceeds [`Payload::MAX_LENGTH`]. Otherwise,
95	/// returns [`Some`]. It is possible to take back ownership of `payload` from [`PayloadError`]
96	/// with [`PayloadError::into_payload`].
97	#[inline]
98	pub fn new(payload: T) -> Result<Self, PayloadError<T>> {
99		if payload.as_ref().len() > Self::MAX_LENGTH {
100			Err(PayloadError { payload })
101		} else {
102			Ok(Self(payload))
103		}
104	}
105
106	/// Get the payload.
107	#[inline]
108	pub fn as_slice(&self) -> &[u8] {
109		self.0.as_ref()
110	}
111
112	/// Get the length of the payload.
113	#[inline]
114	#[allow(clippy::cast_possible_truncation)]
115	pub fn length(&self) -> u32 {
116		self.as_slice().len() as u32
117	}
118}
119
120impl<T: AsRef<[u8]>> AsRef<[u8]> for Payload<T> {
121	fn as_ref(&self) -> &[u8] {
122		self.as_slice()
123	}
124}
125
126const fn max_payload_length() -> usize {
127	let a = u32::MAX as u64;
128	let b = usize::MAX as u64;
129
130	#[allow(clippy::cast_possible_truncation)]
131	if a <= b {
132		a as usize
133	} else {
134		b as usize
135	}
136}