1 // Take a look at the license at the top of the repository in the LICENSE file. 2 3 use proc_macro2::TokenStream; 4 use proc_macro_error::abort_call_site; 5 use quote::quote; 6 7 pub const WRONG_PLACE_MSG: &str = 8 "This macro should be used on `impl` block for `glib::ObjectInterface` trait"; 9 impl_object_interface(input: &syn::ItemImpl) -> TokenStream10pub fn impl_object_interface(input: &syn::ItemImpl) -> TokenStream { 11 let mut has_prerequisites = false; 12 for item in &input.items { 13 if let syn::ImplItem::Type(type_) = item { 14 let name = type_.ident.to_string(); 15 if name == "Prerequisites" { 16 has_prerequisites = true; 17 } 18 } 19 } 20 21 let syn::ItemImpl { 22 attrs, 23 generics, 24 trait_, 25 self_ty, 26 unsafety, 27 items, 28 .. 29 } = &input; 30 31 let prerequisites_opt = if has_prerequisites { 32 None 33 } else { 34 Some(quote!( 35 type Prerequisites = (); 36 )) 37 }; 38 39 let crate_ident = crate::utils::crate_ident_new(); 40 41 let trait_path = match &trait_ { 42 Some(path) => &path.1, 43 None => abort_call_site!(WRONG_PLACE_MSG), 44 }; 45 46 quote! { 47 #(#attrs)* 48 #unsafety impl#generics #trait_path for #self_ty { 49 #prerequisites_opt 50 #(#items)* 51 } 52 53 unsafe impl #crate_ident::subclass::interface::ObjectInterfaceType for #self_ty { 54 fn type_() -> #crate_ident::Type { 55 static ONCE: std::sync::Once = std::sync::Once::new(); 56 static mut TYPE: #crate_ident::Type = #crate_ident::Type::INVALID; 57 58 ONCE.call_once(|| { 59 let type_ = #crate_ident::subclass::register_interface::<Self>(); 60 unsafe { 61 TYPE = type_; 62 } 63 }); 64 65 unsafe { 66 assert!(TYPE.is_valid()); 67 TYPE 68 } 69 } 70 } 71 } 72 } 73