Skip to content

Commit a4365a1

Browse files
Made serde able to be used with alloc and no_std targets
1 parent 447c4c7 commit a4365a1

File tree

7 files changed

+165
-34
lines changed

7 files changed

+165
-34
lines changed

.github/workflows/rust.yml

+4
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@
8585
"alloc,derive",
8686
"std",
8787
"std,derive",
88+
"serde_no_std",
89+
"serde_alloc",
8890
"serde",
91+
"serde_no_std,derive",
92+
"serde_alloc,derive",
8993
"serde,derive"
9094
]
9195
}

Cargo.toml

+11-7
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,23 @@ atomic = []
3030
derive = ["bincode_derive"]
3131

3232
# BlockedTODO: https://github.com/rust-lang/cargo/issues/8832
33-
# We really want these features to automatically be enabled when both "serde" and either "alloc"/"std" is enabled
34-
# But this is currently not possible
35-
serde = ["std", "serde_incl", "serde_incl/std"]
33+
# We want to enable these features automatically based on "alloc" or "std"
34+
# std = ["alloc", "serde?/std"]
35+
# alloc = ["serde?/alloc"]
36+
# now we have to do this hack:
37+
serde = ["serde_incl/std", "std", "serde_alloc"] # std
38+
serde_alloc = ["serde_incl/alloc", "alloc"] # alloc
39+
serde_no_std = ["serde_incl"] # no_std
3640

3741
[dependencies]
3842
bincode_derive = { path = "derive", version = "2.0.0-beta.0", optional = true }
39-
serde_incl = { package = "serde", version = "1.0.130", optional = true }
43+
serde_incl = { package = "serde", version = "1.0", default-features = false, optional = true }
4044

4145
# Used for tests
4246
[dev-dependencies]
43-
serde_derive = "1.0.130"
44-
serde_json = "1.0.68"
45-
tempfile = "3.2.0"
47+
serde_derive = "1.0"
48+
serde_json = { version = "1.0", default-features = false }
49+
tempfile = "3.2"
4650
criterion = "0.3"
4751
rand = "0.8"
4852
uuid = { version = "0.8", features = ["serde"] }

src/error.rs

+4-16
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ pub enum EncodeError {
5151
time: std::time::SystemTime,
5252
},
5353

54-
/// Serde provided bincode with a sequence without a length, which is not supported in bincode
5554
#[cfg(feature = "serde")]
56-
SequenceMustHaveLength,
55+
/// A serde-specific error that occured while decoding.
56+
Serde(crate::features::serde::EncodeError),
5757
}
5858

