tampon/buffer.rs
1/*
2 * @file tampon/buffer.rs
3 *
4 * @module tampon
5 *
6 * @brief Macro used to easily create a buffer from primitive, vectors and Tampon trait implementation.
7 *
8 * @details
9 * Macro used to easily create a buffer from primitive, vectors and Tampon trait implementation.
10 *
11 * @author Mathieu Grenier
12 * @copyright NickelAnge.Studio
13 *
14 * @date 2022-07-16
15 *
16 * @version
17 * 1.0 : 2022-07-16 | Mathieu Grenier | Code creation
18 *
19 * @ref
20 *
21 * @todo
22 */
23
24/// ##### Variadic macro used to create a [`buffer`](https://en.wikipedia.org/wiki/Data_buffer) and [`serialize`](https://en.wikipedia.org/wiki/Serialization) [`compatible variables`](macro.buffer.html#compatible-variabless).
25///
26/// # Description
27/// Variadic macro used to create a [`buffer`](https://en.wikipedia.org/wiki/Data_buffer) and [`serialize`](https://en.wikipedia.org/wiki/Serialization) [`bool`], [`Numeric types`](https://doc.rust-lang.org/reference/types/numeric.html) (except usize, isize), [`String`] and implementors of trait [`Tampon`](trait.Tampon.html).
28/// Also work with [`slice`] by using brackets `[]` instead of parenthesis `()`.
29///
30/// # Usage
31/// `let buffer = buffer!([0..n](v1, ..., vn):type, [0..n][s1, ..., sn]:type);`
32/// * One-to-many `(v1, ..., vn):type` where elements in `parenthesis()` are the variables to be copied into created buffer.
33/// * One-to-many `[s1, ..., sn]:type` where elements in `brackets[]` are the slices to be copied into created buffer.
34///
35/// # Return
36/// New buffer created with argument(s) serialized with the size needed to contain them all.
37///
38/// # Example(s)
39/// ```
40/// // Import macro buffer
41/// use tampon::buffer;
42///
43/// // Declare multiple variables (numerics don't need to be same type)
44/// let a:u8 = 55;
45/// let b:u8 = 255;
46/// let c:u32 = 12545566;
47/// let d:String = String::from("Example string");
48/// let e:Vec<i32> = vec![i32::MAX; 50];
49/// let f:Vec<f64> = vec![f64::MAX; 50];
50/// let g:Vec<f64> = vec![f64::MAX; 50];
51///
52/// // Create a buffer and serialize data with buffer! macro.
53/// let buffer:Vec<u8> = buffer!((a,b):u8, (c):u32, (d):String, [e]:i32, [f,g]:f64);
54///
55/// // Print result
56/// println!("Resulted buffer={:?}", buffer);
57/// ```
58///
59/// # Compatible variables(s)
60/// * [`bool`]
61/// * All [`Numeric types`](https://doc.rust-lang.org/reference/types/numeric.html) except [`usize`] and [`isize`]
62/// * [`String`]
63/// * Implementors of trait [`Tampon`](trait.Tampon.html)
64/// * [`slice`] of the above types
65///
66/// # Endianness
67/// * [`Numeric types`](https://doc.rust-lang.org/reference/types/numeric.html) bytes are written as [`little endian`](https://en.wikipedia.org/wiki/Endianness).
68#[macro_export]
69macro_rules! buffer {
70
71 // Expression without tail
72 (($expr:expr $(,$extra:expr)*):$type:ident) => {{
73 // Get size needed for variable serialization
74 let buffer_size = $crate::bytes_size!(($expr $(,$extra)*):$type);
75
76 // Create mutable buffer of needed size
77 let mut buffer:Vec<u8> = vec![0;buffer_size];
78
79 // Serialize variable into vector
80 $crate::serialize!(buffer, ($expr $(,$extra)*):$type);
81
82 // Return buffer
83 buffer
84 } as Vec<u8> };
85
86 // Expression with tail
87 (($expr:expr $(,$extra:expr)*):$type:ident, $($tail:tt)*) => {{
88 let buffer_size = $crate::bytes_size!(($expr $(,$extra)*):$type, $($tail)*);
89 let mut buffer:Vec<u8> = vec![0;buffer_size];
90 $crate::serialize!(buffer, ($expr $(,$extra)*):$type, $($tail)*);
91 buffer
92 } as Vec<u8> };
93
94 // Slice without tail
95 ([$expr:expr $(,$extra:expr)*]:$type:ident) => { {
96 let buffer_size = $crate::bytes_size!([$expr $(,$extra)*]:$type);
97 let mut buffer:Vec<u8> = vec![0;buffer_size];
98 $crate::serialize!(buffer, [$expr $(,$extra)*]:$type);
99 buffer
100 } as Vec<u8> };
101
102 // Slice with tail
103 ([$expr:expr $(,$extra:expr)*]:$type:ident, $($tail:tt)*) => {{
104 let buffer_size = $crate::bytes_size!([$expr $(,$extra)*]:$type, $($tail)*);
105 let mut buffer:Vec<u8> = vec![0;buffer_size];
106 $crate::serialize!(buffer, [$expr $(,$extra)*]:$type, $($tail)*);
107 buffer
108 } as Vec<u8> };
109}