1 use quote::quote; 2 use syn::*; 3 gen_transparent_convert(s: ItemStruct) -> proc_macro2::TokenStream4pub fn gen_transparent_convert(s: ItemStruct) -> proc_macro2::TokenStream { 5 let mut fields = s.fields.iter(); 6 let field1 = if let Some(field1) = fields.next() { 7 &field1.ty 8 } else { 9 panic!("#[diplomat::transparent_convert] only allowed on structs with a single field") 10 }; 11 12 if fields.next().is_some() { 13 panic!("#[diplomat::transparent_convert] only allowed on structs with a single field") 14 } 15 let struct_name = &s.ident; 16 let (impl_generics, ty_generics, _) = s.generics.split_for_impl(); 17 let mut impl_generics: Generics = parse_quote!(#impl_generics); 18 let custom_lifetime: GenericParam = parse_quote!('transparent_convert_outer); 19 impl_generics.params.push(custom_lifetime); 20 quote! { 21 impl #impl_generics #struct_name #ty_generics { 22 // can potentially add transparent_convert_owned, _mut later 23 pub(crate) fn transparent_convert(from: &'transparent_convert_outer #field1) -> &'transparent_convert_outer Self { 24 // Safety: This is safe because the caller of gen_transparent_convert 25 // adds a repr(transparent) to the struct. 26 unsafe { 27 &*(from as *const #field1 as *const Self) 28 } 29 } 30 } 31 } 32 } 33