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) -> TokenStream10 pub 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