Skip to main content

serde_wincode/
lib.rs

1//! serde compatibility for wincode, suitable for replacing bincode
2
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(not(feature = "std"), no_std)]
5
6use core::{marker::PhantomData, mem::MaybeUninit};
7
8use wincode::{
9    error::{ReadResult, WriteError, WriteResult},
10    io::{Reader, Writer},
11};
12
13#[cfg(feature = "alloc")]
14extern crate alloc;
15
16mod de;
17mod ser;
18
19pub use {de::Deserializer, ser::Serializer};
20
21/// Wrapper struct that impls [`wincode::SchemaRead`] and
22/// [`wincode::SchemaWrite`] for types that impl [`serde::Deserialize`] and
23// [`serde::Serialize`], respectively.
24#[repr(transparent)]
25pub struct SerdeCompat<T> {
26    _marker: PhantomData<T>,
27}
28
29unsafe impl<'de, C, T> wincode::SchemaRead<'de, C> for SerdeCompat<T>
30where
31    C: wincode::config::Config,
32    T: serde::Deserialize<'de>,
33{
34    type Dst = T;
35
36    fn read(
37        reader: impl Reader<'de>,
38        dst: &mut MaybeUninit<Self::Dst>,
39    ) -> ReadResult<()> {
40        let deserializer = Deserializer::<_, C>::new(reader);
41        let value = T::deserialize(deserializer)?;
42        dst.write(value);
43        Ok(())
44    }
45}
46
47unsafe impl<C, T> wincode::SchemaWrite<C> for SerdeCompat<T>
48where
49    C: wincode::config::Config,
50    T: serde::Serialize,
51{
52    type Src = T;
53
54    fn size_of(src: &Self::Src) -> WriteResult<usize> {
55        let mut serializer = ser::SizeOf::<C>::new();
56        serializer = src.serialize(serializer)?;
57        Ok(serializer.serialized_size())
58    }
59
60    fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> {
61        let serializer = Serializer::<_, C>::new(writer);
62        src.serialize(serializer).map_err(WriteError::from)
63    }
64}
65
66#[cfg(all(feature = "alloc", test))]
67mod tests {
68    use serde::{Deserialize, Serialize};
69
70    use super::SerdeCompat;
71
72    #[test]
73    fn test_flattened_roundtrip()
74    -> Result<(), alloc::boxed::Box<dyn core::error::Error>> {
75        #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
76        struct InnerMost<'a> {
77            #[serde(borrow)]
78            msg: &'a str,
79            #[serde(borrow)]
80            bytes: &'a [u8],
81        }
82        #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
83        struct InnerMore<'a> {
84            u32_value: u32,
85            #[serde(borrow)]
86            inner: InnerMost<'a>,
87        }
88        #[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
89        struct Outer<'a> {
90            #[serde(borrow)]
91            inner: InnerMore<'a>,
92            bool_value: bool,
93        }
94
95        let value = Outer {
96            inner: InnerMore {
97                u32_value: 69_420,
98                inner: InnerMost {
99                    msg: "test msg",
100                    bytes: b"test bytes",
101                },
102            },
103            bool_value: true,
104        };
105        let value_serialized_bincode = bincode::serialize(&value)?;
106        let value_serialized_wincode =
107            <SerdeCompat<Outer> as wincode::Serialize>::serialize(&value)?;
108        assert_eq!(value_serialized_bincode, value_serialized_wincode);
109        let value_deserialized =
110            <SerdeCompat<Outer> as wincode::Deserialize>::deserialize(
111                &value_serialized_wincode,
112            )?;
113        assert_eq!(value_deserialized, value);
114        Ok(())
115    }
116}