1extern crate proc_macro;
2
3use syn::{Data, DeriveInput, Error, parse_macro_input};
4use quote::quote;
5
6#[proc_macro_derive(Columns)]
7pub fn columns_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
8 let ast: syn::DeriveInput = parse_macro_input!(input as DeriveInput);
9 let ident = &ast.ident;
10 let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
11 let data = match ast.data {
12 Data::Struct(ref data) => data,
13 _ => {
14 let e = Error::new_spanned(&ast, "trait `Columns` can only be implemented for structs");
15 return proc_macro::TokenStream::from(e.to_compile_error());
16 }
17 };
18
19 let pointers = data.fields.iter().count();
20 let dangling = data.fields.iter().map(|field| &field.ty);
21
22 let expanded = quote! {
23 unsafe impl #impl_generics ::soak::Columns for #ident #ty_generics #where_clause {
24 type Pointers = [::core::ptr::NonNull<u8>; #pointers];
25
26 fn dangling() -> Self::Pointers {
27 [ #(unsafe { ::core::ptr::NonNull::new_unchecked(
28 ::core::mem::align_of::<#dangling>() as *mut u8
29 ) },)* ]
30 }
31 }
32 };
33
34 proc_macro::TokenStream::from(expanded)
35}