1#![recursion_limit = "128"]
11
12extern crate proc_macro;
13extern crate proc_macro2;
14#[macro_use]
15extern crate quote;
16extern crate syn;
17
18#[proc_macro_derive(Bytes)]
19pub fn bytes_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
20 let input: proc_macro2::TokenStream = input.into();
21 let derive_input: syn::DeriveInput =
22 syn::parse2(input).expect("could not parse as syn::DeriveInput");
23 let name = &derive_input.ident;
24
25 if derive_input.generics.type_params().count() > 0
26 || derive_input.generics.lifetimes().count() > 0
27 || derive_input.generics.const_params().count() > 0
28 {
29 panic!("cannot derive Bytes for structs with generic parameters");
30 }
31
32 let impl_tokens: proc_macro2::TokenStream = quote! {
33 impl contrail::mem::Bytes for #name {
34 const LENGTH: usize = std::mem::size_of::<#name>();
35
36 #[inline(always)]
37 unsafe fn read_bytes(bytes: &[u8]) -> #name {
38 let byte_array = *(bytes.as_ptr() as *const [u8; std::mem::size_of::<#name>()]);
40 std::mem::transmute::<[u8; std::mem::size_of::<#name>()], #name>(byte_array)
42 }
43
44 #[inline(always)]
45 unsafe fn write_bytes(self, bytes: &mut [u8]) {
46 let byte_array = std::mem::transmute::<#name, [u8; std::mem::size_of::<#name>()]>(self);
48 bytes.copy_from_slice(&byte_array);
50 }
51 }
52 };
53
54 impl_tokens.into()
55}