Skip to main content

bincode_next/features/serde/
mod.rs

1//! Support for serde integration. Enable this with the `serde` feature.
2//!
3//! To encode/decode type that implement serde's trait, you can use:
4//! - [`borrow_decode_from_slice`\]
5//! - [`decode_from_slice`\]
6//! - [`encode_into_slice`\]
7//! - [`encode_to_vec`\]
8//!
9//! For interop with bincode's [Decode]/[Encode], you can use:
10//! - [`Compat`\]
11//! - [`BorrowCompat`\]
12//!
13//! For interop with bincode's `derive` feature, you can use the `#[bincode(with_serde)]` attribute on each field that implements serde's traits.
14//!
15//! ```
16//! # #[cfg(feature = "derive")]
17//! # mod foo {
18//! # use bincode_next::{Decode, Encode};
19//! # use serde_derive::{Deserialize, Serialize};
20//! #[derive(Serialize, Deserialize)]
21//! pub struct SerdeType {
22//!     // ...
23//! }
24//!
25//! #[derive(Decode, Encode)]
26//! pub struct StructWithSerde {
27//!     #[bincode(with_serde)]
28//!     pub serde: SerdeType,
29//! }
30//!
31//! #[derive(Decode, Encode)]
32//! pub enum EnumWithSerde {
33//!     Unit(#[bincode(with_serde)] SerdeType),
34//!     Struct {
35//!         #[bincode(with_serde)]
36//!         serde: SerdeType,
37//!     },
38//! }
39//! # }
40//! ```
41//!
42//! # Known issues
43//!
44//! Because bincode is a format without meta data, there are several known issues with serde's attributes. Please do not use any of the following attributes if you plan on using bincode, or use bincode's own `derive` macros.
45//! - `#[serde(flatten)]`
46//! - `#[serde(skip)]`
47//! - `#[serde(skip_deserializing)]`
48//! - `#[serde(skip_serializing)]`
49//! - `#[serde(skip_serializing_if = "path")]`
50//! - `#[serde(tag = "...")]`
51//! - `#[serde(untagged)]`
52//!
53//! **Using any of the above attributes can and will cause issues with bincode and will result in lost data**. Consider using bincode's own derive macro instead.
54//!
55//! ### `deserialize_any` and Self-Describing Formats
56//!
57//! Bincode is not a self-describing format (it does not store type metadata with the data map like JSON does). Because of this, it **does not support `deserialize_any`**.
58//!
59//! This means that types like `serde_json::Value` or `toml::Value` cannot be deserialized directly from a bincode stream. Attempting to do so will result in an `AnyNotSupported` error. To work around this, you must deserialize into strongly-typed data structures representing your schema, rather than dynamic or nested value enums.
60//!
61//! # Why move away from serde?
62//!
63//! Serde is a great library, but it has some issues that makes us want to be decoupled from serde:
64//! - The issues documented above with attributes.
65//! - Serde has chosen to not have a MSRV ([source](https://github.com/serde-rs/serde/pull/2257)). We think MSRV is important, bincode 1 still compiles with rust 1.18.
66//! - Before serde we had rustc-serializer. Serde has more than replaced rustc-serializer, but we can imagine a future where serde is replaced by something else.
67//! - We believe that less dependencies is better, and that you should be able to choose your own dependencies. If you disable all features, bincode 2 only has 1 dependency. ([`unty`\], a micro crate we manage ourselves)
68//!
69//! **note:** just because we're making serde an optional dependency, it does not mean we're dropping support for serde. Serde will still be fully supported, we're just giving you the option to not use it.
70//!
71//! [Decode]: ../de/trait.Decode.html
72//! [Encode]: ../enc/trait.Encode.html
73//! [`unty`\]: <https://crates.io/crates/unty>
74
75mod de_borrowed;
76mod de_owned;
77mod ser;
78
79pub use self::de_borrowed::*;
80pub use self::de_owned::*;
81pub use self::ser::*;
82
83use serde::de::Visitor;
84
85#[cfg(feature = "async-fiber")]
86#[doc(alias = "decode_serde_async")]
87#[doc(inline)]
88pub use crate::decode_serde_async as decode_async;
89#[cfg(feature = "async-fiber")]
90#[doc(alias = "decode_serde_async_with_context")]
91#[doc(inline)]
92pub use crate::decode_serde_async_with_context as decode_async_with_context;
93#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
94#[doc(alias = "decode_serde_async_tokio")]
95#[doc(inline)]
96pub use crate::decode_serde_tokio_async as decode_async_tokio;
97#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
98#[doc(alias = "decode_serde_async_tokio_with_context")]
99#[doc(inline)]
100pub use crate::decode_serde_tokio_async_with_context as decode_async_tokio_with_context;
101
102#[doc(hidden)]
103#[macro_export]
104#[rustfmt::skip]
105macro_rules! bincode_error_serde {
106    (
107        $(#[$meta:meta])*
108        $vis:vis enum $name:ident {
109            $(
110                $(#[$variant_meta:meta])*
111                $variant:ident $( { $( $(#[$field_meta:meta])* $field:ident : $ftype:ty ),* $(,)? } )? $( ( $( $(#[$tuple_meta:meta])* $tname:ident : $ttype:ty ),* $(,)? ) )?
112            ),* $(,)?
113        }
114    ) => {
115        $(#[$meta])*
116        $vis enum $name {
117            $(
118                $(#[$variant_meta])*
119                $variant $( { $( $(#[$field_meta])* $field : $ftype ),* } )? $( ( $( $(#[$tuple_meta])* $ttype ),* ) )?,
120            )*
121        }
122
123        pastey::paste! {
124            $(
125                $(#[$variant_meta])*
126                #[doc(hidden)]
127                #[cold]
128                #[track_caller]
129                #[inline(never)]
130                pub const fn [<cold_ $name:snake _ $variant:snake>]<'de, V>(
131                    $($($field : $ftype),*)?
132                    $($($tname : $ttype),*)?
133                ) -> core::result::Result<<V as Visitor<'de>>::Value, $name>
134                where
135                    V: Visitor<'de>,
136                {
137                    core::result::Result::Err($name::$variant $( { $($field),* } )? $( ( $( $tname ),* ) )?)
138                }
139            )*
140        }
141    };
142}
143
144bincode_error_serde! {
145    /// A serde-specific error that occurred while decoding.
146    #[derive(Debug)]
147    #[non_exhaustive]
148    pub enum DecodeError {
149        /// Bincode does not support serde's `any` decoding feature.
150        ///
151        /// See the "known issues" list in the serde module for more information on this.
152        AnyNotSupported,
153
154        /// Bincode does not support serde identifiers
155        IdentifierNotSupported,
156
157        /// Bincode does not support serde's `ignored_any`.
158        ///
159        /// See the "known issues" list in the serde module for more information on this.
160        IgnoredAnyNotSupported,
161
162        /// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead
163        CannotBorrowOwnedData,
164
165        /// Could not allocate data like `String` and `Vec<u8>`
166        #[cfg(not(feature = "alloc"))]
167        CannotAllocate,
168
169        /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
170        #[cfg(not(feature = "alloc"))]
171        CustomError,
172    }
173}
174
175#[cfg(feature = "alloc")]
176impl serde::de::Error for crate::error::DecodeError {
177    fn custom<T>(msg: T) -> Self
178    where
179        T: core::fmt::Display,
180    {
181        use alloc::string::ToString;
182        crate::error::cold_decode_error_other_string::<()>(msg.to_string()).unwrap_err()
183    }
184}
185
186#[cfg(not(feature = "alloc"))]
187impl serde::de::Error for crate::error::DecodeError {
188    fn custom<T>(_: T) -> Self
189    where
190        T: core::fmt::Display,
191    {
192        crate::error::cold_decode_error_serde::<()>(DecodeError::CustomError).unwrap_err()
193    }
194}
195
196/// A serde-specific error that occurred while encoding.
197#[derive(Debug)]
198#[non_exhaustive]
199pub enum EncodeError {
200    /// Serde provided bincode with a sequence without a length, which is not supported in bincode
201    SequenceMustHaveLength,
202
203    /// [Serializer::collect_str] got called but bincode was unable to allocate memory.
204    #[cfg(not(feature = "alloc"))]
205    CannotCollectStr,
206
207    /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
208    #[cfg(not(feature = "alloc"))]
209    CustomError,
210}
211
212#[allow(clippy::from_over_into)]
213impl Into<crate::error::EncodeError> for EncodeError {
214    fn into(self) -> crate::error::EncodeError {
215        crate::error::cold_encode_error_serde::<()>(self).unwrap_err()
216    }
217}
218
219#[cfg(feature = "alloc")]
220impl serde::ser::Error for crate::error::EncodeError {
221    fn custom<T>(msg: T) -> Self
222    where
223        T: core::fmt::Display,
224    {
225        use alloc::string::ToString;
226
227        crate::error::cold_encode_error_other_string::<()>(msg.to_string()).unwrap_err()
228    }
229}
230
231#[cfg(not(feature = "alloc"))]
232impl serde::ser::Error for crate::error::EncodeError {
233    fn custom<T>(_: T) -> Self
234    where
235        T: core::fmt::Display,
236    {
237        crate::error::cold_encode_error_serde::<()>(EncodeError::CustomError).unwrap_err()
238    }
239}
240
241/// Wrapper struct that implements [`crate::Decode`\] and [`crate::Encode`\] on any type that implements serde's [`DeserializeOwned`\] and [`Serialize`\] respectively.
242///
243/// This works for most types, but if you're dealing with borrowed data consider using [`BorrowCompat`\] instead.
244///
245/// [Decode]: ../de/trait.Decode.html
246/// [Encode]: ../enc/trait.Encode.html
247/// [DeserializeOwned]: https://docs.rs/serde/1/serde/de/trait.DeserializeOwned.html
248/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html
249#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
250pub struct Compat<T>(pub T);
251
252impl<Context, T> crate::Decode<Context> for Compat<T>
253where
254    T: serde::de::DeserializeOwned,
255{
256    fn decode<D: crate::de::Decoder>(decoder: &mut D) -> Result<Self, crate::error::DecodeError> {
257        let serde_decoder = de_owned::SerdeDecoder { de: decoder };
258        T::deserialize(serde_decoder).map(Compat)
259    }
260}
261impl<'de, T, Context> crate::BorrowDecode<'de, Context> for Compat<T>
262where
263    T: serde::de::DeserializeOwned,
264{
265    fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
266        decoder: &mut D
267    ) -> Result<Self, crate::error::DecodeError> {
268        let serde_decoder = de_owned::SerdeDecoder { de: decoder };
269        T::deserialize(serde_decoder).map(Compat)
270    }
271}
272
273impl<T> crate::Encode for Compat<T>
274where
275    T: serde::Serialize,
276{
277    fn encode<E: crate::enc::Encoder>(
278        &self,
279        encoder: &mut E,
280    ) -> Result<(), crate::error::EncodeError> {
281        let serializer = ser::SerdeEncoder { enc: encoder };
282        self.0.serialize(serializer)?;
283        Ok(())
284    }
285}
286
287impl<T> core::fmt::Debug for Compat<T>
288where
289    T: core::fmt::Debug,
290{
291    fn fmt(
292        &self,
293        f: &mut core::fmt::Formatter<'_>,
294    ) -> core::fmt::Result {
295        f.debug_tuple("Compat").field(&self.0).finish()
296    }
297}
298
299impl<T> core::fmt::Display for Compat<T>
300where
301    T: core::fmt::Display,
302{
303    fn fmt(
304        &self,
305        f: &mut core::fmt::Formatter<'_>,
306    ) -> core::fmt::Result {
307        self.0.fmt(f)
308    }
309}
310
311/// Wrapper struct that implements [`crate::de::BorrowDecode`\] and [`crate::Encode`\] on any type that implements serde's [`Deserialize`\] and [`Serialize`\] respectively.
312///
313/// This is mostly used on `&[u8]` and `&str`, for other types consider using [`Compat`\] instead.
314/// [`Deserialize`\]: <https://docs.rs/serde/1/serde/de/trait.Deserialize.html>
315/// [`Serialize`\]: <https://docs.rs/serde/1/serde/trait.Serialize.html>
316#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
317pub struct BorrowCompat<T>(pub T);
318
319impl<'de, T, Context> crate::de::BorrowDecode<'de, Context> for BorrowCompat<T>
320where
321    T: serde::de::Deserialize<'de>,
322{
323    fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
324        decoder: &mut D
325    ) -> Result<Self, crate::error::DecodeError> {
326        let serde_decoder = de_borrowed::SerdeDecoder {
327            de: decoder,
328            pd: core::marker::PhantomData,
329        };
330        T::deserialize(serde_decoder).map(BorrowCompat)
331    }
332}
333
334impl<T> crate::Encode for BorrowCompat<T>
335where
336    T: serde::Serialize,
337{
338    fn encode<E: crate::enc::Encoder>(
339        &self,
340        encoder: &mut E,
341    ) -> Result<(), crate::error::EncodeError> {
342        let serializer = ser::SerdeEncoder { enc: encoder };
343        self.0.serialize(serializer)?;
344        Ok(())
345    }
346}
347
348impl<T> core::fmt::Debug for BorrowCompat<T>
349where
350    T: core::fmt::Debug,
351{
352    fn fmt(
353        &self,
354        f: &mut core::fmt::Formatter<'_>,
355    ) -> core::fmt::Result {
356        f.debug_tuple("BorrowCompat").field(&self.0).finish()
357    }
358}
359
360impl<T> core::fmt::Display for BorrowCompat<T>
361where
362    T: core::fmt::Display,
363{
364    fn fmt(
365        &self,
366        f: &mut core::fmt::Formatter<'_>,
367    ) -> core::fmt::Result {
368        self.0.fmt(f)
369    }
370}