soak_derive/
lib.rs

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}