Skip to main content

wincode/
serde.rs

1#[cfg(feature = "alloc")]
2use alloc::vec::Vec;
3use {
4    crate::{
5        SchemaReadContext, SchemaReadOwned,
6        config::{self, DefaultConfig},
7        error::{ReadResult, WriteResult},
8        io::{Reader, Writer},
9        schema::{SchemaRead, SchemaWrite},
10    },
11    core::mem::MaybeUninit,
12};
13
14/// Helper over [`SchemaRead`] that automatically constructs a reader
15/// and initializes a destination.
16///
17/// # Examples
18///
19/// Using containers (indirect deserialization):
20/// ```
21/// # #[cfg(feature = "alloc")] {
22/// # use wincode::{Deserialize, containers, len::BincodeLen};
23/// let vec: Vec<u8> = vec![1, 2, 3];
24/// let bytes = wincode::serialize(&vec).unwrap();
25/// type Dst = containers::Vec<u8, BincodeLen>;
26/// let deserialized = Dst::deserialize(&bytes).unwrap();
27/// assert_eq!(vec, deserialized);
28/// # }
29/// ```
30///
31/// Using direct deserialization (`T::Dst = T`):
32/// ```
33/// # #[cfg(feature = "alloc")] {
34/// let vec: Vec<u8> = vec![1, 2, 3];
35/// let bytes = wincode::serialize(&vec).unwrap();
36/// let deserialized: Vec<u8> = wincode::deserialize(&bytes).unwrap();
37/// assert_eq!(vec, deserialized);
38/// # }
39/// ```
40pub trait Deserialize<'de>: SchemaRead<'de, DefaultConfig> {
41    /// Deserialize the input `src` bytes into a new `Self::Dst`.
42    #[inline(always)]
43    fn deserialize(src: &'de [u8]) -> ReadResult<Self::Dst> {
44        Self::get(src)
45    }
46
47    /// Deserialize the input `src` bytes into `dst`.
48    #[inline]
49    fn deserialize_into(src: &'de [u8], dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
50        Self::read(src, dst)
51    }
52}
53
54impl<'de, T> Deserialize<'de> for T where T: SchemaRead<'de, DefaultConfig> {}
55
56/// A variant of [`Deserialize`] for types that can be deserialized without borrowing from the reader.
57pub trait DeserializeOwned: SchemaReadOwned<DefaultConfig> {
58    /// Deserialize from the given [`Reader`] into a new `Self::Dst`.
59    #[inline(always)]
60    fn deserialize_from<'de>(
61        src: impl Reader<'de>,
62    ) -> ReadResult<<Self as SchemaRead<'de, DefaultConfig>>::Dst> {
63        Self::get(src)
64    }
65
66    /// Deserialize from the given [`Reader`] into `dst`.
67    #[inline]
68    fn deserialize_from_into<'de>(
69        src: impl Reader<'de>,
70        dst: &mut MaybeUninit<<Self as SchemaRead<'de, DefaultConfig>>::Dst>,
71    ) -> ReadResult<()> {
72        Self::read(src, dst)
73    }
74}
75
76impl<T> DeserializeOwned for T where T: SchemaReadOwned<DefaultConfig> {}
77
78/// Helper over [`SchemaWrite`] that automatically constructs a writer
79/// and serializes a source.
80///
81/// # Examples
82///
83/// Using containers (indirect serialization):
84/// ```
85/// # #[cfg(feature = "alloc")] {
86/// # use wincode::{Serialize, containers, len::BincodeLen};
87/// let vec: Vec<u8> = vec![1, 2, 3];
88/// type Src = containers::Vec<u8, BincodeLen>;
89/// let bytes = Src::serialize(&vec).unwrap();
90/// let deserialized: Vec<u8> = wincode::deserialize(&bytes).unwrap();
91/// assert_eq!(vec, deserialized);
92/// # }
93/// ```
94///
95/// Using direct serialization (`T::Src = T`):
96/// ```
97/// # #[cfg(feature = "alloc")] {
98/// let vec: Vec<u8> = vec![1, 2, 3];
99/// let bytes = wincode::serialize(&vec).unwrap();
100/// let deserialized: Vec<u8> = wincode::deserialize(&bytes).unwrap();
101/// assert_eq!(vec, deserialized);
102/// # }
103/// ```
104pub trait Serialize: SchemaWrite<DefaultConfig> {
105    /// Serialize a serializable type into a `Vec` of bytes.
106    #[cfg(feature = "alloc")]
107    #[inline]
108    fn serialize(src: &Self::Src) -> WriteResult<Vec<u8>> {
109        <Self as config::Serialize<DefaultConfig>>::serialize(src, DefaultConfig::default())
110    }
111
112    /// Serialize a serializable type into the given byte buffer.
113    ///
114    /// # Partial writes
115    ///
116    /// This operation is not transactional. If it returns an error, the writer
117    /// may already contain a prefix of the serialized value. Dynamically sized
118    /// values in particular may discover insufficient capacity only after
119    /// preceding fields have been written.
120    ///
121    /// If the destination must remain unchanged on failure, serialize into a
122    /// temporary buffer and copy the result only after serialization succeeds.
123    /// For a fixed-size destination, callers can instead use
124    /// [`Self::serialized_size`] to check that enough space is available first.
125    #[inline]
126    fn serialize_into(dst: impl Writer, src: &Self::Src) -> WriteResult<()> {
127        <Self as config::Serialize<DefaultConfig>>::serialize_into(
128            dst,
129            src,
130            DefaultConfig::default(),
131        )
132    }
133
134    /// Get the size in bytes of the type when serialized.
135    #[inline]
136    fn serialized_size(src: &Self::Src) -> WriteResult<u64> {
137        <Self as config::Serialize<DefaultConfig>>::serialized_size(src, DefaultConfig::default())
138    }
139}
140
141impl<T> Serialize for T where T: SchemaWrite<DefaultConfig> + ?Sized {}
142
143/// Deserialize a type from the given bytes.
144///
145/// This is a "simplified" version of [`Deserialize::deserialize`] that
146/// requires the `T::Dst` to be `T`. In other words, a schema type
147/// that deserializes to itself.
148///
149/// This helper exists to match the expected signature of `serde`'s
150/// `Deserialize`, where types that implement `Deserialize` deserialize
151/// into themselves. This will be true of a large number of schema types,
152/// but wont, for example, for specialized container structures.
153///
154/// # Examples
155///
156/// ```
157/// # #[cfg(feature = "alloc")] {
158/// let vec: Vec<u8> = vec![1, 2, 3];
159/// let bytes = wincode::serialize(&vec).unwrap();
160/// let deserialized: Vec<u8> = wincode::deserialize(&bytes).unwrap();
161/// assert_eq!(vec, deserialized);
162/// # }
163/// ```
164#[inline(always)]
165pub fn deserialize<'de, T>(src: &'de [u8]) -> ReadResult<T>
166where
167    T: SchemaRead<'de, DefaultConfig, Dst = T>,
168{
169    T::deserialize(src)
170}
171
172/// Deserialize a type from the given bytes and reject trailing bytes.
173///
174/// # Examples
175///
176/// ```
177/// # #[cfg(feature = "alloc")] {
178/// let bytes = wincode::serialize(&123u64).unwrap();
179/// let value: u64 = wincode::deserialize_exact(&bytes).unwrap();
180/// assert_eq!(value, 123);
181///
182/// let mut extra = bytes.clone();
183/// extra.push(0xAA);
184/// assert!(wincode::deserialize_exact::<u64>(&extra).is_err());
185/// # }
186/// ```
187#[inline(always)]
188pub fn deserialize_exact<'de, T>(src: &'de [u8]) -> ReadResult<T>
189where
190    T: SchemaRead<'de, DefaultConfig, Dst = T>,
191{
192    config::deserialize_exact(src, DefaultConfig::default())
193}
194
195/// Deserialize a type from the given bytes using the provided context.
196///
197/// # Examples
198///
199/// ```
200/// # #[cfg(feature = "bumpalo")] {
201/// use bumpalo::{Bump, collections::String};
202///
203/// let serialized = wincode::serialize("w1nc0d3").unwrap();
204///
205/// let bump = Bump::new();
206/// let value: String = wincode::deserialize_with_context(&bump, &serialized).unwrap();
207/// assert_eq!(value, "w1nc0d3");
208/// # }
209/// ```
210#[inline(always)]
211pub fn deserialize_with_context<'de, Ctx, T>(ctx: Ctx, src: &'de [u8]) -> ReadResult<T>
212where
213    T: SchemaReadContext<'de, DefaultConfig, Ctx, Dst = T>,
214{
215    config::deserialize_with_context(ctx, src, DefaultConfig::default())
216}
217
218/// Deserialize a type from the given bytes, with the ability
219/// to form mutable references for types that are [`ZeroCopy`](crate::ZeroCopy).
220/// This can allow mutating the serialized data in place.
221///
222/// # Examples
223///
224/// ## Zero-copy types
225/// ```
226/// # #[cfg(all(feature = "alloc", feature = "derive"))] {
227/// # use wincode::{SchemaWrite, SchemaRead};
228/// # #[derive(Debug, PartialEq, Eq)]
229/// #[derive(SchemaWrite, SchemaRead)]
230/// #[repr(C)]
231/// struct Data {
232///     bytes: [u8; 7],
233///     the_answer: u8,
234/// }
235///
236/// let data = Data { bytes: [0; 7], the_answer: 0 };
237///
238/// let mut serialized = wincode::serialize(&data).unwrap();
239/// let data_mut: &mut Data = wincode::deserialize_mut(&mut serialized).unwrap();
240/// data_mut.bytes = *b"wincode";
241/// data_mut.the_answer = 42;
242///
243/// let deserialized: Data = wincode::deserialize(&serialized).unwrap();
244/// assert_eq!(deserialized, Data { bytes: *b"wincode", the_answer: 42 });
245/// # }
246/// ```
247///
248/// ## Mutable zero-copy members
249/// ```
250/// # #[cfg(all(feature = "alloc", feature = "derive"))] {
251/// # use wincode::{SchemaWrite, SchemaRead};
252/// # #[derive(Debug, PartialEq, Eq)]
253/// #[derive(SchemaWrite, SchemaRead)]
254/// struct Data {
255///     bytes: [u8; 7],
256///     the_answer: u8,
257/// }
258/// # #[derive(Debug, PartialEq, Eq)]
259/// #[derive(SchemaRead)]
260/// struct DataMut<'a> {
261///     bytes: &'a mut [u8; 7],
262///     the_answer: u8,
263/// }
264///
265/// let data = Data { bytes: [0; 7], the_answer: 42 };
266///
267/// let mut serialized = wincode::serialize(&data).unwrap();
268/// let data_mut: DataMut<'_> = wincode::deserialize_mut(&mut serialized).unwrap();
269/// *data_mut.bytes = *b"wincode";
270///
271/// let deserialized: Data = wincode::deserialize(&serialized).unwrap();
272/// assert_eq!(deserialized, Data { bytes: *b"wincode", the_answer: 42 });
273/// # }
274/// ```
275#[inline(always)]
276pub fn deserialize_mut<'de, T>(src: &'de mut [u8]) -> ReadResult<T>
277where
278    T: SchemaRead<'de, DefaultConfig, Dst = T>,
279{
280    <T as SchemaRead<'de, DefaultConfig>>::get(src)
281}
282
283/// Deserialize a type from the given bytes into the given target.
284///
285/// Like [`deserialize`], but allows the caller to provide their own reader.
286///
287/// Because not all readers will support zero-copy deserialization, this function
288/// requires [`SchemaReadOwned`] instead of [`SchemaRead`]. If you are deserializing
289/// from raw bytes, always prefer [`deserialize`] for maximum flexibility.
290#[inline(always)]
291pub fn deserialize_from<'de, T>(src: impl Reader<'de>) -> ReadResult<T>
292where
293    T: SchemaReadOwned<DefaultConfig, Dst = T>,
294{
295    T::deserialize_from(src)
296}
297
298/// Serialize a type into a `Vec` of bytes.
299///
300/// This is a "simplified" version of [`Serialize::serialize`] that
301/// requires the `T::Src` to be `T`. In other words, a schema type
302/// that serializes to itself.
303///
304/// This helper exists to match the expected signature of `serde`'s
305/// `Serialize`, where types that implement `Serialize` serialize
306/// themselves. This will be true of a large number of schema types,
307/// but wont, for example, for specialized container structures.
308///
309/// # Examples
310///
311/// ```
312/// let vec: Vec<u8> = vec![1, 2, 3];
313/// let bytes = wincode::serialize(&vec).unwrap();
314/// ```
315#[inline(always)]
316#[cfg(feature = "alloc")]
317pub fn serialize<T>(src: &T) -> WriteResult<Vec<u8>>
318where
319    T: SchemaWrite<DefaultConfig, Src = T> + ?Sized,
320{
321    T::serialize(src)
322}
323
324/// Serialize a type into the given writer.
325///
326/// Like [`serialize`], but allows the caller to provide their own writer.
327///
328/// # Partial writes
329///
330/// This operation is not transactional. If it returns an error, `dst` may
331/// already contain a prefix of the serialized value. Dynamically sized values
332/// in particular may discover insufficient capacity only after preceding
333/// fields have been written.
334///
335/// If the destination must remain unchanged on failure, serialize into a
336/// temporary buffer and copy the result only after serialization succeeds. For
337/// a fixed-size destination, callers can instead use [`serialized_size`] to
338/// check that enough space is available first.
339#[inline]
340pub fn serialize_into<T>(dst: impl Writer, src: &T) -> WriteResult<()>
341where
342    T: SchemaWrite<DefaultConfig, Src = T> + ?Sized,
343{
344    T::serialize_into(dst, src)
345}
346
347/// Get the size in bytes of the type when serialized.
348#[inline(always)]
349pub fn serialized_size<T>(src: &T) -> WriteResult<u64>
350where
351    T: SchemaWrite<DefaultConfig, Src = T> + ?Sized,
352{
353    T::serialized_size(src)
354}