lightyear_serde/
lib.rs

1//! # Lightyear Serde
2//!
3//! This crate provides serialization and deserialization utilities for Lightyear.
4//! It defines the [`ToBytes`] trait for converting types to and from byte representations,
5//! along with [`Reader`] and [`Writer`](writer::Writer) utilities for handling byte streams.
6//!
7//! It includes implementations for common types and collections, and utilities for
8//! efficient serialization, such as varint encoding.
9//!
10//! This crate is fundamental for preparing data to be sent over the network and for
11//! reconstructing data received from remote peers.
12#![no_std]
13
14extern crate alloc;
15#[cfg(feature = "std")]
16extern crate std;
17
18use crate::reader::{ReadInteger, ReadVarInt, Reader};
19use crate::varint::varint_len;
20use alloc::vec::Vec;
21use bevy_platform::collections::HashMap;
22use bytes::Bytes;
23use core::hash::{BuildHasher, Hash};
24use no_std_io2::io;
25
26/// Utilities for mapping entities during serialization and deserialization.
27pub mod entity_map;
28/// Provides the [`Reader`] struct and traits for deserializing data from a byte stream.
29pub mod reader;
30/// Defines traits and structures for registering serializable types.
31pub mod registry;
32/// Utilities for variable-length integer encoding and decoding.
33pub mod varint;
34/// Provides the [`Writer`](writer::Writer) struct and traits for serializing data into a byte stream.
35pub mod writer;
36
37/// Commonly used items from the `lightyear_serde` crate.
38pub mod prelude {
39    pub use crate::SerializationError;
40}
41
42use crate::writer::WriteInteger;
43
44pub type RawData = Vec<u8>;
45
46/// Errors that can occur during serialization or deserialization.
47#[non_exhaustive]
48#[derive(thiserror::Error, Debug)]
49pub enum SerializationError {
50    #[error(transparent)]
51    Io(#[from] io::Error),
52    #[error("Invalid packet type")]
53    InvalidPacketType,
54    #[error("Invalid value")]
55    InvalidValue,
56    #[error("Subtraction overflow")]
57    SubtractionOverflow,
58    #[error(transparent)]
59    BincodeEncode(#[from] bincode::error::EncodeError),
60    #[error(transparent)]
61    BincodeDecode(#[from] bincode::error::DecodeError),
62}
63
64/// Trait for types that can be serialized to and deserialized from a byte stream.
65///
66/// This trait provides methods to:
67/// - Calculate the number of bytes required for serialization (`bytes_len`).
68/// - Serialize the type into a buffer (`to_bytes`).
69/// - Deserialize the type from a buffer (`from_bytes`).
70///
71/// It is implemented for various primitive types, collections, and [`Bytes`].
72#[allow(clippy::len_without_is_empty)]
73pub trait ToBytes {
74    fn bytes_len(&self) -> usize;
75    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError>;
76
77    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
78    where
79        Self: Sized;
80}
81
82impl<M: ToBytes> ToBytes for Option<M> {
83    fn bytes_len(&self) -> usize {
84        match self {
85            Some(value) => 1 + value.bytes_len(),
86            None => 1,
87        }
88    }
89
90    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
91        match self {
92            Some(value) => {
93                buffer.write_u8(1)?;
94                value.to_bytes(buffer)?;
95            }
96            None => {
97                buffer.write_u8(0)?;
98            }
99        }
100        Ok(())
101    }
102
103    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
104    where
105        Self: Sized,
106    {
107        let has_value = buffer.read_u8()? != 0;
108        if has_value {
109            Ok(Some(M::from_bytes(buffer)?))
110        } else {
111            Ok(None)
112        }
113    }
114}
115
116/// When we read, instead of allocating we just create a new Bytes by slicing the buffer
117impl ToBytes for Bytes {
118    fn bytes_len(&self) -> usize {
119        varint_len(self.len() as u64) + self.len()
120    }
121
122    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
123        buffer.write_varint(self.len() as u64)?;
124        buffer.write_all(self.as_ref())?;
125        Ok(())
126    }
127
128    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
129    where
130        Self: Sized,
131    {
132        let len = buffer.read_varint()? as usize;
133        let bytes = buffer.split_len(len);
134        Ok(bytes)
135    }
136}
137
138impl ToBytes for u8 {
139    fn bytes_len(&self) -> usize {
140        1
141    }
142
143    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
144        buffer.write_u8(*self)?;
145        Ok(())
146    }
147
148    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
149    where
150        Self: Sized,
151    {
152        Ok(buffer.read_u8()?)
153    }
154}
155
156impl ToBytes for u16 {
157    fn bytes_len(&self) -> usize {
158        varint_len(*self as u64)
159    }
160
161    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
162        buffer.write_varint(*self as u64)?;
163        Ok(())
164    }
165
166    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
167    where
168        Self: Sized,
169    {
170        Ok(buffer.read_varint()? as u16)
171    }
172}
173
174macro_rules! impl_tuple_query_data {
175    ($($name: ident),*) => {
176
177        #[allow(non_snake_case)]
178        #[allow(clippy::unused_unit)]
179        // SAFETY: defers to soundness `$name: WorldQuery` impl
180        impl<$($name: ToBytes),*> ToBytes for ($($name,)*) {
181            fn bytes_len(&self) -> usize {
182                let ($($name,)*) = self;
183                let mut len = 0;
184                $(len += $name.bytes_len();)*
185                len
186            }
187
188            fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
189                let ($($name,)*) = self;
190                $($name.to_bytes(buffer)?;)*
191                Ok(())
192            }
193
194            fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError> {
195                Ok(($($name::from_bytes(buffer)?,)*))
196            }
197        }
198    };
199}
200
201variadics_please::all_tuples!(impl_tuple_query_data, 1, 8, P);
202
203impl<M: ToBytes> ToBytes for Vec<M> {
204    fn bytes_len(&self) -> usize {
205        varint_len(self.len() as u64) + self.iter().map(ToBytes::bytes_len).sum::<usize>()
206    }
207
208    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
209        buffer.write_varint(self.len() as u64)?;
210        self.iter().try_for_each(|item| item.to_bytes(buffer))?;
211        Ok(())
212    }
213
214    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
215    where
216        Self: Sized,
217    {
218        let len = buffer.read_varint()? as usize;
219        // TODO: if we know the MIN_LEN we can preallocate
220        let mut vec = Vec::with_capacity(len);
221        for _ in 0..len {
222            vec.push(M::from_bytes(buffer)?);
223        }
224        Ok(vec)
225    }
226}
227
228impl<K: ToBytes + Eq + Hash, V: ToBytes, S: Default + BuildHasher> ToBytes for HashMap<K, V, S> {
229    fn bytes_len(&self) -> usize {
230        varint_len(self.len() as u64)
231            + self
232                .iter()
233                .map(|(k, v)| k.bytes_len() + v.bytes_len())
234                .sum::<usize>()
235    }
236
237    fn to_bytes(&self, buffer: &mut impl WriteInteger) -> Result<(), SerializationError> {
238        buffer.write_varint(self.len() as u64)?;
239        self.iter().try_for_each(|(k, v)| {
240            k.to_bytes(buffer)?;
241            v.to_bytes(buffer)?;
242            Ok::<(), SerializationError>(())
243        })?;
244        Ok(())
245    }
246
247    fn from_bytes(buffer: &mut Reader) -> Result<Self, SerializationError>
248    where
249        Self: Sized,
250    {
251        let len = buffer.read_varint()? as usize;
252        // TODO: if we know the MIN_LEN we can preallocate
253        let mut res = HashMap::with_capacity_and_hasher(len, S::default());
254        for _ in 0..len {
255            let key = K::from_bytes(buffer)?;
256            let value = V::from_bytes(buffer)?;
257            res.insert(key, value);
258        }
259        Ok(res)
260    }
261}
262
263#[cfg(test)]
264mod tests {
265    use super::*;
266    use crate::writer::Writer;
267    use alloc::vec;
268    use bevy_ecs::entity::Entity;
269
270    #[test]
271    fn test_serialize_bytes() {
272        let a: Bytes = vec![7; 100].into();
273        let mut writer = Writer::with_capacity(5);
274        a.to_bytes(&mut writer).unwrap();
275
276        let mut reader = Reader::from(writer.to_bytes());
277        let read = Bytes::from_bytes(&mut reader).unwrap();
278        assert_eq!(a, read);
279    }
280
281    #[test]
282    fn test_serialize_vec() {
283        let a = [5; 10].to_vec();
284        let mut writer = Writer::with_capacity(5);
285        a.to_bytes(&mut writer).unwrap();
286        let b: Vec<u8> = vec![];
287        b.to_bytes(&mut writer).unwrap();
288
289        let mut reader = Reader::from(writer.to_bytes());
290        let a_read = Vec::<u8>::from_bytes(&mut reader).unwrap();
291        let b_read = Vec::<u8>::from_bytes(&mut reader).unwrap();
292        assert_eq!(a, a_read);
293        assert_eq!(b, b_read);
294    }
295
296    #[test]
297    fn test_serialize_map() {
298        let mut a = HashMap::default();
299        a.insert(1, 2);
300        a.insert(3, 4);
301        let mut writer = Writer::with_capacity(5);
302        a.to_bytes(&mut writer).unwrap();
303
304        let mut reader = Reader::from(writer.to_bytes());
305        let read = HashMap::<u8, u8>::from_bytes(&mut reader).unwrap();
306        assert_eq!(a, read);
307    }
308
309    #[test]
310    fn test_serialize_entity() {
311        let a = Entity::from_raw(0);
312        let b = Entity::from_raw(23);
313        let c = Entity::from_raw(u32::MAX);
314        let mut writer = Writer::with_capacity(5);
315        a.to_bytes(&mut writer).unwrap();
316        b.to_bytes(&mut writer).unwrap();
317        c.to_bytes(&mut writer).unwrap();
318
319        let mut reader = Reader::from(writer.to_bytes());
320        let read_a = Entity::from_bytes(&mut reader).unwrap();
321        let read_b = Entity::from_bytes(&mut reader).unwrap();
322        let read_c = Entity::from_bytes(&mut reader).unwrap();
323        assert_eq!(a, read_a);
324        assert_eq!(b, read_b);
325        assert_eq!(c, read_c);
326    }
327}