bincode/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::{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//! # Why move away from serde?
56//!
57//! Serde is a great library, but it has some issues that makes us want to be decoupled from serde:
58//! - The issues documented above with attributes.
59//! - 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.
60//! - 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.
61//! - 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)
62//!
63//! **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.
64//!
65//! [Decode]: ../de/trait.Decode.html
66//! [Encode]: ../enc/trait.Encode.html
67//! [`unty`]: https://crates.io/crates/unty
68
69mod de_borrowed;
70mod de_owned;
71mod ser;
72
73pub use self::de_borrowed::*;
74pub use self::de_owned::*;
75pub use self::ser::*;
76
77/// A serde-specific error that occurred while decoding.
78#[derive(Debug)]
79#[non_exhaustive]
80pub enum DecodeError {
81    /// Bincode does not support serde's `any` decoding feature.
82    ///
83    /// See the "known issues" list in the serde module for more information on this.
84    AnyNotSupported,
85
86    /// Bincode does not support serde identifiers
87    IdentifierNotSupported,
88
89    /// Bincode does not support serde's `ignored_any`.
90    ///
91    /// See the "known issues" list in the serde module for more information on this.
92    IgnoredAnyNotSupported,
93
94    /// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead
95    CannotBorrowOwnedData,
96
97    /// Could not allocate data like `String` and `Vec<u8>`
98    #[cfg(not(feature = "alloc"))]
99    CannotAllocate,
100
101    /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
102    #[cfg(not(feature = "alloc"))]
103    CustomError,
104}
105
106#[cfg(feature = "alloc")]
107impl serde::de::Error for crate::error::DecodeError {
108    fn custom<T>(msg: T) -> Self
109    where
110        T: core::fmt::Display,
111    {
112        use alloc::string::ToString;
113        Self::OtherString(msg.to_string())
114    }
115}
116
117#[cfg(not(feature = "alloc"))]
118impl serde::de::Error for crate::error::DecodeError {
119    fn custom<T>(_: T) -> Self
120    where
121        T: core::fmt::Display,
122    {
123        DecodeError::CustomError.into()
124    }
125}
126
127#[allow(clippy::from_over_into)]
128impl Into<crate::error::DecodeError> for DecodeError {
129    fn into(self) -> crate::error::DecodeError {
130        crate::error::DecodeError::Serde(self)
131    }
132}
133
134/// A serde-specific error that occurred while encoding.
135#[derive(Debug)]
136#[non_exhaustive]
137pub enum EncodeError {
138    /// Serde provided bincode with a sequence without a length, which is not supported in bincode
139    SequenceMustHaveLength,
140
141    /// [Serializer::collect_str] got called but bincode was unable to allocate memory.
142    #[cfg(not(feature = "alloc"))]
143    CannotCollectStr,
144
145    /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
146    #[cfg(not(feature = "alloc"))]
147    CustomError,
148}
149
150#[allow(clippy::from_over_into)]
151impl Into<crate::error::EncodeError> for EncodeError {
152    fn into(self) -> crate::error::EncodeError {
153        crate::error::EncodeError::Serde(self)
154    }
155}
156
157#[cfg(feature = "alloc")]
158impl serde::ser::Error for crate::error::EncodeError {
159    fn custom<T>(msg: T) -> Self
160    where
161        T: core::fmt::Display,
162    {
163        use alloc::string::ToString;
164
165        Self::OtherString(msg.to_string())
166    }
167}
168
169#[cfg(not(feature = "alloc"))]
170impl serde::ser::Error for crate::error::EncodeError {
171    fn custom<T>(_: T) -> Self
172    where
173        T: core::fmt::Display,
174    {
175        EncodeError::CustomError.into()
176    }
177}
178
179/// Wrapper struct that implements [Decode] and [Encode] on any type that implements serde's [DeserializeOwned] and [Serialize] respectively.
180///
181/// This works for most types, but if you're dealing with borrowed data consider using [BorrowCompat] instead.
182///
183/// [Decode]: ../de/trait.Decode.html
184/// [Encode]: ../enc/trait.Encode.html
185/// [DeserializeOwned]: https://docs.rs/serde/1/serde/de/trait.DeserializeOwned.html
186/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html
187#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
188pub struct Compat<T>(pub T);
189
190impl<Context, T> crate::Decode<Context> for Compat<T>
191where
192    T: serde::de::DeserializeOwned,
193{
194    fn decode<D: crate::de::Decoder>(decoder: &mut D) -> Result<Self, crate::error::DecodeError> {
195        let serde_decoder = de_owned::SerdeDecoder { de: decoder };
196        T::deserialize(serde_decoder).map(Compat)
197    }
198}
199impl<'de, T, Context> crate::BorrowDecode<'de, Context> for Compat<T>
200where
201    T: serde::de::DeserializeOwned,
202{
203    fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
204        decoder: &mut D,
205    ) -> Result<Self, crate::error::DecodeError> {
206        let serde_decoder = de_owned::SerdeDecoder { de: decoder };
207        T::deserialize(serde_decoder).map(Compat)
208    }
209}
210
211impl<T> crate::Encode for Compat<T>
212where
213    T: serde::Serialize,
214{
215    fn encode<E: crate::enc::Encoder>(
216        &self,
217        encoder: &mut E,
218    ) -> Result<(), crate::error::EncodeError> {
219        let serializer = ser::SerdeEncoder { enc: encoder };
220        self.0.serialize(serializer)?;
221        Ok(())
222    }
223}
224
225impl<T> core::fmt::Debug for Compat<T>
226where
227    T: core::fmt::Debug,
228{
229    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
230        f.debug_tuple("Compat").field(&self.0).finish()
231    }
232}
233
234impl<T> core::fmt::Display for Compat<T>
235where
236    T: core::fmt::Display,
237{
238    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
239        self.0.fmt(f)
240    }
241}
242
243/// Wrapper struct that implements [BorrowDecode] and [Encode] on any type that implements serde's [Deserialize] and [Serialize] respectively. This is mostly used on `&[u8]` and `&str`, for other types consider using [Compat] instead.
244///
245/// [BorrowDecode]: ../de/trait.BorrowDecode.html
246/// [Encode]: ../enc/trait.Encode.html
247/// [Deserialize]: https://docs.rs/serde/1/serde/de/trait.Deserialize.html
248/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html
249#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
250pub struct BorrowCompat<T>(pub T);
251
252impl<'de, T, Context> crate::de::BorrowDecode<'de, Context> for BorrowCompat<T>
253where
254    T: serde::de::Deserialize<'de>,
255{
256    fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
257        decoder: &mut D,
258    ) -> Result<Self, crate::error::DecodeError> {
259        let serde_decoder = de_borrowed::SerdeDecoder {
260            de: decoder,
261            pd: core::marker::PhantomData,
262        };
263        T::deserialize(serde_decoder).map(BorrowCompat)
264    }
265}
266
267impl<T> crate::Encode for BorrowCompat<T>
268where
269    T: serde::Serialize,
270{
271    fn encode<E: crate::enc::Encoder>(
272        &self,
273        encoder: &mut E,
274    ) -> Result<(), crate::error::EncodeError> {
275        let serializer = ser::SerdeEncoder { enc: encoder };
276        self.0.serialize(serializer)?;
277        Ok(())
278    }
279}
280
281impl<T> core::fmt::Debug for BorrowCompat<T>
282where
283    T: core::fmt::Debug,
284{
285    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
286        f.debug_tuple("BorrowCompat").field(&self.0).finish()
287    }
288}
289
290impl<T> core::fmt::Display for BorrowCompat<T>
291where
292    T: core::fmt::Display,
293{
294    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
295        self.0.fmt(f)
296    }
297}