5959
impl core::fmt::Display for EncodeError {
@@ -157,21 +157,9 @@ pub enum DecodeError {
157157
#[cfg(feature = "alloc")]
158158
OtherString(alloc::string::String),
159159

160-
/// Bincode does not support serde's `any` decoding feature
161160
#[cfg(feature = "serde")]
162-
SerdeAnyNotSupported,
163-
164-
/// Bincode does not support serde identifiers
165-
#[cfg(feature = "serde")]
166-
SerdeIdentifierNotSupported,
167-
168-
/// Bincode does not support serde's `ignored_any`
169-
#[cfg(feature = "serde")]
170-
SerdeIgnoredAnyNotSupported,
171-
172-
/// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead
173-
#[cfg(feature = "serde")]
174-
CannotBorrowOwnedData,
161+
/// A serde-specific error that occured while decoding.
162+
Serde(crate::features::serde::DecodeError),
175163
}
176164

177165
impl core::fmt::Display for DecodeError {

src/features/serde/de_borrowed.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::DecodeError as SerdeDecodeError;
12
use crate::{
23
config::Config,
34
de::{BorrowDecode, BorrowDecoder, Decode},
@@ -33,7 +34,7 @@ impl<'a, 'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'a, 'de
3334
where
3435
V: serde_incl::de::Visitor<'de>,
3536
{
36-
Err(DecodeError::SerdeAnyNotSupported)
37+
Err(SerdeDecodeError::AnyNotSupported.into())
3738
}
3839

3940
fn deserialize_bool<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
@@ -128,6 +129,15 @@ impl<'a, 'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'a, 'de
128129
visitor.visit_borrowed_str(str)
129130
}
130131

132+
#[cfg(not(feature = "alloc"))]
133+
fn deserialize_string<V>(self, _: V) -> Result<V::Value, Self::Error>
134+
where
135+
V: serde_incl::de::Visitor<'de>,
136+
{
137+
Err(SerdeDecodeError::CannotBorrowOwnedData.into())
138+
}
139+
140+
#[cfg(feature = "alloc")]
131141
fn deserialize_string<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
132142
where
133143
V: serde_incl::de::Visitor<'de>,
@@ -143,6 +153,15 @@ impl<'a, 'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'a, 'de
143153
visitor.visit_borrowed_bytes(bytes)
144154
}
145155

156+
#[cfg(not(feature = "alloc"))]
157+
fn deserialize_byte_buf<V>(self, _: V) -> Result<V::Value, Self::Error>
158+
where
159+
V: serde_incl::de::Visitor<'de>,
160+
{
161+
Err(SerdeDecodeError::CannotBorrowOwnedData.into())
162+
}
163+
164+
#[cfg(feature = "alloc")]
146165
fn deserialize_byte_buf<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
147166
where
148167
V: serde_incl::de::Visitor<'de>,
@@ -339,14 +358,14 @@ impl<'a, 'de, DE: BorrowDecoder<'de>> Deserializer<'de> for SerdeDecoder<'a, 'de
339358
where
340359
V: serde_incl::de::Visitor<'de>,
341360
{
342-
Err(DecodeError::SerdeIdentifierNotSupported)
361+
Err(SerdeDecodeError::IdentifierNotSupported.into())
343362
}
344363

345364
fn deserialize_ignored_any<V>(self, _: V) -> Result<V::Value, Self::Error>
346365
where
347366
V: serde_incl::de::Visitor<'de>,
348367
{
349-
Err(DecodeError::SerdeIgnoredAnyNotSupported)
368+
Err(SerdeDecodeError::IgnoredAnyNotSupported.into())
350369
}
351370
}
352371

src/features/serde/de_owned.rs

+24-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::DecodeError as SerdeDecodeError;
12
use crate::{
23
config::Config,
34
de::{Decode, Decoder},
@@ -34,7 +35,7 @@ impl<'a, 'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'a, DE> {
3435
where
3536
V: serde_incl::de::Visitor<'de>,
3637
{
37-
Err(DecodeError::SerdeAnyNotSupported)
38+
Err(SerdeDecodeError::AnyNotSupported.into())
3839
}
3940

4041
fn deserialize_bool<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
@@ -130,20 +131,29 @@ impl<'a, 'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'a, DE> {
130131
}
131132

132133
#[cfg(not(feature = "alloc"))]
133-
fn deserialize_str<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
134+
fn deserialize_str<V>(self, _: V) -> Result<V::Value, Self::Error>
134135
where
135136
V: serde_incl::de::Visitor<'de>,
136137
{
137-
Err(DecodeError::CannotBorrowOwnedData)
138+
Err(SerdeDecodeError::CannotBorrowOwnedData.into())
138139
}
139140

141+
#[cfg(feature = "alloc")]
140142
fn deserialize_string<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
141143
where
142144
V: serde_incl::de::Visitor<'de>,
143145
{
144146
visitor.visit_string(Decode::decode(&mut self.de)?)
145147
}
146148

149+
#[cfg(not(feature = "alloc"))]
150+
fn deserialize_string<V>(self, _: V) -> Result<V::Value, Self::Error>
151+
where
152+
V: serde_incl::de::Visitor<'de>,
153+
{
154+
Err(SerdeDecodeError::CannotAllocate.into())
155+
}
156+
147157
#[cfg(feature = "alloc")]
148158
fn deserialize_bytes<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
149159
where
@@ -157,15 +167,23 @@ impl<'a, 'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'a, DE> {
157167
where
158168
V: serde_incl::de::Visitor<'de>,
159169
{
160-
Err(DecodeError::CannotBorrowOwnedData)
170+
Err(SerdeDecodeError::CannotBorrowOwnedData.into())
161171
}
162172

