maybe_serde/
lib.rs

1#![feature(specialization)]
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5/// Maybe implement Serialize
6///
7/// This trait is impl for all types
8///
9/// If type implement `Serialize` then `maybe_serialize` return `Serialize::serialize` value with `Some`
10///
11/// Otherwise if type doesn't implement `Serialize` then `maybe_serialize` return just `None`
12pub trait MaybeSer {
13    /// true if implement `serde::Serialize`
14    const IMPL_SERIALIZE: bool;
15
16    fn maybe_serialize<S>(&self, serializer: S) -> Option<Result<S::Ok, S::Error>>
17    where
18        S: Serializer;
19}
20
21/// Maybe implement Deserialize
22///
23/// This trait is impl for all types
24///
25/// If type implement `Deserialize` then `maybe_deserialize` return `Deserialize::deserialize` value with `Some`
26///
27/// Otherwise if type doesn't implement `Deserialize` then `maybe_deserialize` return just `None`
28pub trait MaybeDe<'de>: Sized {
29    /// true if implement `serde::Deserialize`
30    const IMPL_DESERIALIZE: bool;
31
32    fn maybe_deserialize<D>(deserializer: D) -> Option<Result<Self, D::Error>>
33    where
34        D: Deserializer<'de>;
35}
36
37/// Always return `None`
38impl<T> MaybeSer for T {
39
40    /// Always return `false`
41    default const IMPL_SERIALIZE: bool = false;
42
43    default fn maybe_serialize<S>(
44        &self,
45        _serializer: S,
46    ) -> Option<Result<<S as Serializer>::Ok, <S as Serializer>::Error>>
47    where
48        S: Serializer,
49    {
50        None
51    }
52}
53
54/// Always return `None`
55impl<'de, T> MaybeDe<'de> for T {
56    /// Always return `false`
57    default const IMPL_DESERIALIZE: bool = false;
58
59    default fn maybe_deserialize<D>(
60        _deserializer: D,
61    ) -> Option<Result<Self, <D as Deserializer<'de>>::Error>>
62    where
63        D: Deserializer<'de>,
64    {
65        None
66    }
67}
68
69/// Always return `Some`
70impl<T> MaybeSer for T
71where
72    T: Serialize,
73{
74    /// Always return `true`
75    const IMPL_SERIALIZE: bool = true;
76
77    fn maybe_serialize<S>(
78        &self,
79        serializer: S,
80    ) -> Option<Result<<S as Serializer>::Ok, <S as Serializer>::Error>>
81    where
82        S: Serializer,
83    {
84        Some(self.serialize(serializer))
85    }
86}
87
88/// Always return `Some`
89impl<'de, T> MaybeDe<'de> for T
90where
91    T: Deserialize<'de>,
92{
93    /// Always return `true`
94    const IMPL_DESERIALIZE: bool = true;
95
96    fn maybe_deserialize<D>(
97        deserializer: D,
98    ) -> Option<Result<Self, <D as Deserializer<'de>>::Error>>
99    where
100        D: Deserializer<'de>,
101    {
102        Some(T::deserialize(deserializer))
103    }
104}
105
106/// Helper type for connect serde and maybe-serde
107///
108/// This type implement both `serde::{Serialize, Deserialize}` for all T
109///
110/// It's just helper type and not necessary
111///
112/// you could define your own type using MaybeSer and MaybeDe
113///
114/// ### When Serialize
115/// if T: Serialize and Option is Some then just serialize T itself (doesn't serialize as Option!)
116///
117/// and T: !Serialize or Option is None then serialize None
118///
119/// maybe `#[serde(skip_serializing_if = "T::IMPL_SERIALIZE")]` attribute could be help
120///
121/// ### When Deserialize
122/// if T: Deserialize then get Some<T>
123///
124/// and T: !Deserialize just None
125pub struct MaybeSerde<T>(pub Option<T>);
126
127impl<T> Into<Option<T>> for MaybeSerde<T> {
128    fn into(self) -> Option<T> { self.0 }
129}
130
131impl<T: MaybeSer> Serialize for MaybeSerde<T> {
132    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
133        S: Serializer {
134
135        if T::IMPL_SERIALIZE {
136            match &self.0 {
137                Some(dat) => dat.maybe_serialize(serializer).unwrap(),
138                None => serializer.serialize_none(),
139            }
140        } else {
141            serializer.serialize_none()
142        }
143    }
144}
145
146impl<'de, T: MaybeDe<'de>> Deserialize<'de> for MaybeSerde<T> {
147    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where
148        D: Deserializer<'de> {
149
150        if T::IMPL_DESERIALIZE {
151            Ok(MaybeSerde(Some(T::maybe_deserialize(deserializer).unwrap()?)))
152        } else {
153            Ok(MaybeSerde(None))
154        }
155    }
156}
157
158#[cfg(test)]
159mod tests {
160    use super::{MaybeDe, MaybeSer, MaybeSerde};
161    use serde_derive::{Deserialize, Serialize};
162    use serde_json::{de::StrRead, Deserializer, Result, Serializer, to_string, from_str};
163
164    fn ser_fn<V>(val: &V) -> Option<Result<()>>
165    where
166        V: MaybeSer,
167    {
168        let mut buf = Vec::new();
169        val.maybe_serialize(&mut Serializer::new(&mut buf))
170    }
171
172    fn de_fn<'de, V>(text: &'de str) -> Option<Result<V>>
173    where
174        V: MaybeDe<'de>,
175    {
176        V::maybe_deserialize(&mut Deserializer::new(StrRead::new(text)))
177    }
178
179    struct NoneSerde(i32);
180
181    #[derive(Serialize, Deserialize)]
182    struct SomeSerde(i32);
183
184    #[test]
185    fn serde_none() {
186        struct NoneSerde(i32);
187
188        assert!(ser_fn(&NoneSerde(123)).is_none());
189        assert!(de_fn::<NoneSerde>("123").is_none());
190    }
191
192    #[test]
193    fn serde_some() {
194
195        assert!(ser_fn(&SomeSerde(123)).is_some());
196        assert_eq!(de_fn::<SomeSerde>("123").unwrap().unwrap().0, 123);
197    }
198
199    #[test]
200    fn serde_none_maybe_serde() {
201        let maybe_serde = MaybeSerde(Some(NoneSerde(123)));
202
203        assert!(to_string(&maybe_serde).is_ok());
204        assert!(from_str::<MaybeSerde<NoneSerde>>("").unwrap().0.is_none());
205    }
206
207    #[test]
208    fn serde_some_maybe_serde() {
209        let maybe_serde = MaybeSerde(Some(SomeSerde(123)));
210
211        assert_eq!(to_string(&maybe_serde).unwrap(), "123");
212        assert_eq!(from_str::<MaybeSerde<SomeSerde>>("123").unwrap().0.unwrap().0, 123);
213    }
214}