Skip to main content

bincode/features/serde/
mod.rs

1//! Support for serde integration. Enable this with the `serde` feature.
2//!
3//! Use the `*_untrusted` functions or decoder constructors to opt into
4//! [collection allocation safeguards](crate#untrusted-input). Ordinary functions
5//! retain upstream size hints and allocation behavior. [`Compat`], [`BorrowCompat`],
6//! and `#[bincode(with_serde)]` inherit the enclosing native decoder's policy.
7//!
8//! To encode/decode type that implement serde's trait, you can use:
9//! - [borrow_decode_from_slice]
10//! - [decode_from_slice]
11//! - [encode_into_slice]
12//! - [encode_to_vec]
13//!
14//! For interop with bincode's [Decode]/[Encode], you can use:
15//! - [Compat]
16//! - [BorrowCompat]
17//!
18//! For interop with bincode's `derive` feature, you can use the `#[bincode(with_serde)]` attribute on each field that implements serde's traits.
19//!
20//! ```
21//! # #[cfg(feature = "derive")]
22//! # mod foo {
23//! # use bincode::{Decode, Encode};
24//! # use serde_derive::{Deserialize, Serialize};
25//! #[derive(Serialize, Deserialize)]
26//! pub struct SerdeType {
27//!     // ...
28//! }
29//!
30//! #[derive(Decode, Encode)]
31//! pub struct StructWithSerde {
32//!     #[bincode(with_serde)]
33//!     pub serde: SerdeType,
34//! }
35//!
36//! #[derive(Decode, Encode)]
37//! pub enum EnumWithSerde {
38//!     Unit(#[bincode(with_serde)] SerdeType),
39//!     Struct {
40//!         #[bincode(with_serde)]
41//!         serde: SerdeType,
42//!     },
43//! }
44//! # }
45//! ```
46//!
47//! # Known issues
48//!
49//! 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.
50//! - `#[serde(flatten)]`
51//! - `#[serde(skip)]`
52//! - `#[serde(skip_deserializing)]`
53//! - `#[serde(skip_serializing)]`
54//! - `#[serde(skip_serializing_if = "path")]`
55//! - `#[serde(tag = "...")]`
56//! - `#[serde(untagged)]`
57//!
58//! **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.
59//!
60//! # Why move away from serde?
61//!
62//! Serde is a great library, but it has some issues that makes us want to be decoupled from serde:
63//! - The issues documented above with attributes.
64//! - 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.
65//! - 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.
66//! - 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)
67//!
68//! **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.
69//!
70//! [Decode]: ../de/trait.Decode.html
71//! [Encode]: ../enc/trait.Encode.html
72//! [`unty`]: https://crates.io/crates/unty
73
74mod de_borrowed;
75mod de_owned;
76mod de_policy;
77mod ser;
78mod untrusted;
79pub use untrusted::{DeserializeSeedUntrusted, DeserializeUntrusted};
80
81pub use self::de_borrowed::*;
82pub use self::de_owned::*;
83pub use self::ser::*;
84
85/// A serde-specific error that occurred while decoding.
86#[derive(Debug)]
87#[non_exhaustive]
88pub enum DecodeError {
89    /// Bincode does not support serde's `any` decoding feature.
90    ///
91    /// See the "known issues" list in the serde module for more information on this.
92    AnyNotSupported,
93
94    /// Bincode does not support serde identifiers
95    IdentifierNotSupported,
96
97    /// Bincode does not support serde's `ignored_any`.
98    ///
99    /// See the "known issues" list in the serde module for more information on this.
100    IgnoredAnyNotSupported,
101
102    /// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead
103    CannotBorrowOwnedData,
104
105    /// Could not allocate data like `String` and `Vec<u8>`
106    #[cfg(not(feature = "alloc"))]
107    CannotAllocate,
108
109    /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
110    #[cfg(not(feature = "alloc"))]
111    CustomError,
112}
113
114#[cfg(feature = "alloc")]
115impl serde::de::Error for crate::error::DecodeError {
116    fn custom<T>(msg: T) -> Self
117    where
118        T: core::fmt::Display,
119    {
120        use alloc::string::ToString;
121        Self::OtherString(msg.to_string())
122    }
123}
124
125#[cfg(not(feature = "std"))]
126impl serde::de::StdError for crate::error::DecodeError {}
127
128#[cfg(not(feature = "alloc"))]
129impl serde::de::Error for crate::error::DecodeError {
130    fn custom<T>(_: T) -> Self
131    where
132        T: core::fmt::Display,
133    {
134        DecodeError::CustomError.into()
135    }
136}
137
138#[allow(clippy::from_over_into)]
139impl Into<crate::error::DecodeError> for DecodeError {
140    fn into(self) -> crate::error::DecodeError {
141        crate::error::DecodeError::Serde(self)
142    }
143}
144
145/// A serde-specific error that occurred while encoding.
146#[derive(Debug)]
147#[non_exhaustive]
148pub enum EncodeError {
149    /// Serde provided bincode with a sequence without a length, which is not supported in bincode
150    SequenceMustHaveLength,
151
152    /// [Serializer::collect_str] got called but bincode was unable to allocate memory.
153    #[cfg(not(feature = "alloc"))]
154    CannotCollectStr,
155
156    /// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
157    #[cfg(not(feature = "alloc"))]
158    CustomError,
159}
160
161#[allow(clippy::from_over_into)]
162impl Into<crate::error::EncodeError> for EncodeError {
163    fn into(self) -> crate::error::EncodeError {
164        crate::error::EncodeError::Serde(self)
165    }
166}
167
168#[cfg(feature = "alloc")]
169impl serde::ser::Error for crate::error::EncodeError {
170    fn custom<T>(msg: T) -> Self
171    where
172        T: core::fmt::Display,
173    {
174        use alloc::string::ToString;
175
176        Self::OtherString(msg.to_string())
177    }
178}
179
180#[cfg(not(feature = "std"))]
181impl serde::de::StdError for crate::error::EncodeError {}
182
183#[cfg(not(feature = "alloc"))]
184impl serde::ser::Error for crate::error::EncodeError {
185    fn custom<T>(_: T) -> Self
186    where
187        T: core::fmt::Display,
188    {
189        EncodeError::CustomError.into()
190    }
191}
192
193/// Wrapper struct that implements [Decode] and [Encode] on any type that implements serde's [DeserializeOwned] and [Serialize] respectively.
194///
195/// This works for most types, but if you're dealing with borrowed data consider using [BorrowCompat] instead.
196///
197/// [Decode]: ../de/trait.Decode.html
198/// [Encode]: ../enc/trait.Encode.html
199/// [DeserializeOwned]: https://docs.rs/serde/1/serde/de/trait.DeserializeOwned.html
200/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html
201#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
202pub struct Compat<T>(pub T);
203
204impl<Context, T> crate::Decode<Context> for Compat<T>
205where
206    T: serde::de::DeserializeOwned,
207{
208    fn decode<D: crate::de::Decoder>(decoder: &mut D) -> Result<Self, crate::error::DecodeError> {
209        let serde_decoder = de_owned::SerdeDecoder {
210            de: decoder,
211            policy: de_policy::Ordinary,
212        };
213        T::deserialize(serde_decoder).map(Compat)
214    }
215}
216impl<'de, T, Context> crate::BorrowDecode<'de, Context> for Compat<T>
217where
218    T: serde::de::DeserializeOwned,
219{
220    fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
221        decoder: &mut D,
222    ) -> Result<Self, crate::error::DecodeError> {
223        let serde_decoder = de_owned::SerdeDecoder {
224            de: decoder,
225            policy: de_policy::Ordinary,
226        };
227        T::deserialize(serde_decoder).map(Compat)
228    }
229}
230
231impl<T> crate::Encode for Compat<T>
232where
233    T: serde::Serialize,
234{
235    fn encode<E: crate::enc::Encoder>(
236        &self,
237        encoder: &mut E,
238    ) -> Result<(), crate::error::EncodeError> {
239        let serializer = ser::SerdeEncoder { enc: encoder };
240        self.0.serialize(serializer)?;
241        Ok(())
242    }
243}
244
245impl<T> core::fmt::Debug for Compat<T>
246where
247    T: core::fmt::Debug,
248{
249    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
250        f.debug_tuple("Compat").field(&self.0).finish()
251    }
252}
253
254impl<T> core::fmt::Display for Compat<T>
255where
256    T: core::fmt::Display,
257{
258    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
259        self.0.fmt(f)
260    }
261}
262
263/// 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.
264///
265/// [BorrowDecode]: ../de/trait.BorrowDecode.html
266/// [Encode]: ../enc/trait.Encode.html
267/// [Deserialize]: https://docs.rs/serde/1/serde/de/trait.Deserialize.html
268/// [Serialize]: https://docs.rs/serde/1/serde/trait.Serialize.html
269#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
270pub struct BorrowCompat<T>(pub T);
271
272impl<'de, T, Context> crate::de::BorrowDecode<'de, Context> for BorrowCompat<T>
273where
274    T: serde::de::Deserialize<'de>,
275{
276    fn borrow_decode<D: crate::de::BorrowDecoder<'de>>(
277        decoder: &mut D,
278    ) -> Result<Self, crate::error::DecodeError> {
279        let serde_decoder = de_borrowed::SerdeDecoder {
280            policy: de_policy::Ordinary,
281            de: decoder,
282            pd: core::marker::PhantomData,
283        };
284        T::deserialize(serde_decoder).map(BorrowCompat)
285    }
286}
287
288impl<T> crate::Encode for BorrowCompat<T>
289where
290    T: serde::Serialize,
291{
292    fn encode<E: crate::enc::Encoder>(
293        &self,
294        encoder: &mut E,
295    ) -> Result<(), crate::error::EncodeError> {
296        let serializer = ser::SerdeEncoder { enc: encoder };
297        self.0.serialize(serializer)?;
298        Ok(())
299    }
300}
301
302impl<T> core::fmt::Debug for BorrowCompat<T>
303where
304    T: core::fmt::Debug,
305{
306    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
307        f.debug_tuple("BorrowCompat").field(&self.0).finish()
308    }
309}
310
311impl<T> core::fmt::Display for BorrowCompat<T>
312where
313    T: core::fmt::Display,
314{
315    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
316        self.0.fmt(f)
317    }
318}