actix_storage/
format.rs

1#![allow(unused_variables, unused_imports)]
2use serde::{de::DeserializeOwned, Serialize};
3
4use crate::error::{Result, StorageError};
5
6/// An enum representing the format used for serde interactions
7///
8/// It is default to None if no format is specified and none of the serde
9/// extension features are activated which will cause run time error if
10/// used.
11///
12/// requires "with-serde" feature
13#[derive(Debug, Clone, Copy, Eq, PartialEq)]
14pub enum Format {
15    #[cfg(feature = "serde-json")]
16    Json,
17    #[cfg(feature = "serde-cbor")]
18    Cbor,
19    #[cfg(feature = "serde-ron")]
20    Ron,
21    #[cfg(feature = "serde-yaml")]
22    Yaml,
23    #[cfg(feature = "serde-bincode")]
24    Bincode,
25    #[cfg(feature = "serde-xml")]
26    Xml,
27    #[cfg(not(any(
28        feature = "serde-json",
29        feature = "serde-cbor",
30        feature = "serde-ron",
31        feature = "serde-yaml",
32        feature = "serde-bincode",
33        feature = "serde-xml"
34    )))]
35    None,
36}
37
38impl Default for Format {
39    #[allow(unreachable_code)]
40    fn default() -> Self {
41        #[cfg(feature = "serde-json")]
42        return Format::Json;
43        #[cfg(feature = "serde-cbor")]
44        return Format::Cbor;
45        #[cfg(feature = "serde-ron")]
46        return Format::Ron;
47        #[cfg(feature = "serde-yaml")]
48        return Format::Yaml;
49        #[cfg(feature = "serde-bincode")]
50        return Format::Bincode;
51        #[cfg(feature = "serde-xml")]
52        return Format::Xml;
53        #[cfg(not(any(
54            feature = "serde-json",
55            feature = "serde-cbor",
56            feature = "serde-ron",
57            feature = "serde-yaml",
58            feature = "serde-bincode",
59            feature = "serde-xml"
60        )))]
61        Format::None
62    }
63}
64
65/// Serializes a generic value based on the format specified
66///
67/// ## Errors
68/// It will result in error if serialization fails or if there is no serde
69/// extension feature is activated.
70pub fn serialize<T>(value: &T, format: &Format) -> Result<Vec<u8>>
71where
72    T: Serialize,
73{
74    match format {
75        #[cfg(feature = "serde-json")]
76        Format::Json => serde_json::to_vec(value).map_err(|_| StorageError::SerializationError),
77        #[cfg(feature = "serde-cbor")]
78        Format::Cbor => serde_cbor::to_vec(value).map_err(|_| StorageError::SerializationError),
79        #[cfg(feature = "serde-ron")]
80        Format::Ron => {
81            let mut writer = Vec::new();
82            ron::ser::to_writer(&mut writer, value)
83                .map_err(|_| StorageError::SerializationError)?;
84            Ok(writer)
85        }
86        #[cfg(feature = "serde-yaml")]
87        Format::Yaml => serde_yaml::to_vec(value).map_err(|_| StorageError::SerializationError),
88        #[cfg(feature = "serde-bincode")]
89        Format::Bincode => bincode::serialize(value).map_err(|_| StorageError::SerializationError),
90        #[cfg(feature = "serde-xml")]
91        Format::Xml => {
92            let mut writer = Vec::new();
93            quick_xml::se::to_writer(&mut writer, value)
94                .map_err(|_| StorageError::SerializationError)?;
95            Ok(writer)
96        }
97        #[cfg(not(any(
98            feature = "serde-json",
99            feature = "serde-cbor",
100            feature = "serde-ron",
101            feature = "serde-yaml",
102            feature = "serde-bincode",
103            feature = "serde-xml"
104        )))]
105        Format::None => {
106            panic!("At least one of the serde extension features should be active to use serialize")
107        }
108    }
109}
110
111/// Deserializes a generic value based on the format specified
112///
113/// ## Errors
114/// It will result in error if deserialization fails or if there is no serde
115/// extension feature is activated.
116pub fn deserialize<T>(slice: &[u8], format: &Format) -> Result<T>
117where
118    T: DeserializeOwned,
119{
120    match format {
121        #[cfg(feature = "serde-json")]
122        Format::Json => serde_json::from_slice(slice).map_err(|_| StorageError::SerializationError),
123        #[cfg(feature = "serde-cbor")]
124        Format::Cbor => serde_cbor::from_slice(slice).map_err(|_| StorageError::SerializationError),
125        #[cfg(feature = "serde-ron")]
126        Format::Ron => ron::de::from_bytes(slice).map_err(|_| StorageError::SerializationError),
127        #[cfg(feature = "serde-yaml")]
128        Format::Yaml => serde_yaml::from_slice(slice).map_err(|_| StorageError::SerializationError),
129        #[cfg(feature = "serde-bincode")]
130        Format::Bincode => {
131            bincode::deserialize(slice).map_err(|_| StorageError::SerializationError)
132        }
133        #[cfg(feature = "serde-xml")]
134        Format::Xml => {
135            quick_xml::de::from_reader(slice).map_err(|_| StorageError::SerializationError)
136        }
137        #[cfg(not(any(
138            feature = "serde-json",
139            feature = "serde-cbor",
140            feature = "serde-ron",
141            feature = "serde-yaml",
142            feature = "serde-bincode",
143            feature = "serde-xml"
144        )))]
145        Format::None => panic!(
146            "At least one of the serde extension features should be active to use deserialzie"
147        ),
148    }
149}
150
151#[cfg(test)]
152mod test {
153    use super::*;
154    use serde::{Deserialize, Serialize};
155
156    #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
157    struct Human {
158        name: String,
159        height: u32,
160        says_hello: bool,
161    }
162
163    fn get_mamad() -> Human {
164        Human {
165            name: "Mamad".to_string(),
166            height: 160,
167            says_hello: false,
168        }
169    }
170
171    #[cfg(not(any(
172        feature = "serde-json",
173        feature = "serde-cbor",
174        feature = "serde-ron",
175        feature = "serde-yaml",
176        feature = "serde-bincode",
177        feature = "serde-xml"
178    )))]
179    mod noext_test {
180        use super::*;
181
182        #[test]
183        fn test_features() {
184            let format = Format::default();
185            assert!(format, Format::None);
186        }
187
188        #[test]
189        #[should_panic(
190            expected = "At least one of the serde extension features should be active to use deserialzie"
191        )]
192        fn test_deser_panic() {
193            let format = Format::default();
194            let _: Result<String> = deserialize("panic".as_bytes(), &format);
195        }
196
197        #[test]
198        #[should_panic(
199            expected = "At least one of the serde extension features should be active to use serialize"
200        )]
201        fn test_ser_panic() {
202            let format = Format::default();
203            let code = "panic".as_bytes().to_vec();
204            let _: Result<Vec<u8>> = serialize(&code, &format);
205        }
206    }
207
208    #[cfg(any(
209        feature = "serde-json",
210        feature = "serde-cbor",
211        feature = "serde-ron",
212        feature = "serde-yaml",
213        feature = "serde-bincode",
214        feature = "serde-xml"
215    ))]
216    #[test]
217    fn test_serde() {
218        let format = Format::default();
219        let mamad = get_mamad();
220        let s = serialize(&mamad, &format).unwrap();
221        let demamad: Human = deserialize(&s, &format).unwrap();
222
223        assert_eq!(mamad, demamad)
224    }
225
226    #[cfg(any(
227        feature = "serde-json",
228        feature = "serde-cbor",
229        feature = "serde-ron",
230        feature = "serde-yaml",
231        feature = "serde-bincode",
232        feature = "serde-xml"
233    ))]
234    #[test]
235    fn test_wrong_serde() {
236        let format = Format::default();
237        let demamad: Result<Human> = deserialize(b"Some random bytes", &format);
238
239        assert!(demamad.is_err())
240    }
241
242    #[cfg(any(feature = "serde-json"))]
243    #[test]
244    fn test_json() {
245        let format = Format::Json;
246        let mamad = get_mamad();
247        let s = serialize(&mamad, &format).unwrap();
248        assert_eq!(s, br#"{"name":"Mamad","height":160,"says_hello":false}"#);
249        let demamad: Human = deserialize(&s, &format).unwrap();
250        assert_eq!(mamad, demamad)
251    }
252
253    #[cfg(any(feature = "serde-cbor"))]
254    #[test]
255    fn test_cbor() {
256        let format = Format::Cbor;
257        let mamad = get_mamad();
258        let s = serialize(&mamad, &format).unwrap();
259        assert_eq!(
260            s,
261            [
262                163, 100, 110, 97, 109, 101, 101, 77, 97, 109, 97, 100, 102, 104, 101, 105, 103,
263                104, 116, 24, 160, 106, 115, 97, 121, 115, 95, 104, 101, 108, 108, 111, 244
264            ]
265        );
266        let demamad: Human = deserialize(&s, &format).unwrap();
267        assert_eq!(mamad, demamad)
268    }
269
270    #[cfg(any(feature = "serde-ron"))]
271    #[test]
272    fn test_ron() {
273        let format = Format::Ron;
274        let mamad = get_mamad();
275        let s = serialize(&mamad, &format).unwrap();
276        assert_eq!(s, br#"(name:"Mamad",height:160,says_hello:false)"#);
277        let demamad: Human = deserialize(&s, &format).unwrap();
278        assert_eq!(mamad, demamad)
279    }
280
281    #[cfg(any(feature = "serde-yaml"))]
282    #[test]
283    fn test_yaml() {
284        let format = Format::Yaml;
285        let mamad = get_mamad();
286        let s = serialize(&mamad, &format).unwrap();
287        assert_eq!(
288            s,
289            "---\nname: Mamad\nheight: 160\nsays_hello: false\n".as_bytes()
290        );
291        let demamad: Human = deserialize(&s, &format).unwrap();
292        assert_eq!(mamad, demamad)
293    }
294
295    #[cfg(any(feature = "serde-bincode"))]
296    #[test]
297    fn test_bincode() {
298        let format = Format::Bincode;
299        let mamad = get_mamad();
300        let s = serialize(&mamad, &format).unwrap();
301        assert_eq!(
302            s,
303            [5, 0, 0, 0, 0, 0, 0, 0, 77, 97, 109, 97, 100, 160, 0, 0, 0, 0]
304        );
305        let demamad: Human = deserialize(&s, &format).unwrap();
306        assert_eq!(mamad, demamad)
307    }
308
309    #[cfg(any(feature = "serde-xml"))]
310    #[test]
311    fn test_xml() {
312        let format = Format::Xml;
313        let mamad = get_mamad();
314        let s = serialize(&mamad, &format).unwrap();
315        assert_eq!(
316            s,
317            br#"<Human name="Mamad" height="160" says_hello="false"/>"#
318        );
319        let demamad: Human = deserialize(&s, &format).unwrap();
320        assert_eq!(mamad, demamad)
321    }
322}