1use bincode::{
12 de::{BorrowDecoder, Decoder},
13 enc::Encoder,
14 error::{DecodeError, EncodeError},
15};
16use serde::{Serialize, de::DeserializeOwned};
17
18mod de;
19mod ser;
20
21#[derive(Copy, Clone, PartialEq, Eq)]
25#[repr(u8)]
26enum TypeTag {
27 BoolTrue = 1,
28 BoolFalse,
29 U8,
30 U16,
31 U32,
32 U64,
33 I8,
34 I16,
35 I32,
36 I64,
37 F32,
38 F64,
39 Char,
40 String,
41 Bytes,
42 OptionNone,
43 OptionSome,
44 Unit,
45 UnitStruct,
46 UnitVariant,
47 NewtypeStruct,
48 NewtypeVariant,
49 SeqSized,
50 SeqUnsizedStart,
51 Tuple,
52 TupleStruct,
53 TupleVariant,
54 MapSized,
55 MapUnsizedStart,
56 Struct,
57 StructVariant,
58 CollectionEnd,
59}
60
61impl TryFrom<u8> for TypeTag {
62 type Error = DecodeError;
63
64 fn try_from(num: u8) -> Result<Self, DecodeError> {
65 let tag = match num {
66 1 => TypeTag::BoolTrue,
67 2 => TypeTag::BoolFalse,
68 3 => TypeTag::U8,
69 4 => TypeTag::U16,
70 5 => TypeTag::U32,
71 6 => TypeTag::U64,
72 7 => TypeTag::I8,
73 8 => TypeTag::I16,
74 9 => TypeTag::I32,
75 10 => TypeTag::I64,
76 11 => TypeTag::F32,
77 12 => TypeTag::F64,
78 13 => TypeTag::Char,
79 14 => TypeTag::String,
80 15 => TypeTag::Bytes,
81 16 => TypeTag::OptionNone,
82 17 => TypeTag::OptionSome,
83 18 => TypeTag::Unit,
84 19 => TypeTag::UnitStruct,
85 20 => TypeTag::UnitVariant,
86 21 => TypeTag::NewtypeStruct,
87 22 => TypeTag::NewtypeVariant,
88 23 => TypeTag::SeqSized,
89 24 => TypeTag::SeqUnsizedStart,
90 25 => TypeTag::Tuple,
91 26 => TypeTag::TupleStruct,
92 27 => TypeTag::TupleVariant,
93 28 => TypeTag::MapSized,
94 29 => TypeTag::MapUnsizedStart,
95 30 => TypeTag::Struct,
96 31 => TypeTag::StructVariant,
97 32 => TypeTag::CollectionEnd,
98 _ => {
99 return Err(DecodeError::OtherString(format!("invalid type tag: {num}")));
100 }
101 };
102 debug_assert_eq!(tag as u8, num);
103 Ok(tag)
104 }
105}
106
107pub fn encode<E: Encoder, T: Serialize>(value: &T, encoder: &mut E) -> Result<(), EncodeError> {
108 value
109 .serialize(&mut ser::BincodeSerializer::new(encoder))
110 .map_err(|e| e.0)
111}
112
113pub fn decode<Context, D: Decoder<Context = Context>, T: DeserializeOwned>(
114 decoder: &mut D,
115) -> Result<T, DecodeError> {
116 T::deserialize(de::BincodeDeserializer::new(decoder)).map_err(|e| e.0)
117}
118
119pub fn borrow_decode<
120 'de,
121 Context,
122 D: BorrowDecoder<'de, Context = Context>,
123 T: serde::de::Deserialize<'de>,
124>(
125 decoder: &mut D,
126) -> Result<T, DecodeError> {
127 T::deserialize(de::BincodeDeserializer::new(decoder)).map_err(|e| e.0)
128}
129
130#[cfg(test)]
131mod tests {
132 use std::{collections::HashMap, fmt::Debug};
133
134 use bincode::{Decode, Encode, decode_from_slice, encode_to_vec};
135 use serde::{Deserialize, Serialize, de::DeserializeOwned};
136
137 fn round_trip<T: Serialize + DeserializeOwned + PartialEq + Debug>(value: T) -> T {
138 #[derive(Encode)]
139 #[bincode(encode_bounds = "T: Serialize")]
140 struct EncodeWrapper<'a, T>(#[bincode(with = "crate::serde_self_describing")] &'a T);
141
142 #[derive(Decode)]
143 #[bincode(
144 decode_bounds = "T: DeserializeOwned",
145 borrow_decode_bounds = "T: Deserialize<'__de>"
146 )]
147 struct DecodeWrapper<T>(#[bincode(with = "crate::serde_self_describing")] T);
148
149 let config = bincode::config::standard();
150
151 let encoded = encode_to_vec(EncodeWrapper(&value), config).unwrap();
152 let (DecodeWrapper(decoded), len) = decode_from_slice(&encoded, config).unwrap();
153 assert_eq!(value, decoded);
154 assert_eq!(len, encoded.len(), "the entire buffer must be decoded");
155 decoded
156 }
157
158 #[test]
159 fn test_primitives() {
160 round_trip(true);
161 round_trip(false);
162 round_trip(42u8);
163 round_trip(42u16);
164 round_trip(42u32);
165 round_trip(42u64);
166 round_trip(-42i8);
167 round_trip(-42i16);
168 round_trip(-42i32);
169 round_trip(-42i64);
170 round_trip(1.23f32);
171 round_trip(1.23f64);
172 round_trip('a');
173 }
174
175 #[test]
176 fn test_string() {
177 round_trip(String::new());
178 round_trip(String::from("hello world"));
179 }
180
181 #[test]
182 fn test_option() {
183 round_trip(Option::<i32>::None);
184 round_trip(Some(42));
185 round_trip(Some(String::from("hello")));
186 round_trip(Some(Some(42)));
187 }
188
189 #[test]
190 fn test_vec() {
191 round_trip(Vec::<i32>::new());
192 round_trip(vec![String::from("a"), String::from("b")]);
193 round_trip(vec![vec![1, 2], vec![3, 4]]);
194 round_trip(b"abc\0def".to_vec());
195 }
196
197 #[test]
198 fn test_tuple() {
199 round_trip(());
200 round_trip((vec![1, 2], "hello".to_string(), Some(42), false, true));
201 }
202
203 #[test]
204 fn test_hashmap() {
205 let mut map = HashMap::new();
206 map.insert("key1".to_string(), 1);
207 map.insert("key2".to_string(), 2);
208 round_trip(map);
209
210 let empty: HashMap<String, i32> = HashMap::new();
211 round_trip(empty);
212 }
213
214 #[test]
215 fn test_struct() {
216 #[derive(Debug, PartialEq, Serialize, Deserialize)]
217 struct Struct {
218 a: String,
219 b: Option<i32>,
220 #[serde(flatten)]
221 flattened: Flattened,
222 }
223
224 #[derive(Debug, PartialEq, Serialize, Deserialize)]
225 struct Flattened {
226 d: i32,
227 }
228
229 round_trip(Struct {
230 a: "hello".to_string(),
231 b: None,
232 flattened: Flattened { d: 42 },
233 });
234 round_trip(Struct {
235 a: "hello".to_string(),
236 b: Some(42),
237 flattened: Flattened { d: 43 },
238 });
239 }
240
241 #[test]
242 fn test_unit_struct() {
243 #[derive(Debug, PartialEq, Serialize, Deserialize)]
244 struct UnitStruct;
245
246 round_trip(UnitStruct);
247 }
248
249 #[test]
250 fn test_newtype_struct() {
251 #[derive(Debug, PartialEq, Serialize, Deserialize)]
252 struct NewtypeStruct(i32);
253
254 round_trip(NewtypeStruct(42));
255 }
256
257 #[test]
258 fn test_tuple_struct() {
259 #[derive(Debug, PartialEq, Serialize, Deserialize)]
260 struct TupleStruct(i32, String, bool);
261
262 round_trip(TupleStruct(42, "hello".to_string(), true));
263 }
264
265 #[test]
266 fn test_enum_unit_variants() {
267 #[derive(Debug, PartialEq, Serialize, Deserialize)]
268 enum Color {
269 Red,
270 Green,
271 Blue,
272 }
273
274 round_trip(Color::Red);
275 round_trip(Color::Green);
276 round_trip(Color::Blue);
277 }
278
279 #[test]
280 fn test_enum_newtype_variants() {
281 #[derive(Debug, PartialEq, Serialize, Deserialize)]
282 enum Value {
283 #[allow(unused)]
284 #[serde(skip)]
285 Empty(()),
286 Int(i32),
287 Text(String),
288 }
289
290 round_trip(Value::Int(42));
291 round_trip(Value::Text("hello".to_string()));
292 }
293
294 #[test]
295 fn test_enum_tuple_variants() {
296 #[derive(Debug, PartialEq, Serialize, Deserialize)]
297 enum Point {
298 TwoD(i32, i32),
299 ThreeD(i32, i32, i32),
300 }
301
302 round_trip(Point::TwoD(1, 2));
303 round_trip(Point::ThreeD(1, 2, 3));
304 }
305
306 #[test]
307 fn test_enum_struct_variants() {
308 #[derive(Debug, PartialEq, Serialize, Deserialize)]
309 enum Message {
310 Request { id: u32, method: String },
311 Response { id: u32, result: Option<String> },
312 }
313
314 round_trip(Message::Request {
315 id: 1,
316 method: "get".to_string(),
317 });
318 round_trip(Message::Response {
319 id: 1,
320 result: Some("ok".to_string()),
321 });
322 round_trip(Message::Response {
323 id: 2,
324 result: None,
325 });
326 }
327}