rust_fr/
lib.rs

1//! ### rust-fr
2//! A simple, non-self-describing data-interchange format. It exposes two modules, `serializer`
3//! and `deserializer`, for serializing and deserializing data which contain [`to_bytes`](serializer::to_bytes),
4//! [`from_bytes`](deserializer::from_bytes) functions which do exactly what their names suggest.
5//! - The data to be encoded & decoded must implement the `serde::Serialize` and `serde::Deserialize` traits.
6//!
7//! ### Example
8//! ```rust
9//! use rust_fr::{deserializer, serializer};
10//!
11//! #[derive(Debug, serde::Serialize, serde::Deserialize, PartialEq)]
12//! struct Human {
13//!    name: String,
14//!    age: u8,
15//! }
16//!
17//! let human = Human {
18//!    name: "Ayush".to_string(),
19//!    age: 19,
20//! };
21//!
22//! // serialize the data to bytes (Vec<u8>)
23//! let human_bytes = serializer::to_bytes(&human).unwrap();
24//!
25//! // deserialize the data from serialized bytes.
26//! let deserialized_human = deserializer::from_bytes::<Human>(&human_bytes).unwrap();
27//!
28//! assert_eq!(human, deserialized_human);
29//! ```
30
31pub mod deserializer;
32pub mod error;
33pub mod serializer;
34
35#[cfg(test)]
36mod tests {
37    use crate::{deserializer, serializer};
38    use serde::{Deserialize, Serialize};
39    use std::collections::HashMap;
40
41    #[derive(Debug, Serialize, Deserialize, PartialEq)]
42    struct Primitives {
43        a: u8,
44        b: u16,
45        c: u32,
46        d: u64,
47        e: i8,
48        f: i16,
49        g: i32,
50        h: i64,
51        i: f32,
52        j: f64,
53        k: bool,
54        l: char,
55        m: String,
56    }
57
58    #[test]
59    fn primitives() {
60        let primitives = Primitives {
61            a: 1,
62            b: 2,
63            c: 3,
64            d: 4,
65            e: -1,
66            f: -2,
67            g: -3,
68            h: -4,
69            i: 1.0,
70            j: 2.0,
71            k: true,
72            l: 'a',
73            m: "hello".to_string(),
74        };
75
76        // Serialize
77        let bytes = serializer::to_bytes(&primitives).unwrap();
78
79        // Deserialize
80        let deserialized_primitives = deserializer::from_bytes::<Primitives>(&bytes).unwrap();
81        assert_eq!(primitives, deserialized_primitives);
82    }
83
84    #[derive(Debug, Serialize, Deserialize, PartialEq)]
85    struct CompundTypes {
86        a: Vec<u8>,
87        b: HashMap<String, u8>,
88        c: Option<u8>,
89        d: Option<String>,
90        e: Primitives,
91        f: Vec<AnEnum>,
92    }
93
94    #[derive(Debug, Serialize, Deserialize, PartialEq)]
95    enum AnEnum {
96        A(u8),
97        B { a: u8, b: u16 },
98        C,
99    }
100
101    #[test]
102    fn compound_types() {
103        let compound_types = CompundTypes {
104            a: vec![1, 2, 3],
105            b: [("a".to_string(), 1), ("b".to_string(), 2)]
106                .iter()
107                .cloned()
108                .collect(),
109            c: Some(1),
110            d: None,
111            e: Primitives {
112                a: 1,
113                b: 2,
114                c: 3,
115                d: 4,
116                e: -1,
117                f: -2,
118                g: -3,
119                h: -4,
120                i: 1.0,
121                j: 2.0,
122                k: true,
123                l: 'a',
124                m: "hello".to_string(),
125            },
126            f: vec![AnEnum::A(1), AnEnum::B { a: 1, b: 2 }, AnEnum::C],
127        };
128
129        // Serialize
130        let bytes = serializer::to_bytes(&compound_types).unwrap();
131
132        // Deserialize
133        let deserialized_compound_types = deserializer::from_bytes::<CompundTypes>(&bytes).unwrap();
134        assert_eq!(compound_types, deserialized_compound_types);
135    }
136
137    #[derive(Debug, Serialize, Deserialize, PartialEq)]
138    struct Random {
139        a: u8,
140        b: u16,
141        c: u32,
142        d: u64,
143        e: i8,
144        f: i16,
145        g: i32,
146        h: i64,
147        i: f32,
148        j: f64,
149        k: bool,
150        l: char,
151        m: String,
152        n: Vec<u8>,
153        o: HashMap<String, u8>,
154        p: Option<u8>,
155        q: Option<String>,
156        r: [u8; 3],
157    }
158
159    #[test]
160    fn random() {
161        let random = Random {
162            a: 1,
163            b: 2,
164            c: 3,
165            d: 4,
166            e: -1,
167            f: -2,
168            g: -3,
169            h: -4,
170            i: 1.0,
171            j: 2.0,
172            k: true,
173            l: 'a',
174            m: "hello".to_string(),
175            n: vec![1, 2, 3],
176            o: [("a".to_string(), 1), ("b".to_string(), 2)]
177                .iter()
178                .cloned()
179                .collect(),
180            p: Some(1),
181            q: None,
182            r: [1, 2, 3],
183        };
184
185        // Serialize
186        let bytes = serializer::to_bytes(&random).unwrap();
187
188        // Deserialize
189        let deserialized_random = deserializer::from_bytes::<Random>(&bytes).unwrap();
190        assert_eq!(random, deserialized_random);
191    }
192
193    #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
194    struct Human {
195        name: String,
196        age: u8,
197    }
198
199    #[test]
200    fn readme_example() {
201        let human = Human {
202            name: "Ayush".to_string(),
203            age: 19,
204        };
205
206        // serialize the data to bytes (Vec<u8>)
207        let human_bytes = serializer::to_bytes(&human).unwrap();
208
209        // deserialize the data from serialized bytes.
210        let deserialized_human = deserializer::from_bytes::<Human>(&human_bytes).unwrap();
211
212        assert_eq!(human, deserialized_human);
213    }
214
215    #[derive(Debug, Serialize, Deserialize, PartialEq)]
216    struct PlaygroundData {
217        never: HashMap<String, Vec<u8>>,
218        gonna: Vec<u8>,
219        give: Option<i32>,
220        you: bool,
221        up: Option<Primitives>,
222    }
223
224    #[test]
225    #[ignore = "playground test; use cargo test -- --nocapture --ignored"]
226    fn length_test_large_data() {
227        let data = PlaygroundData {
228            never: (0..1000)
229                .map(|i| (i.to_string(), vec![i as u8; 100]))
230                .collect(),
231            gonna: (0..1000).map(|i| i as u8).collect(),
232            give: Some(1),
233            you: true,
234            up: Some(Primitives {
235                a: 1,
236                b: 2,
237                c: 3,
238                d: 4,
239                e: -1,
240                f: -2,
241                g: -3,
242                h: -4,
243                i: 1.0,
244                j: 2.0,
245                k: true,
246                l: 'a',
247                m: "hello".to_string(),
248            }),
249        };
250
251        let rust_fr_bytes = serializer::to_bytes(&data).unwrap();
252        let serde_json_bytes = serde_json::to_vec(&data).unwrap();
253        let rmp_serde_bytes = rmp_serde::to_vec(&data).unwrap();
254        let mut cir_serde_bytes = Vec::new();
255        ciborium::ser::into_writer(&data, &mut cir_serde_bytes).unwrap();
256
257        println!("---- Large Data ----");
258        println!("rust_fr:\t{} bytes", rust_fr_bytes.len());
259        println!("serde_json:\t{} bytes", serde_json_bytes.len());
260        println!("rmp_serde:\t{} bytes", rmp_serde_bytes.len());
261        println!("ciborium:\t{} bytes", cir_serde_bytes.len());
262    }
263
264    #[test]
265    #[ignore = "playground test; use cargo test -- --nocapture --ignored"]
266    fn length_test_small_data() {
267        let data = PlaygroundData {
268            never: (0..10)
269                .map(|i| (i.to_string(), vec![i as u8; 10]))
270                .collect(),
271            gonna: (0..10).map(|i| i as u8).collect(),
272            give: Some(1),
273            you: false,
274            up: None,
275        };
276
277        let rust_fr_bytes = serializer::to_bytes(&data).unwrap();
278        let serde_json_bytes = serde_json::to_vec(&data).unwrap();
279        let rmp_serde_bytes = rmp_serde::to_vec(&data).unwrap();
280        let mut cir_serde_bytes = Vec::new();
281        ciborium::ser::into_writer(&data, &mut cir_serde_bytes).unwrap();
282
283        println!("---- Small Data ----");
284        println!("rust_fr:\t{} bytes", rust_fr_bytes.len());
285        println!("serde_json:\t{} bytes", serde_json_bytes.len());
286        println!("rmp_serde:\t{} bytes", rmp_serde_bytes.len());
287        println!("ciborium:\t{} bytes", cir_serde_bytes.len());
288    }
289
290    #[test]
291    #[ignore = "playground test; use cargo test -- --nocapture --ignored"]
292    fn length_test_medium_data() {
293        let data = PlaygroundData {
294            never: (0..100)
295                .map(|i| (i.to_string(), vec![i as u8; 100]))
296                .collect(),
297            gonna: (0..100).map(|i| i as u8).collect(),
298            give: Some(1),
299            you: true,
300            up: Some(Primitives {
301                a: 1,
302                b: 2,
303                c: 3,
304                d: 4,
305                e: -1,
306                f: -2,
307                g: -3,
308                h: -4,
309                i: 1.0,
310                j: 2.0,
311                k: true,
312                l: 'a',
313                m: "hello".to_string(),
314            }),
315        };
316
317        let rust_fr_bytes = serializer::to_bytes(&data).unwrap();
318        let serde_json_bytes = serde_json::to_vec(&data).unwrap();
319        let rmp_serde_bytes = rmp_serde::to_vec(&data).unwrap();
320        let mut cir_serde_bytes = Vec::new();
321        ciborium::ser::into_writer(&data, &mut cir_serde_bytes).unwrap();
322
323        println!("---- Medium Data ----");
324        println!("rust_fr:\t{} bytes", rust_fr_bytes.len());
325        println!("serde_json:\t{} bytes", serde_json_bytes.len());
326        println!("rmp_serde:\t{} bytes", rmp_serde_bytes.len());
327        println!("ciborium:\t{} bytes", cir_serde_bytes.len());
328    }
329}