173+
#[cfg(feature = "alloc")]
163174
fn deserialize_byte_buf<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
164175
where
165176
V: serde_incl::de::Visitor<'de>,
166177
{
167178
visitor.visit_byte_buf(Decode::decode(&mut self.de)?)
168179
}
180+
#[cfg(not(feature = "alloc"))]
181+
fn deserialize_byte_buf<V>(self, _: V) -> Result<V::Value, Self::Error>
182+
where
183+
V: serde_incl::de::Visitor<'de>,
184+
{
185+
Err(SerdeDecodeError::CannotAllocate.into())
186+
}
169187

170188
fn deserialize_option<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
171189
where
@@ -353,14 +371,14 @@ impl<'a, 'de, DE: Decoder> Deserializer<'de> for SerdeDecoder<'a, DE> {
353371
where
354372
V: serde_incl::de::Visitor<'de>,
355373
{
356-
Err(DecodeError::SerdeIdentifierNotSupported)
374+
Err(SerdeDecodeError::IdentifierNotSupported.into())
357375
}
358376

359377
fn deserialize_ignored_any<V>(self, _: V) -> Result<V::Value, Self::Error>
360378
where
361379
V: serde_incl::de::Visitor<'de>,
362380
{
363-
Err(DecodeError::SerdeIgnoredAnyNotSupported)
381+
Err(SerdeDecodeError::IgnoredAnyNotSupported.into())
364382
}
365383
}
366384

src/features/serde/mod.rs

+89
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@
4040
//! # }
4141
//! ```
4242
//!
43+
//! # `alloc` and `no_std`
44+
//!
45+
//! The `serde` feature enables both `alloc` and `std` at this point in time.
46+
//! To use bincode and serde on no_std targets, try one of the following features:
47+
//!
48+
//! - `serde_alloc`: enables `serde` and `alloc`
49+
//! - `serde_no_std`: enables `serde` without `alloc` or `std`
50+
//!
4351
//! # Known issues
4452
//!
4553
//! Currently the `serde` feature will automatically enable the `alloc` and `std` feature. If you're running in a `#[no_std]` environment consider using bincode's own derive macros.
@@ -66,6 +74,60 @@ pub use self::de_borrowed::*;
6674
pub use self::de_owned::*;
6775
pub use self::ser::*;
6876

77+
/// A serde-specific error that occured while decoding.
78+
#[derive(Debug, PartialEq)]
79+
pub enum DecodeError {
80+
/// Bincode does not support serde's `any` decoding feature
81+
AnyNotSupported,
82+
83+
/// Bincode does not support serde identifiers
84+
IdentifierNotSupported,
85+
86+
/// Bincode does not support serde's `ignored_any`
87+
IgnoredAnyNotSupported,
88+
89+
/// Serde tried decoding a borrowed value from an owned reader. Use `serde_decode_borrowed_from_*` instead
90+
CannotBorrowOwnedData,
91+
92+
/// Could not allocate data like `String` and `Vec<u8>`
93+
#[cfg(not(feature = "alloc"))]
94+
CannotAllocate,
95+
96+
/// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
97+
#[cfg(not(feature = "alloc"))]
98+
CustomError,
99+
}
100+
101+
#[allow(clippy::from_over_into)]
102+
impl Into<crate::error::DecodeError> for DecodeError {
103+
fn into(self) -> crate::error::DecodeError {
104+
crate::error::DecodeError::Serde(self)
105+
}
106+
}
107+
108+
/// A serde-specific error that occured while encoding.
109+
#[derive(Debug, PartialEq)]
110+
pub enum EncodeError {
111+
/// Serde provided bincode with a sequence without a length, which is not supported in bincode
112+
SequenceMustHaveLength,
113+
114+
/// [Serializer::collect_str] got called but bincode was unable to allocate memory.
115+
#[cfg(not(feature = "alloc"))]
116+
CannotCollectStr,
117+
118+
/// Custom serde error but bincode is unable to allocate a string. Set a breakpoint where this is thrown for more information.
119+
#[cfg(not(feature = "alloc"))]
120+
CustomError,
121+
}
122+
123+
#[allow(clippy::from_over_into)]
124+
impl Into<crate::error::EncodeError> for EncodeError {
125+
fn into(self) -> crate::error::EncodeError {
126+
crate::error::EncodeError::Serde(self)
127+
}
128+
}
129+
130+
#[cfg(feature = "alloc")]
69131
impl serde_incl::de::Error for crate::error::DecodeError {
70132
fn custom<T>(msg: T) -> Self
71133
where
@@ -76,6 +138,20 @@ impl serde_incl::de::Error for crate::error::DecodeError {
76138
}
77139
}
78140

