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}