1use crate::{BufMut, Bytes, BytesMut};
6use alloc::{borrow::Cow, boxed::Box, rc::Rc, sync::Arc};
7
8pub trait Serialize {
10 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
42 where
43 Buffer: BufMut + ?Sized;
44
45 fn size(&self) -> Option<usize>;
69
70 fn to_bytes(&self) -> Result<Bytes, SerializeError> {
87 let Some(size) = self.size() else {
88 return Err(SerializeError::SizeOverflow);
89 };
90 let mut buffer = BytesMut::with_capacity(size);
91 self.serialize(&mut buffer).map(|_total| buffer.freeze())
92 }
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
97#[non_exhaustive]
98pub enum SerializeError {
99 #[error("buffer would overflow")]
101 BufferOverflow,
102 #[error("invariant failed: {0}")]
104 InvariantFailed(Cow<'static, str>),
105 #[error("length exceeds capacity of length field")]
107 LengthOverflow,
108 #[error("size doesn't match expected value")]
110 SizeMismatch,
111 #[error("size exceeds capacity of `usize`")]
113 SizeOverflow,
114}
115
116impl SerializeError {
117 #[inline]
133 #[must_use]
134 pub fn invariant(message: impl Into<Cow<'static, str>>) -> Self {
135 Self::InvariantFailed(message.into())
136 }
137}
138
139macro_rules! impl_serialize_forward {
141 ($name:ty) => {
142 impl<T: Serialize + ?Sized> Serialize for $name {
143 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
144 where
145 Buffer: BufMut + ?Sized,
146 {
147 (**self).serialize(buffer)
148 }
149
150 fn size(&self) -> Option<usize> {
151 (**self).size()
152 }
153 }
154 };
155}
156
157impl_serialize_forward!(&T);
158impl_serialize_forward!(&mut T);
159impl_serialize_forward!(Box<T>);
160impl_serialize_forward!(Rc<T>);
161impl_serialize_forward!(Arc<T>);
162
163macro_rules! impl_serialize_tuple {
167 ($( $name:ident )+) => {
168 #[expect(non_snake_case, reason = "generic parameters")]
169 #[expect(clippy::min_ident_chars, reason = "generic parameters")]
170 impl<$($name: Serialize),+> Serialize for ($($name,)+) {
171 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
172 where
173 Buffer: BufMut + ?Sized
174 {
175 let &($(ref $name,)+) = self;
176 Ok(0_usize)
177 $(
178 .and_then(|total| {
179 $name.serialize(buffer).and_then(|size|
180 total.checked_add(size).ok_or(SerializeError::SizeOverflow)
181 )
182 })
183 )+
184 }
185
186 fn size(&self) -> Option<usize> {
187 let &($(ref $name,)+) = self;
188 Some(0_usize)
189 $(
190 .and_then(|total| {
191 $name.size().and_then(|size| total.checked_add(size))
192 })
193 )+
194 }
195 }
196 };
197}
198
199impl_serialize_tuple! { A }
200impl_serialize_tuple! { A B }
201impl_serialize_tuple! { A B C }
202impl_serialize_tuple! { A B C D }
203impl_serialize_tuple! { A B C D E }
204impl_serialize_tuple! { A B C D E F }
205impl_serialize_tuple! { A B C D E F G }
206impl_serialize_tuple! { A B C D E F G H }
207impl_serialize_tuple! { A B C D E F G H I }
208impl_serialize_tuple! { A B C D E F G H I J }
209impl_serialize_tuple! { A B C D E F G H I J K }
210impl_serialize_tuple! { A B C D E F G H I J K L }
211
212macro_rules! impl_serialize_basic_type {
220 ($name:ty, $method:ident) => {
221 impl Serialize for $name {
222 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
230 where
231 Buffer: BufMut + ?Sized,
232 {
233 buffer.$method(*self);
234 Ok(size_of::<$name>())
235 }
236
237 fn size(&self) -> Option<usize> {
241 Some(size_of::<$name>())
242 }
243 }
244 };
245}
246impl_serialize_basic_type!(u8, put_u8);
247impl_serialize_basic_type!(u16, put_u16);
248impl_serialize_basic_type!(u32, put_u32);
249impl_serialize_basic_type!(u64, put_u64);
250impl_serialize_basic_type!(i8, put_i8);
251impl_serialize_basic_type!(i16, put_i16);
252impl_serialize_basic_type!(i32, put_i32);
253impl_serialize_basic_type!(i64, put_i64);
254impl_serialize_basic_type!(f32, put_f32);
255impl_serialize_basic_type!(f64, put_f64);
256
257impl Serialize for bool {
258 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
259 where
260 Buffer: BufMut + ?Sized,
261 {
262 if *self {
263 buffer.put_u8(1);
264 } else {
265 buffer.put_u8(0);
266 }
267 Ok(size_of::<u8>())
268 }
269
270 fn size(&self) -> Option<usize> {
271 Some(1)
272 }
273}
274
275impl<T: Serialize, const N: usize> Serialize for [T; N] {
276 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
277 where
278 Buffer: BufMut + ?Sized,
279 {
280 let mut iterator = self.iter();
281 iterator.try_fold(0_usize, |acc, elem| {
282 elem.serialize(buffer)
283 .and_then(|elem| acc.checked_add(elem).ok_or(SerializeError::SizeOverflow))
284 })
285 }
286
287 fn size(&self) -> Option<usize> {
288 let mut iterator = self.iter();
289 iterator.try_fold(0_usize, |acc, elem| {
290 elem.size().and_then(|elem| acc.checked_add(elem))
291 })
292 }
293}
294
295impl Serialize for Bytes {
296 fn serialize<Buffer>(&self, buffer: &mut Buffer) -> Result<usize, SerializeError>
297 where
298 Buffer: BufMut + ?Sized,
299 {
300 buffer.put_slice(self);
301 Ok(self.len())
302 }
303
304 fn size(&self) -> Option<usize> {
305 Some(self.len())
306 }
307}
308
309pub struct SerializeWithFn<'value, Value, SerializeFn, SizeFn> {
334 value: &'value Value,
336 serialize: SerializeFn,
338 size: SizeFn,
340}
341
342impl<'value, Value, SerializeFn, SizeFn> SerializeWithFn<'value, Value, SerializeFn, SizeFn>
343where
344 for<'any> SerializeFn: Fn(&Value, &mut dyn BufMut) -> Result<usize, SerializeError>,
345 for<'any> SizeFn: Fn(&Value) -> Option<usize>,
346{
347 #[inline]
349 #[must_use]
350 pub const fn new(value: &'value Value, serialize: SerializeFn, size: SizeFn) -> Self {
351 Self {
352 value,
353 serialize,
354 size,
355 }
356 }
357}
358
359impl<Value, SerializeFn, SizeFn> Serialize for SerializeWithFn<'_, Value, SerializeFn, SizeFn>
360where
361 for<'any> SerializeFn: Fn(&Value, &mut dyn BufMut) -> Result<usize, SerializeError>,
362 for<'any> SizeFn: Fn(&Value) -> Option<usize>,
363{
364 fn serialize<Buffer>(&self, mut buffer: &mut Buffer) -> Result<usize, SerializeError>
365 where
366 Buffer: BufMut + ?Sized,
367 {
368 (self.serialize)(self.value, &mut buffer)
369 }
370
371 fn size(&self) -> Option<usize> {
372 (self.size)(self.value)
373 }
374}
375
376#[cfg(test)]
377#[expect(clippy::inline_modules, reason = "rust-clippy#17342")]
378mod tests {
379 use super::*;
380
381 macro_rules! test_serialize_basic_type {
382 ($t:ty, $name:ident) => {
383 #[test]
384 fn $name() {
385 let mut buffer = BytesMut::with_capacity(size_of::<$t>());
386 let result = <$t>::MAX.serialize(&mut buffer);
387 assert_eq!(result, Ok(size_of::<$t>()));
388 assert_eq!(result.ok(), <$t>::MAX.size());
389 assert_eq!(buffer.freeze(), <$t>::MAX.to_be_bytes().as_slice());
390 }
391 };
392 }
393
394 test_serialize_basic_type!(u8, serialize_u8);
395 test_serialize_basic_type!(u16, serialize_u16);
396 test_serialize_basic_type!(u32, serialize_u32);
397 test_serialize_basic_type!(u64, serialize_u64);
398 test_serialize_basic_type!(i8, serialize_i8);
399 test_serialize_basic_type!(i16, serialize_i16);
400 test_serialize_basic_type!(i32, serialize_i32);
401 test_serialize_basic_type!(i64, serialize_i64);
402 test_serialize_basic_type!(f32, serialize_f32);
403 test_serialize_basic_type!(f64, serialize_f64);
404
405 #[test]
406 fn serialize_bool() {
407 let mut buffer = BytesMut::with_capacity(2);
408 for value in [true, false] {
409 let size = value
410 .serialize(&mut buffer)
411 .expect("should serialize the bool");
412 assert_eq!(size, 1);
413 assert_eq!(value.size(), Some(1));
414 }
415 assert_eq!(buffer.freeze(), [1_u8, 0_u8].as_slice());
416 }
417
418 #[test]
419 fn serialize_array() {
420 let mut buffer = BytesMut::with_capacity(2);
421 let array = [1_u8, 2_u8];
422 let size = array
423 .serialize(&mut buffer)
424 .expect("should serialize the array");
425 assert_eq!(size, 2);
426 assert_eq!(Some(size), array.size());
427 assert_eq!(buffer.freeze(), [1_u8, 2_u8].as_slice());
428 }
429
430 #[test]
431 fn serialize_tuple() {
432 let mut buffer = BytesMut::with_capacity(2);
433 let tuple = (1_u8, 2_u8);
434 let size = tuple
435 .serialize(&mut buffer)
436 .expect("should serialize the tuple");
437 assert_eq!(size, 2);
438 assert_eq!(Some(size), tuple.size());
439 assert_eq!(buffer.freeze(), [1_u8, 2_u8].as_slice());
440 }
441
442 #[test]
443 fn serialize_bytes() {
444 let mut buffer = BytesMut::with_capacity(2);
445 let bytes = Bytes::copy_from_slice(&[1_u8, 2_u8]);
446 let size = bytes
447 .serialize(&mut buffer)
448 .expect("should serialize the buffer");
449 assert_eq!(size, 2);
450 assert_eq!(Some(size), bytes.size());
451 assert_eq!(buffer.freeze(), [1_u8, 2].as_slice());
452 }
453
454 #[test]
455 fn serialize_box() {
456 let mut buffer = BytesMut::with_capacity(2);
457 let value = Box::new(0x0102_u16);
458 let size = value
459 .serialize(&mut buffer)
460 .expect("should serialize the buffer");
461 assert_eq!(size, 2);
462 assert_eq!(Some(size), value.size());
463 assert_eq!(buffer.freeze(), [1_u8, 2].as_slice());
464 }
465}