summaryrefslogtreecommitdiffstats
path: root/third_party/rust/diplomat/src/transparent_convert.rs
blob: 9ac8bf64e78538fdb5c7a0b9dcb82b0212f34a5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
use quote::quote;
use syn::*;

pub fn gen_transparent_convert(s: ItemStruct) -> proc_macro2::TokenStream {
    let mut fields = s.fields.iter();
    let field1 = if let Some(field1) = fields.next() {
        &field1.ty
    } else {
        panic!("#[diplomat::transparent_convert] only allowed on structs with a single field")
    };

    if fields.next().is_some() {
        panic!("#[diplomat::transparent_convert] only allowed on structs with a single field")
    }
    let struct_name = &s.ident;
    let (impl_generics, ty_generics, _) = s.generics.split_for_impl();
    let mut impl_generics: Generics = parse_quote!(#impl_generics);
    let custom_lifetime: GenericParam = parse_quote!('transparent_convert_outer);
    impl_generics.params.push(custom_lifetime);
    quote! {
        impl #impl_generics #struct_name #ty_generics {
            // can potentially add transparent_convert_owned, _mut later
            pub(crate) fn transparent_convert(from: &'transparent_convert_outer #field1) -> &'transparent_convert_outer Self {
                unsafe {
                    &*(from as *const #field1 as *const Self)
                }
            }
        }
    }
}