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}