Skip to main content

safe_uninit_derive/
lib.rs

1extern crate proc_macro;
2extern crate syn;
3#[macro_use]
4extern crate quote;
5
6use proc_macro::TokenStream;
7use quote::TokenStreamExt;
8
9#[proc_macro_derive(SafeUninit)]
10pub fn derive_answer_fn(item: TokenStream) -> TokenStream {
11    let mut st = syn::parse_macro_input!(item as syn::ItemStruct);
12    let ident = &st.ident;
13    let fields = &mut st.fields;
14
15    let mut tok = quote!();
16    let mut is_named = true;
17    for f in fields {
18        if let Some(name) = f.ident.as_ref() {
19            tok.append_all(quote!(#name: safe_uninit::SafeUninit::safe_uninit(),));
20            is_named = true;
21        } else {
22            is_named = false;
23            tok.append_all(quote!(safe_uninit::SafeUninit::safe_uninit(),));
24        }
25    }
26    let tok = if is_named {
27        quote!({#tok})
28    } else {
29        quote!((#tok))
30    };
31
32    quote!(
33        unsafe impl safe_uninit::SafeUninit for #ident {
34            fn safe_uninit() -> Self {
35                #ident #tok
36            }
37        }
38    ).into()
39}
40
41#[cfg(test)]
42mod test {
43
44    #[test]
45    fn derive0() {
46        let t = trybuild::TestCases::new();
47        t.pass("src/tests/pass.rs");
48        t.compile_fail("src/tests/fail.rs");
49    }
50}