nimble/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(missing_docs, unstable_features)]
3//! # Nimble
4//!
5//! Async friendly, simple and fast binary encoding/decoding in Rust.
6//!
7//! ## Binary encoding scheme
8//!
9//! This crate uses a minimal binary encoding scheme. For example, consider the following `struct`:
10//!
11//! ```
12//! struct MyStruct {
13//!     a: u8,
14//!     b: u16,
15//! }
16//! ```
17//!
18//! `encode()` will serialize this into `Vec` of size `3` (which is the sum of sizes of `u8` and `u16`).
19//!
20//! Similarly, for types which can have dynamic size (`Vec`, `String`, etc.), `encode()` prepends the size of encoded value
21//! as `u64`.
22//!
23//! ## Usage
24//!
25//! Add `nimble` in your `Cargo.toml`'s `dependencies` section:
26//!
27//! ```toml
28//! [dependencies]
29//! nimble = { version = "0.2", features = ["derive"] }
30//! ```
31//!
32//! Or, if you are in an environment based on `tokio`, use:
33//!
34//! ```toml
35//! [dependencies]
36//! nimble = { version = "0.2", default-features = false, features = ["derive", "tokio"] }
37//! ```
38//!
39//! For encoding and decoding, any type must implement two traits provided by this crate, i.e., `Encode` and `Decode`. For
40//! convenience, `nimble` provides `derive` macros (only when `"derive"` feature is enabled) to implement these traits.
41//!
42//! ```rust,ignore
43//! use nimble::{Encode, Decode};
44//!
45//! #[derive(Encode, Decode)]
46//! struct MyStruct {
47//!     a: u8,
48//!     b: u16,
49//! }
50//! ```
51//!
52//! Now you can use `encode()` and `decode()` functions to encode and decode values of `MyStruct`. In addition to this, you
53//! can also use `MyStruct::encode_to()` function to encode values directly to a type implementing `AsyncWrite` and
54//! `MyStruct::decode_from()` function to decode values directly from a type implementing `AsyncRead`.
55//!
56//! > Note: Most of the functions exposed by this crate are `async` functions and returns `Future` values. So, you'll need
57//! an executor to drive the `Future` returned from these functions. `async-std` and `tokio` are two popular options.
58//!
59//! ### Features
60//!
61//! - `futures`: Select this feature when you want to implement `Encode` and `Decode` using `futures`'
62//!   `AsyncRead`/`AsyncWrite` traits.
63//!   - **Enabled** by default.
64//! - `tokio`: Select this feature when you want to implement `Encode` and `Decode` using `tokio`'s `AsyncRead`/`AsyncWrite`
65//!   traits.
66//!   - **Disabled** by default.
67//! - `derive`: Enables derive macros for implementing `Encode` and `Decode` traits.
68//!   - **Disabled** by default.
69//!
70//! > Note: Features `futures` and `tokio` are mutually exclusive, i.e., only one of them can be enabled at a time.
71//! > Compilation will fail if either both of them are enabled or none of them are enabled.
72#[cfg(all(feature = "futures", feature = "tokio"))]
73compile_error!("Features `futures` and `tokio` are mutually exclusive");
74
75#[cfg(not(any(feature = "futures", feature = "tokio")))]
76compile_error!("Either feature `futures` or `tokio` must be enabled for this crate");
77
78mod config;
79mod decode;
80mod encode;
81mod error;
82
83pub mod io;
84
85#[cfg(feature = "derive")]
86pub use nimble_derive::{Decode, Encode};
87
88/// Utility macro for implementing [`Encode`](trait.Encode.html) and [`Decode`](trait.Decode.html) traits.
89pub use async_trait::async_trait;
90
91pub use self::{
92    config::{Config, Endianness},
93    decode::Decode,
94    encode::Encode,
95    error::{Error, Result},
96};
97
98use self::io::{Read, Write};
99
100const DEFAULT_CONFIG: Config = Config::new_default();
101
102/// Returns default `Config`
103pub fn config<'a>() -> &'a Config {
104    &DEFAULT_CONFIG
105}
106
107/// Encodes a value in a `Vec` using default configuration
108#[inline]
109pub async fn encode<E: Encode + ?Sized>(value: &E) -> Vec<u8> {
110    DEFAULT_CONFIG.encode(value).await
111}
112
113/// Writes encoded byte array to writer and returns the number of bytes written
114#[inline]
115pub async fn encode_to<E: Encode + ?Sized, W: Write + Unpin + Send>(
116    value: &E,
117    writer: W,
118) -> Result<usize> {
119    DEFAULT_CONFIG.encode_to(value, writer).await
120}
121
122/// Decodes a value from bytes using default configuration
123#[inline]
124pub async fn decode<D: Decode, T: AsRef<[u8]>>(bytes: T) -> Result<D> {
125    DEFAULT_CONFIG.decode(bytes).await
126}
127
128/// Decodes values from reader
129#[inline]
130pub async fn decode_from<D: Decode, R: Read + Unpin + Send>(reader: R) -> Result<D> {
131    DEFAULT_CONFIG.decode_from(reader).await
132}
133
134#[cfg(test)]
135#[cfg(not(feature = "tokio"))]
136mod tests {
137    use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
138    use std::{
139        collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
140        ffi::CString,
141    };
142
143    use futures_executor as executor;
144    use rand::random;
145
146    use crate::{decode, encode, Encode};
147
148    macro_rules! primitive_test {
149        ($type: ty, $name: ident) => {
150            #[test]
151            fn $name() {
152                executor::block_on(async {
153                    let original = random::<$type>();
154                    let encoded = encode(&original).await;
155                    assert_eq!(original.size(), encoded.len());
156                    let decoded: $type = decode(&encoded).await.unwrap();
157                    assert_eq!(original, decoded, "Invalid encoding/decoding");
158                });
159            }
160        };
161    }
162
163    primitive_test!(u8, u8_test);
164    primitive_test!(u16, u16_test);
165    primitive_test!(u32, u32_test);
166    primitive_test!(u64, u64_test);
167    primitive_test!(u128, u128_test);
168
169    primitive_test!(i8, i8_test);
170    primitive_test!(i16, i16_test);
171    primitive_test!(i32, i32_test);
172    primitive_test!(i64, i64_test);
173    primitive_test!(i128, i128_test);
174
175    primitive_test!(usize, usize_test);
176    primitive_test!(isize, isize_test);
177    primitive_test!(bool, bool_test);
178    primitive_test!(char, char_test);
179
180    primitive_test!(f32, f32_test);
181    primitive_test!(f64, f64_test);
182
183    primitive_test!(NonZeroU8, non_zero_u8_test);
184    primitive_test!(NonZeroU16, non_zero_u16_test);
185    primitive_test!(NonZeroU32, non_zero_u32_test);
186    primitive_test!(NonZeroU64, non_zero_u64_test);
187    primitive_test!(NonZeroU128, non_zero_u128_test);
188    primitive_test!(NonZeroUsize, non_zero_usize_test);
189
190    primitive_test!([u8; 32], u8_arr_test);
191    primitive_test!([u16; 32], u16_arr_test);
192    primitive_test!([u32; 32], u32_arr_test);
193    primitive_test!([u64; 32], u64_arr_test);
194    primitive_test!([u128; 32], u128_arr_test);
195
196    primitive_test!([i8; 32], i8_arr_test);
197    primitive_test!([i16; 32], i16_arr_test);
198    primitive_test!([i32; 32], i32_arr_test);
199    primitive_test!([i64; 32], i64_arr_test);
200    primitive_test!([i128; 32], i128_arr_test);
201
202    primitive_test!([usize; 32], usize_arr_test);
203    primitive_test!([isize; 32], isize_arr_test);
204    primitive_test!([bool; 32], bool_arr_test);
205    primitive_test!([char; 32], char_arr_test);
206
207    primitive_test!([f32; 32], f32_arr_test);
208    primitive_test!([f64; 32], f64_arr_test);
209
210    #[test]
211    fn option_none_test() {
212        executor::block_on(async {
213            let original: Option<u8> = None;
214            let encoded = encode(&original).await;
215            assert_eq!(original.size(), encoded.len());
216            let decoded: Option<u8> = decode(&encoded).await.unwrap();
217            assert_eq!(original, decoded, "Invalid encoding/decoding");
218        });
219    }
220
221    #[test]
222    fn option_some_test() {
223        executor::block_on(async {
224            let original: Option<u8> = Some(random());
225            let encoded = encode(&original).await;
226            assert_eq!(original.size(), encoded.len());
227            let decoded: Option<u8> = decode(&encoded).await.unwrap();
228            assert_eq!(original, decoded, "Invalid encoding/decoding");
229        });
230    }
231
232    #[test]
233    fn result_ok_test() {
234        executor::block_on(async {
235            let original: Result<u8, u8> = Ok(random());
236            let encoded = encode(&original).await;
237            assert_eq!(original.size(), encoded.len());
238            let decoded: Result<u8, u8> = decode(&encoded).await.unwrap();
239            assert_eq!(original, decoded, "Invalid encoding/decoding");
240        });
241    }
242
243    #[test]
244    fn result_err_test() {
245        executor::block_on(async {
246            let original: Result<u8, u8> = Err(random());
247            let encoded = encode(&original).await;
248            assert_eq!(original.size(), encoded.len());
249            let decoded: Result<u8, u8> = decode(&encoded).await.unwrap();
250            assert_eq!(original, decoded, "Invalid encoding/decoding");
251        });
252    }
253
254    #[test]
255    fn fixed_arr_test() {
256        executor::block_on(async {
257            let original = [1i32, 2i32, 3i32];
258            let encoded = encode(&original).await;
259            assert_eq!(original.size(), encoded.len());
260            let decoded: [i32; 3] = decode(&encoded).await.unwrap();
261            assert_eq!(original, decoded, "Invalid encoding/decoding");
262        });
263    }
264
265    #[test]
266    fn vec_test() {
267        executor::block_on(async {
268            let original = vec![1, 2, 3];
269            let encoded = encode(&original).await;
270            assert_eq!(original.size(), encoded.len());
271            let decoded: Vec<i32> = decode(&encoded).await.unwrap();
272            assert_eq!(original, decoded, "Invalid encoding/decoding");
273        });
274    }
275
276    #[test]
277    fn slice_test() {
278        executor::block_on(async {
279            let original = [1i32, 2i32, 3i32];
280            let encoded = encode(&original[..]).await;
281            assert_eq!(original[..].size(), encoded.len());
282            let decoded: Vec<i32> = decode(&encoded).await.unwrap();
283            assert_eq!(original.to_vec(), decoded, "Invalid encoding/decoding");
284        });
285    }
286
287    #[test]
288    fn string_test() {
289        executor::block_on(async {
290            let original = "hello";
291            let encoded = encode(original).await;
292            assert_eq!(original.size(), encoded.len());
293            let decoded: String = decode(&encoded).await.unwrap();
294            assert_eq!(original.to_string(), decoded, "Invalid encoding/decoding");
295        })
296    }
297
298    #[test]
299    fn c_string_test() {
300        executor::block_on(async {
301            let original = CString::new("hello").unwrap();
302            let encoded = encode(&original).await;
303            assert_eq!(original.size(), encoded.len());
304            let decoded: CString = decode(&encoded).await.unwrap();
305            assert_eq!(original, decoded, "Invalid encoding/decoding");
306        })
307    }
308
309    #[test]
310    fn vec_string_test() {
311        executor::block_on(async {
312            let original = vec!["hello".to_string(), "world".to_string()];
313            let encoded = encode(&original).await;
314            assert_eq!(original.size(), encoded.len());
315            let decoded: Vec<String> = decode(&encoded).await.unwrap();
316            assert_eq!(original, decoded, "Invalid encoding/decoding");
317        })
318    }
319
320    #[test]
321    fn box_test() {
322        executor::block_on(async {
323            let original = Box::new("10".to_string());
324            let encoded = encode(&original).await;
325            assert_eq!(original.size(), encoded.len());
326            let decoded: Box<String> = decode(&encoded).await.unwrap();
327            assert_eq!(original, decoded, "Invalid encoding/decoding");
328        });
329    }
330
331    #[test]
332    fn tuple_test() {
333        executor::block_on(async {
334            let original = ("hello".to_string(), 25u8, 100i32);
335            let encoded = encode(&original).await;
336            assert_eq!(original.size(), encoded.len());
337            let decoded: (String, u8, i32) = decode(&encoded).await.unwrap();
338            assert_eq!(original, decoded, "Invalid encoding/decoding");
339        });
340    }
341
342    #[test]
343    fn vec_deque_test() {
344        executor::block_on(async {
345            let mut original = VecDeque::with_capacity(3);
346            original.push_back(1);
347            original.push_back(2);
348            original.push_back(3);
349            let encoded = encode(&original).await;
350            assert_eq!(original.size(), encoded.len());
351            let decoded: VecDeque<i32> = decode(&encoded).await.unwrap();
352            assert_eq!(original, decoded, "Invalid encoding/decoding");
353        });
354    }
355
356    #[test]
357    fn linked_list_test() {
358        executor::block_on(async {
359            let mut original = LinkedList::new();
360            original.push_back(1);
361            original.push_back(2);
362            original.push_back(3);
363            let encoded = encode(&original).await;
364            assert_eq!(original.size(), encoded.len());
365            let decoded: LinkedList<i32> = decode(&encoded).await.unwrap();
366            assert_eq!(original, decoded, "Invalid encoding/decoding");
367        });
368    }
369
370    #[test]
371    fn hash_set_test() {
372        executor::block_on(async {
373            let mut original = HashSet::with_capacity(3);
374            original.insert(1);
375            original.insert(2);
376            original.insert(3);
377            let encoded = encode(&original).await;
378            assert_eq!(original.size(), encoded.len());
379            let decoded: HashSet<i32> = decode(&encoded).await.unwrap();
380            assert_eq!(original, decoded, "Invalid encoding/decoding");
381        });
382    }
383
384    #[test]
385    fn btree_set_test() {
386        executor::block_on(async {
387            let mut original = BTreeSet::new();
388            original.insert(3);
389            original.insert(1);
390            original.insert(2);
391            let encoded = encode(&original).await;
392            assert_eq!(original.size(), encoded.len());
393            let decoded: BTreeSet<i32> = decode(&encoded).await.unwrap();
394            assert_eq!(original, decoded, "Invalid encoding/decoding");
395        });
396    }
397
398    #[test]
399    fn binary_heap_test() {
400        executor::block_on(async {
401            let mut original: BinaryHeap<i32> = BinaryHeap::new();
402            original.push(3);
403            original.push(1);
404            original.push(2);
405            let encoded = encode(&original).await;
406            assert_eq!(original.size(), encoded.len());
407            let decoded: BinaryHeap<i32> = decode(&encoded).await.unwrap();
408            let new_encoded = encode(&decoded).await;
409            assert_eq!(encoded, new_encoded, "Invalid encoding/decoding");
410        });
411    }
412
413    #[test]
414    fn hash_map_test() {
415        executor::block_on(async {
416            let mut original = HashMap::with_capacity(3);
417            original.insert(1, "Hello".to_owned());
418            original.insert(2, "World".to_owned());
419            original.insert(3, "!".to_owned());
420            let encoded = encode(&original).await;
421            assert_eq!(original.size(), encoded.len());
422            let decoded: HashMap<i32, String> = decode(&encoded).await.unwrap();
423            assert_eq!(original, decoded, "Invalid encoding/decoding");
424        });
425    }
426
427    #[test]
428    fn btree_map_test() {
429        executor::block_on(async {
430            let mut original = BTreeMap::new();
431            original.insert(1, "Hello".to_owned());
432            original.insert(2, "World".to_owned());
433            original.insert(3, "!".to_owned());
434            let encoded = encode(&original).await;
435            assert_eq!(original.size(), encoded.len());
436            let decoded: BTreeMap<i32, String> = decode(&encoded).await.unwrap();
437            assert_eq!(original, decoded, "Invalid encoding/decoding");
438        });
439    }
440}