bytevec2/
macros.rs

1/// Implements the byte serialization traits for the given structures.
2///
3/// This macro implements both the `ByteEncodable` and `ByteDecodable` traits
4/// for the given `struct` definitions. This macro does not declare the `struct`
5/// definitions, the user should either declare them separately or use the
6/// `bytevec_decl` trait.
7///
8/// This trait also allows the user to create a partial implementation of the
9/// serialization operations for a select number of the fields of the
10/// structure. If the actual definition of the `struct` has more fields than
11/// the one provided to the macro, only the listed fields in the macro invocation
12/// will be serialized and deserialized. In the deserialization process, the
13/// rest of the fields of the `struct` will be initialized using the value
14/// returned from the [`Default::default()`][1] method, so the `struct` must
15/// implement [`Default`][2].
16///
17/// # Examples
18///
19/// ```rust
20/// # #[macro_use]
21/// # extern crate bytevec2;
22/// #
23/// # use bytevec2::{ByteEncodable, ByteDecodable};
24/// #
25/// #[derive(PartialEq, Eq, Debug, Default)]
26/// struct Vertex3d {
27///     x: u32,
28///     y: u32,
29///     z: u32
30/// }
31///
32/// bytevec_impls! {
33///     impl Vertex3d {
34///         x: u32,
35///         y: u32
36///     }
37/// }
38///
39/// fn main() {
40///     let p1 = Vertex3d {x: 32, y: 436, z: 0};
41///     let bytes = p1.encode::<u32>().unwrap();
42///     let p2 = Vertex3d::decode::<u32>(&bytes).unwrap();
43///     assert_eq!(p1, p2);
44/// }
45/// ```
46/// [1]: http://doc.rust-lang.org/stable/std/default/trait.Default.html#tymethod.default
47/// [2]: http://doc.rust-lang.org/stable/std/default/trait.Default.html
48#[macro_export]
49macro_rules! bytevec_impls {
50    {$(impl $name:ident {$($field:ident : $t:ty),*})*} => {
51        $(
52            impl $crate::ByteEncodable for $name
53            {
54                fn get_size<Size>(&self) -> Option<Size>
55                    where Size: $crate::BVSize + $crate::ByteEncodable
56                {
57                    let mut size = Some(Size::from_usize(0));
58                    $(
59                        size = size.and_then(|size: Size|
60                            self.$field.get_size::<Size>().and_then(|field_size|
61                                size.checked_add(field_size).and_then(
62                                    |acc_size| acc_size.checked_add(
63                                        Size::get_size_of())
64                                )
65                            )
66                        );
67                    )*
68                    size
69                }
70
71                fn encode<Size>(&self) -> $crate::BVEncodeResult<Vec<u8>>
72                    where Size: $crate::BVSize + $crate::ByteEncodable
73                {
74                    if self.get_size::<Size>().is_some() {
75                        let mut bytes = Vec::new();
76                        $(
77                            let field_size: Option<Size> = self.$field.get_size::<Size>();
78                            bytes.extend_from_slice(&(
79                                field_size.unwrap().encode::<Size>())?);
80                        )*
81                        $(
82                            bytes.extend_from_slice(&(self.$field.encode::<Size>())?);
83                        )*
84                        Ok(bytes)
85                    } else {
86                        Err($crate::errors::ByteVecError::OverflowError)
87                    }
88                }
89            }
90
91            #[allow(dead_code, unused_assignments)]
92            impl $crate::ByteDecodable for $name {
93                fn decode<Size>(bytes: &[u8]) -> $crate::BVDecodeResult<$name>
94                    where Size: $crate::BVSize + $crate::ByteDecodable
95                {
96                    let mut index = 0;
97                    let mut sizes = ::std::collections::HashMap::new();
98                    $(
99                        if bytes[index..].len() >= Size::get_size_of().as_usize() {
100                            sizes.insert(stringify!($field),
101                                (Size::decode::<Size>(
102                                    &bytes[index..index + Size::get_size_of().as_usize()]))?);
103                            index += Size::get_size_of().as_usize();
104                        }
105                        else {
106                            return Err($crate::errors::ByteVecError::BadSizeDecodeError {
107                                expected: $crate::errors::BVExpectedSize::MoreThan(
108                                    Size::get_size_of().as_usize() + index),
109                                actual: bytes.len()
110                            });
111                        }
112                    )*
113
114                    let body_size = sizes.values().fold(0, |acc, ref size| acc + size.as_usize());
115                    if body_size == bytes[index..].len() {
116                        Ok($name {
117                            $(
118                                $field: {
119                                    let size = sizes[stringify!($field)].as_usize();
120                                    let field = (<$t as $crate::ByteDecodable>::decode::<Size>(
121                                        &bytes[index..index + size]))?;
122                                    index += size;
123                                    field
124                                },
125                            )*
126                            ..Default::default()
127                        })
128                    } else {
129                        Err($crate::errors::ByteVecError::BadSizeDecodeError {
130                            expected: $crate::errors::BVExpectedSize::EqualTo(
131                                Size::get_size_of().as_usize() * sizes.len() + body_size),
132                            actual: bytes.len()
133                        })
134                    }
135                }
136            }
137        )*
138    };
139}
140
141/// Declares the given structures and implements the byte serialization traits.
142///
143/// This macro allows the user to declare an arbitrary number of structures that
144/// automatically implement both the `ByteEncodable` and `ByteDecodable` traits,
145/// as long as all of the fields also implement both traits.
146///
147/// # Examples
148///
149/// ```rust
150/// # #[macro_use]
151/// # extern crate bytevec2;
152/// #
153/// # use bytevec2::{ByteEncodable, ByteDecodable};
154/// #
155/// bytevec_decl! {
156///     #[derive(PartialEq, Eq, Debug)]
157///     pub struct Point {
158///         x: u32,
159///         y: u32
160///     }
161/// }
162///
163/// fn main() {
164///     let p1 = Point {x: 32, y: 436};
165///     let bytes = p1.encode::<u32>().unwrap();
166///     let p2 = Point::decode::<u32>(&bytes).unwrap();
167///     assert_eq!(p1, p2);
168/// }
169/// ```
170#[macro_export]
171macro_rules! bytevec_decl {
172    {$($(#[$attr:meta])* struct $name:ident {$($field:ident : $t:ty),*})*} => {
173        $(
174            $(#[$attr])*
175            #[derive(Default)]
176            struct $name {
177                $($field: $t),*
178            }
179            bytevec_impls!(impl $name {$($field:$t),*});
180        )*
181    };
182
183    {$($(#[$attr:meta])* pub struct $name:ident {$(pub $field:ident : $t:ty),*})*} => {
184        $(
185            $(#[$attr])*
186            #[derive(Default)]
187            pub struct $name {
188                $(pub $field: $t),*
189            }
190            bytevec_impls!(impl $name {$($field:$t),*});
191        )*
192    };
193
194    {$($(#[$attr:meta])* pub struct $name:ident {$($field:ident : $t:ty),*})*} => {
195        $(
196            $(#[$attr])*
197            #[derive(Default)]
198            pub struct $name {
199                $($field: $t),*
200            }
201            bytevec_impls!(impl $name {$($field:$t),*});
202        )*
203    };
204}