1use crate::{Buf, Bytes};
7use alloc::{borrow::Cow, boxed::Box, rc::Rc, sync::Arc};
8use core::array;
9
10pub trait Deserialize {
12 type Output: Sized;
14
15 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
41 where
42 Buffer: Buf + ?Sized;
43
44 #[must_use]
71 fn size_hint() -> Option<usize>;
72}
73
74#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
76#[non_exhaustive]
77pub enum DeserializeError {
78 #[error("insufficient data in buffer")]
80 InsufficientData,
81 #[error("invariant failed: {0}")]
83 InvariantFailed(Cow<'static, str>),
84 #[error("length exceeds usize::MAX")]
86 LengthOverflow,
87}
88
89impl DeserializeError {
90 #[inline]
106 #[must_use]
107 pub fn invariant(message: impl Into<Cow<'static, str>>) -> Self {
108 Self::InvariantFailed(message.into())
109 }
110}
111
112macro_rules! impl_deserialize_ptr {
114 ($name:ty) => {
115 impl<T> Deserialize for $name
116 where
117 T: Deserialize<Output = T>,
118 $name: From<T>,
119 {
120 type Output = $name;
121
122 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
123 where
124 Buffer: Buf + ?Sized,
125 {
126 T::deserialize(buffer).map(<$name>::from)
127 }
128
129 fn size_hint() -> Option<usize> {
130 T::size_hint()
131 }
132 }
133 };
134}
135
136impl_deserialize_ptr!(Box<T>);
137impl_deserialize_ptr!(Rc<T>);
138impl_deserialize_ptr!(Arc<T>);
139
140macro_rules! impl_deserialize_tuple {
145 ( $( $name:ident )+ ) => {
146 impl<$($name: Deserialize<Output=$name>),+> Deserialize for ($($name,)+) {
147 type Output = Self;
148 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
149 where Buffer: Buf + ?Sized
150 {
151 Ok((
152 $($name::deserialize(buffer)?,)+
153 ))
154 }
155
156 fn size_hint() -> Option<usize> {
157 Some(0_usize)
158 $(
159 .and_then(|total| {
160 <$name>::size_hint().and_then(|size| total.checked_add(size))
161 })
162 )+
163 }
164 }
165 };
166}
167
168impl_deserialize_tuple! { A }
169impl_deserialize_tuple! { A B }
170impl_deserialize_tuple! { A B C }
171impl_deserialize_tuple! { A B C D }
172impl_deserialize_tuple! { A B C D E }
173impl_deserialize_tuple! { A B C D E F }
174impl_deserialize_tuple! { A B C D E F G }
175impl_deserialize_tuple! { A B C D E F G H }
176impl_deserialize_tuple! { A B C D E F G H I }
177impl_deserialize_tuple! { A B C D E F G H I J }
178impl_deserialize_tuple! { A B C D E F G H I J K }
179impl_deserialize_tuple! { A B C D E F G H I J K L }
180
181macro_rules! impl_deserialize_basic_type {
183 ($name:ty, $try_get:ident) => {
184 impl Deserialize for $name {
185 type Output = Self;
186
187 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
188 where
189 Buffer: Buf + ?Sized,
190 {
191 buffer
192 .$try_get()
193 .map_err(|_err| DeserializeError::InsufficientData)
194 }
195
196 fn size_hint() -> Option<usize> {
200 Some(size_of::<$name>())
201 }
202 }
203 };
204}
205
206impl_deserialize_basic_type!(u8, try_get_u8);
207impl_deserialize_basic_type!(u16, try_get_u16);
208impl_deserialize_basic_type!(u32, try_get_u32);
209impl_deserialize_basic_type!(u64, try_get_u64);
210impl_deserialize_basic_type!(i8, try_get_i8);
211impl_deserialize_basic_type!(i16, try_get_i16);
212impl_deserialize_basic_type!(i32, try_get_i32);
213impl_deserialize_basic_type!(i64, try_get_i64);
214impl_deserialize_basic_type!(f32, try_get_f32);
215impl_deserialize_basic_type!(f64, try_get_f64);
216
217impl Deserialize for bool {
218 type Output = Self;
219
220 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
221 where
222 Buffer: Buf + ?Sized,
223 {
224 u8::deserialize(buffer).map(|value| (value & 0x01) == 0x01)
226 }
227
228 fn size_hint() -> Option<usize> {
229 Some(1)
230 }
231}
232
233impl<T, const N: usize> Deserialize for [T; N]
235where
236 T: Deserialize<Output = T> + Default,
237{
238 type Output = Self;
239
240 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
241 where
242 Buffer: Buf + ?Sized,
243 {
244 let mut error: Option<DeserializeError> = None;
246 let array = array::from_fn(|_| {
248 if error.is_none() {
249 T::deserialize(buffer)
250 .map_err(|err| {
251 error = Some(err);
252 })
253 .unwrap_or_default()
254 } else {
255 T::default()
256 }
257 });
258 error.map_or_else(|| Ok(array), Err)
260 }
261
262 fn size_hint() -> Option<usize> {
263 T::size_hint().and_then(|size| size.checked_mul(N))
264 }
265}
266
267impl Deserialize for Bytes {
268 type Output = Self;
269
270 fn deserialize<Buffer>(buffer: &mut Buffer) -> Result<Self::Output, DeserializeError>
271 where
272 Buffer: Buf + ?Sized,
273 {
274 Ok(buffer.copy_to_bytes(buffer.remaining()))
275 }
276
277 fn size_hint() -> Option<usize> {
278 Some(0)
279 }
280}
281
282#[cfg(test)]
283#[expect(clippy::inline_modules, reason = "rust-clippy#17342")]
284mod tests {
285 use super::*;
286 use bytes::Bytes;
287
288 macro_rules! test_deserialize_basic_type {
293 ($t:ty, $name:tt) => {
294 #[test]
295 fn $name() {
296 assert_eq!(<$t>::size_hint(), Some(size_of::<$t>()));
297 let value = <$t>::try_from(1_u8).expect("1_u8 fits in every other basic type");
298 let buffer = value.to_be_bytes();
299 let mut cursor = buffer.as_slice();
300 assert_eq!(<$t>::deserialize(&mut cursor), Ok(value));
301 assert_eq!(
302 <$t>::deserialize(&mut cursor),
303 Err(DeserializeError::InsufficientData)
304 );
305 }
306 };
307 }
308
309 test_deserialize_basic_type!(u8, deserialize_u8);
310 test_deserialize_basic_type!(u16, deserialize_u16);
311 test_deserialize_basic_type!(u32, deserialize_u32);
312 test_deserialize_basic_type!(u64, deserialize_u64);
313 test_deserialize_basic_type!(i8, deserialize_i8);
314 test_deserialize_basic_type!(i16, deserialize_i16);
315 test_deserialize_basic_type!(i32, deserialize_i32);
316 test_deserialize_basic_type!(i64, deserialize_i64);
317 test_deserialize_basic_type!(f32, deserialize_f32);
318 test_deserialize_basic_type!(f64, deserialize_f64);
319
320 #[test]
321 fn deserialize_bool() {
322 assert_eq!(bool::size_hint(), Some(size_of::<u8>()));
323 let mut buffer = Bytes::copy_from_slice(&[0_u8, 1_u8]);
324 assert_eq!(bool::deserialize(&mut buffer), Ok(false));
325 assert_eq!(bool::deserialize(&mut buffer), Ok(true));
326 assert_eq!(
327 bool::deserialize(&mut buffer),
328 Err(DeserializeError::InsufficientData)
329 );
330 }
331
332 #[test]
333 fn deserialize_array() {
334 assert_eq!(<[u8; 2]>::size_hint(), Some(size_of::<u16>()));
335 let mut buffer = Bytes::copy_from_slice(&[1_u8, 2_u8]);
336 assert_eq!(<[u8; 2]>::deserialize(&mut buffer), Ok([1_u8, 2_u8]));
337 assert_eq!(
338 <[u8; 2]>::deserialize(&mut buffer),
339 Err(DeserializeError::InsufficientData)
340 );
341 }
342
343 #[test]
344 fn deserialize_tuple() {
345 assert_eq!(<(u8, u8)>::size_hint(), Some(size_of::<u16>()));
346 let mut buffer = Bytes::copy_from_slice(&[1_u8, 2_u8]);
347 assert_eq!(<(u8, u8)>::deserialize(&mut buffer), Ok((1_u8, 2_u8)));
348 assert_eq!(
349 <(u8, u8)>::deserialize(&mut buffer),
350 Err(DeserializeError::InsufficientData)
351 );
352 }
353
354 #[test]
355 fn deserialize_bytes() {
356 assert_eq!(Bytes::size_hint(), Some(0));
357 let mut buffer = Bytes::copy_from_slice(&[1_u8, 2]);
358 let output = Bytes::deserialize(&mut buffer).expect("should deserialize the bytes");
359 assert_eq!(output, [1_u8, 2].as_slice());
360 }
361
362 #[test]
363 fn deserialize_box() {
364 assert_eq!(Box::<u16>::size_hint(), u16::size_hint());
365 let mut buffer = Bytes::copy_from_slice(&[1_u8, 2]);
366 let output = Box::<u16>::deserialize(&mut buffer).expect("should deserialize the Box");
367 assert_eq!(*output, 0x0102_u16);
368 }
369}