141+
#[cfg(not(feature = "std"))]
142+
impl serde_incl::de::StdError for crate::error::DecodeError {}
143+
144+
#[cfg(not(feature = "alloc"))]
145+
impl serde_incl::de::Error for crate::error::DecodeError {
146+
fn custom<T>(_: T) -> Self
147+
where
148+
T: core::fmt::Display,
149+
{
150+
DecodeError::CustomError.into()
151+
}
152+
}
153+
154+
#[cfg(feature = "alloc")]
79155
impl serde_incl::ser::Error for crate::error::EncodeError {
80156
fn custom<T>(msg: T) -> Self
81157
where
@@ -87,6 +163,19 @@ impl serde_incl::ser::Error for crate::error::EncodeError {
87163
}
88164
}
89165

166+
#[cfg(not(feature = "std"))]
167+
impl serde_incl::de::StdError for crate::error::EncodeError {}
168+
169+
#[cfg(not(feature = "alloc"))]
170+
impl serde_incl::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+
90179
/// Wrapper struct that implements [Decode] and [Encode] on any type that implements serde's [DeserializeOwned] and [Serialize] respectively.
91180
///
92181
/// This works for most types, but if you're dealing with borrowed data consider using [BorrowCompat] instead.

src/features/serde/ser.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::EncodeError as SerdeEncodeError;
12
use crate::{
23
config::Config,
34
enc::{Encode, Encoder},
@@ -165,7 +166,7 @@ where
165166
}
166167

167168
fn serialize_seq(mut self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
168-
let len = len.ok_or(EncodeError::SequenceMustHaveLength)?;
169+
let len = len.ok_or_else(|| SerdeEncodeError::SequenceMustHaveLength.into())?;
169170
len.encode(&mut self.enc)?;
170171
Ok(Compound { enc: self.enc })
171172
}
@@ -196,7 +197,7 @@ where
196197
}
197198

198199
fn serialize_map(mut self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
199-
let len = len.ok_or(EncodeError::SequenceMustHaveLength)?;
200+
let len = len.ok_or_else(|| SerdeEncodeError::SequenceMustHaveLength.into())?;
200201
len.encode(&mut self.enc)?;
201202
Ok(Compound { enc: self.enc })
202203
}
@@ -219,6 +220,14 @@ where
219220
variant_index.encode(&mut self.enc)?;
220221
Ok(Compound { enc: self.enc })
221222
}
223+
224+
#[cfg(not(feature = "alloc"))]
225+
fn collect_str<T: ?Sized>(self, _: &T) -> Result<Self::Ok, Self::Error>
226+
where
227+
T: core::fmt::Display,
228+
{
229+
Err(SerdeEncodeError::CannotCollectStr.into())
230+
}
222231
}
223232

224233
type Compound<'a, ENC> = SerdeEncoder<'a, ENC>;

0 commit comments

Comments
 (0)