Skip to main content

binius_utils/
serialization.rs

1// Copyright 2024-2025 Irreducible Inc.
2
3use bytes::{Buf, BufMut};
4use hybrid_array::{Array, ArraySize};
5use thiserror::Error;
6
7/// Serialize data to a byte buffer.
8pub trait SerializeBytes {
9	fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError>;
10
11	/// Serializes every element of `slice` back-to-back, with no length prefix.
12	///
13	/// The default loops, calling [`serialize`](Self::serialize) once per element.
14	/// That default is always correct.
15	/// Overriding this method is an optimization, never a correctness requirement.
16	/// Override it only when `slice`'s byte layout already matches its serialized form.
17	/// Then the whole call collapses to one bulk copy instead of N small writes.
18	fn serialize_slice(slice: &[Self], write_buf: impl BufMut) -> Result<(), SerializationError>
19	where
20		Self: Sized,
21	{
22		let mut write_buf = write_buf;
23		slice
24			.iter()
25			.try_for_each(|item| item.serialize(&mut write_buf))
26	}
27}
28
29/// Deserialize data from a byte buffer.
30pub trait DeserializeBytes: Sized {
31	fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError>;
32}
33
34/// A type whose byte-serialized form has a fixed, compile-time-known size.
35///
36/// Implementors must guarantee that [`SerializeBytes::serialize`] writes exactly
37/// [`BYTE_SIZE`](Self::BYTE_SIZE) bytes and that [`DeserializeBytes::deserialize`] reads exactly
38/// [`BYTE_SIZE`](Self::BYTE_SIZE) bytes.
39pub trait FixedSizeSerializeBytes: SerializeBytes + DeserializeBytes {
40	/// The exact number of bytes written by `serialize` and read by `deserialize`.
41	const BYTE_SIZE: usize;
42}
43
44macro_rules! impl_fixed_size_serialize_bytes {
45	($ty:ty, $size:expr) => {
46		impl FixedSizeSerializeBytes for $ty {
47			const BYTE_SIZE: usize = $size;
48		}
49	};
50}
51
52impl_fixed_size_serialize_bytes!(u8, 1);
53impl_fixed_size_serialize_bytes!(u16, 2);
54impl_fixed_size_serialize_bytes!(u32, 4);
55impl_fixed_size_serialize_bytes!(u64, 8);
56impl_fixed_size_serialize_bytes!(u128, 16);
57// `usize` is serialized as a `u32`.
58impl_fixed_size_serialize_bytes!(usize, 4);
59impl_fixed_size_serialize_bytes!(bool, 1);
60
61#[derive(Error, Debug, Clone)]
62pub enum SerializationError {
63	#[error("Write buffer is full")]
64	WriteBufferFull,
65	#[error("Not enough data in read buffer to deserialize")]
66	NotEnoughBytes,
67	#[error("Unknown enum variant index {name}::{index}")]
68	UnknownEnumVariant { name: &'static str, index: u8 },
69	#[error("FromUtf8Error: {0}")]
70	FromUtf8Error(#[from] std::string::FromUtf8Error),
71	#[error("Invalid construction of {name}")]
72	InvalidConstruction { name: &'static str },
73	#[error("usize {size} is too large to serialize (max is {max})", max = u32::MAX)]
74	UsizeTooLarge { size: usize },
75}
76
77impl<T: SerializeBytes + ?Sized> SerializeBytes for &T {
78	fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
79		(**self).serialize(write_buf)
80	}
81}
82
83impl SerializeBytes for usize {
84	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
85		let value: u32 = (*self)
86			.try_into()
87			.map_err(|_| SerializationError::UsizeTooLarge { size: *self })?;
88		SerializeBytes::serialize(&value, &mut write_buf)
89	}
90}
91
92impl DeserializeBytes for usize {
93	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
94	where
95		Self: Sized,
96	{
97		let value: u32 = DeserializeBytes::deserialize(&mut read_buf)?;
98		Ok(value as Self)
99	}
100}
101
102impl SerializeBytes for u128 {
103	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
104		assert_enough_space_for(&write_buf, std::mem::size_of::<Self>())?;
105		write_buf.put_u128_le(*self);
106		Ok(())
107	}
108}
109
110impl DeserializeBytes for u128 {
111	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
112	where
113		Self: Sized,
114	{
115		assert_enough_data_for(&read_buf, std::mem::size_of::<Self>())?;
116		Ok(read_buf.get_u128_le())
117	}
118}
119
120impl SerializeBytes for u64 {
121	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
122		assert_enough_space_for(&write_buf, std::mem::size_of::<Self>())?;
123		write_buf.put_u64_le(*self);
124		Ok(())
125	}
126}
127
128impl DeserializeBytes for u64 {
129	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
130	where
131		Self: Sized,
132	{
133		assert_enough_data_for(&read_buf, std::mem::size_of::<Self>())?;
134		Ok(read_buf.get_u64_le())
135	}
136}
137
138impl SerializeBytes for u32 {
139	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
140		assert_enough_space_for(&write_buf, std::mem::size_of::<Self>())?;
141		write_buf.put_u32_le(*self);
142		Ok(())
143	}
144}
145
146impl DeserializeBytes for u32 {
147	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
148	where
149		Self: Sized,
150	{
151		assert_enough_data_for(&read_buf, std::mem::size_of::<Self>())?;
152		Ok(read_buf.get_u32_le())
153	}
154}
155
156impl SerializeBytes for u16 {
157	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
158		assert_enough_space_for(&write_buf, std::mem::size_of::<Self>())?;
159		write_buf.put_u16_le(*self);
160		Ok(())
161	}
162}
163
164impl DeserializeBytes for u16 {
165	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
166	where
167		Self: Sized,
168	{
169		assert_enough_data_for(&read_buf, std::mem::size_of::<Self>())?;
170		Ok(read_buf.get_u16_le())
171	}
172}
173
174impl SerializeBytes for u8 {
175	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
176		assert_enough_space_for(&write_buf, std::mem::size_of::<Self>())?;
177		write_buf.put_u8(*self);
178		Ok(())
179	}
180}
181
182impl DeserializeBytes for u8 {
183	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
184	where
185		Self: Sized,
186	{
187		assert_enough_data_for(&read_buf, std::mem::size_of::<Self>())?;
188		Ok(read_buf.get_u8())
189	}
190}
191
192impl SerializeBytes for bool {
193	fn serialize(&self, write_buf: impl BufMut) -> Result<(), SerializationError> {
194		u8::serialize(&(*self as u8), write_buf)
195	}
196}
197
198impl DeserializeBytes for bool {
199	fn deserialize(read_buf: impl Buf) -> Result<Self, SerializationError>
200	where
201		Self: Sized,
202	{
203		Ok(u8::deserialize(read_buf)? != 0)
204	}
205}
206
207impl<T> SerializeBytes for std::marker::PhantomData<T> {
208	fn serialize(&self, _write_buf: impl BufMut) -> Result<(), SerializationError> {
209		Ok(())
210	}
211}
212
213impl<T> DeserializeBytes for std::marker::PhantomData<T> {
214	fn deserialize(_read_buf: impl Buf) -> Result<Self, SerializationError>
215	where
216		Self: Sized,
217	{
218		Ok(Self)
219	}
220}
221
222impl SerializeBytes for &str {
223	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
224		let bytes = self.as_bytes();
225		SerializeBytes::serialize(&bytes.len(), &mut write_buf)?;
226		assert_enough_space_for(&write_buf, bytes.len())?;
227		write_buf.put_slice(bytes);
228		Ok(())
229	}
230}
231
232impl SerializeBytes for String {
233	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
234		SerializeBytes::serialize(&self.as_str(), &mut write_buf)
235	}
236}
237
238impl DeserializeBytes for String {
239	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
240	where
241		Self: Sized,
242	{
243		let len = DeserializeBytes::deserialize(&mut read_buf)?;
244		assert_enough_data_for(&read_buf, len)?;
245		Ok(Self::from_utf8(read_buf.copy_to_bytes(len).to_vec())?)
246	}
247}
248
249impl<T: SerializeBytes> SerializeBytes for [T] {
250	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
251		SerializeBytes::serialize(&self.len(), &mut write_buf)?;
252		T::serialize_slice(self, write_buf)
253	}
254}
255
256impl<T: SerializeBytes> SerializeBytes for Vec<T> {
257	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
258		SerializeBytes::serialize(self.as_slice(), &mut write_buf)
259	}
260}
261
262impl<T: DeserializeBytes> DeserializeBytes for Vec<T> {
263	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
264	where
265		Self: Sized,
266	{
267		let len: usize = DeserializeBytes::deserialize(&mut read_buf)?;
268		(0..len)
269			.map(|_| DeserializeBytes::deserialize(&mut read_buf))
270			.collect()
271	}
272}
273
274impl<T: SerializeBytes> SerializeBytes for Option<T> {
275	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
276		match self {
277			Some(value) => {
278				SerializeBytes::serialize(&true, &mut write_buf)?;
279				SerializeBytes::serialize(value, &mut write_buf)?;
280			}
281			None => {
282				SerializeBytes::serialize(&false, write_buf)?;
283			}
284		}
285		Ok(())
286	}
287}
288
289impl<T: DeserializeBytes> DeserializeBytes for Option<T> {
290	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
291	where
292		Self: Sized,
293	{
294		Ok(match bool::deserialize(&mut read_buf)? {
295			true => Some(T::deserialize(&mut read_buf)?),
296			false => None,
297		})
298	}
299}
300
301impl<U: SerializeBytes, V: SerializeBytes> SerializeBytes for (U, V) {
302	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
303		U::serialize(&self.0, &mut write_buf)?;
304		V::serialize(&self.1, write_buf)
305	}
306}
307
308impl<U: DeserializeBytes, V: DeserializeBytes> DeserializeBytes for (U, V) {
309	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
310	where
311		Self: Sized,
312	{
313		Ok((U::deserialize(&mut read_buf)?, V::deserialize(read_buf)?))
314	}
315}
316
317impl<T: SerializeBytes, const N: usize> SerializeBytes for [T; N] {
318	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
319		for val in self {
320			val.serialize(&mut write_buf)?;
321		}
322		Ok(())
323	}
324}
325
326impl<T: DeserializeBytes, const N: usize> DeserializeBytes for [T; N] {
327	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError>
328	where
329		Self: Sized,
330	{
331		array_util::try_from_fn(|_| T::deserialize(&mut read_buf))
332	}
333}
334
335impl<U: ArraySize> SerializeBytes for Array<u8, U> {
336	fn serialize(&self, mut write_buf: impl BufMut) -> Result<(), SerializationError> {
337		assert_enough_space_for(&write_buf, U::USIZE)?;
338		write_buf.put_slice(self);
339		Ok(())
340	}
341}
342
343impl<U: ArraySize> DeserializeBytes for Array<u8, U> {
344	fn deserialize(mut read_buf: impl Buf) -> Result<Self, SerializationError> {
345		assert_enough_data_for(&read_buf, U::USIZE)?;
346		let mut ret = Self::default();
347		read_buf.copy_to_slice(&mut ret);
348		Ok(ret)
349	}
350}
351
352#[inline]
353pub fn assert_enough_space_for(
354	write_buf: &impl BufMut,
355	size: usize,
356) -> Result<(), SerializationError> {
357	if write_buf.remaining_mut() < size {
358		return Err(SerializationError::WriteBufferFull);
359	}
360	Ok(())
361}
362
363#[inline]
364pub fn assert_enough_data_for(read_buf: &impl Buf, size: usize) -> Result<(), SerializationError> {
365	if read_buf.remaining() < size {
366		return Err(SerializationError::NotEnoughBytes);
367	}
368	Ok(())
369}
370
371#[cfg(test)]
372mod tests {
373	use hybrid_array::sizes::U32;
374	use rand::prelude::*;
375
376	use super::*;
377
378	#[test]
379	fn test_generic_array_serialize_deserialize() {
380		let mut rng = StdRng::seed_from_u64(0);
381
382		let mut data = Array::<u8, U32>::default();
383		rng.fill_bytes(&mut data);
384
385		let mut buf = Vec::new();
386		data.serialize(&mut buf).unwrap();
387
388		let data_deserialized = Array::<u8, U32>::deserialize(&mut buf.as_slice()).unwrap();
389		assert_eq!(data_deserialized, data);
390	}
391}