#[macro_export]
macro_rules! bytevec_impls {
{$(impl $name:ident {$($field:ident : $t:ty),*})*} => {
$(
impl $crate::ByteEncodable for $name
{
fn get_size<Size>(&self) -> Option<Size>
where Size: $crate::BVSize + $crate::ByteEncodable
{
let mut size = Some(Size::from_usize(0));
$(
size = size.and_then(|size: Size|
self.$field.get_size::<Size>().and_then(|field_size|
size.checked_add(field_size).and_then(
|acc_size| acc_size.checked_add(
Size::get_size_of())
)
)
);
)*
size
}
fn encode<Size>(&self) -> $crate::BVEncodeResult<Vec<u8>>
where Size: $crate::BVSize + $crate::ByteEncodable
{
if self.get_size::<Size>().is_some() {
let mut bytes = Vec::new();
$(
let field_size: Option<Size> = self.$field.get_size::<Size>();
bytes.extend_from_slice(&try!(
field_size.unwrap().encode::<Size>()));
)*
$(
bytes.extend_from_slice(&try!(self.$field.encode::<Size>()));
)*
Ok(bytes)
} else {
Err($crate::errors::ByteVecError::OverflowError)
}
}
}
#[allow(dead_code, unused_assignments)]
impl $crate::ByteDecodable for $name {
fn decode<Size>(bytes: &[u8]) -> $crate::BVDecodeResult<$name>
where Size: $crate::BVSize + $crate::ByteDecodable
{
let mut index = 0;
let mut sizes = ::std::collections::HashMap::new();
$(
if bytes[index..].len() >= Size::get_size_of().as_usize() {
sizes.insert(stringify!($field),
try!(Size::decode::<Size>(
&bytes[index..index + Size::get_size_of().as_usize()])));
index += Size::get_size_of().as_usize();
}
else {
return Err($crate::errors::ByteVecError::BadSizeDecodeError {
expected: $crate::errors::BVExpectedSize::MoreThan(
Size::get_size_of().as_usize() + index),
actual: bytes.len()
});
}
)*
let body_size = sizes.values().fold(0, |acc, ref size| acc + size.as_usize());
if body_size == bytes[index..].len() {
Ok($name {
$(
$field: {
let size = sizes[stringify!($field)].as_usize();
let field = try!(<$t as $crate::ByteDecodable>::decode::<Size>(
&bytes[index..index + size]));
index += size;
field
},
)*
..Default::default()
})
} else {
Err($crate::errors::ByteVecError::BadSizeDecodeError {
expected: $crate::errors::BVExpectedSize::EqualTo(
Size::get_size_of().as_usize() * sizes.len() + body_size),
actual: bytes.len()
})
}
}
}
)*
};
}
#[macro_export]
macro_rules! bytevec_decl {
{$($(#[$attr:meta])* struct $name:ident {$($field:ident : $t:ty),*})*} => {
$(
$(#[$attr])*
#[derive(Default)]
struct $name {
$($field: $t),*
}
bytevec_impls!(impl $name {$($field:$t),*});
)*
};
{$($(#[$attr:meta])* pub struct $name:ident {$(pub $field:ident : $t:ty),*})*} => {
$(
$(#[$attr])*
#[derive(Default)]
pub struct $name {
$(pub $field: $t),*
}
bytevec_impls!(impl $name {$($field:$t),*});
)*
};
{$($(#[$attr:meta])* pub struct $name:ident {$($field:ident : $t:ty),*})*} => {
$(
$(#[$attr])*
#[derive(Default)]
pub struct $name {
$($field: $t),*
}
bytevec_impls!(impl $name {$($field:$t),*});
)*
};
}