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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
// Take a look at the license at the top of the repository in the LICENSE file. use super::fields::{derive_downgrade_fields, DowngradeStructParts}; use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::{Generics, Ident}; /// This function derives a weak type for a given strong struct and /// implementations of `Downgrade` and `Upgrade` traits. /// /// # Example /// /// ```rust,ignore /// #[derive(glib::Downgrade)] /// struct Unnamed(X, Y); /// /// #[derive(glib::Downgrade)] /// struct Named { /// x: X, /// y: Y, /// } /// ``` /// /// Here is what will be derived: /// /// ```rust,ignore /// pub struct UnnamedWeak(<X as Downgrade>::Weak, <Y as Downgrade>::Weak); /// /// impl glib::clone::Downgrade for Unnamed { /// type Weak = UnnamedWeak; /// /// fn downgrade(&self) -> Self::Weak { /// let Self (ref _0, ref _1) = self; /// UnnamedWeak ( /// glib::clone::Downgrade::downgrade(_0), /// glib::clone::Downgrade::downgrade(_1), /// ) /// } /// } /// /// impl glib::clone::Upgrade for UnnamedWeak { /// type Strong = Unnamed; /// /// fn upgrade(&self) -> Option<Self::Strong> { /// let Self (ref _0, ref _1) = self; /// Some(Unnamed ( /// glib::clone::Upgrade::upgrade(_0)?, /// glib::clone::Upgrade::upgrade(_1)?, /// )) /// } /// } /// /// pub struct NamedWeak { /// x: <X as Downgrade>::Weak, /// y: <Y as Downgrade>::Weak, /// } /// /// impl glib::clone::Downgrade for Named { /// type Weak = NamedWeak; /// /// fn downgrade(&self) -> Self::Weak { /// let Self { ref x, ref y } = self; /// NamedWeak { /// glib::clone::Downgrade::downgrade(x), /// glib::clone::Downgrade::downgrade(y), /// } /// } /// } /// /// impl glib::clone::Upgrade for NamedWeak { /// type Strong = Named; /// /// fn upgrade(&self) -> Option<Self::Strong> { /// let Self { ref x, ref y } = self; /// Some(Named { /// glib::clone::Upgrade::upgrade(x)?, /// glib::clone::Upgrade::upgrade(y)?, /// }) /// } /// } /// ``` pub fn derive_downgrade_for_struct( ident: Ident, generics: Generics, data_struct: syn::DataStruct, ) -> TokenStream { let weak_type = format_ident!("{}Weak", ident); let DowngradeStructParts { weak_fields, end_of_struct, destruct, downgrade, upgrade, } = derive_downgrade_fields(data_struct.fields); let derived = quote! { pub struct #weak_type #generics #weak_fields #end_of_struct impl #generics glib::clone::Downgrade for #ident #generics { type Weak = #weak_type #generics; fn downgrade(&self) -> Self::Weak { let Self #destruct = self; #weak_type #downgrade } } impl #generics glib::clone::Upgrade for #weak_type #generics { type Strong = #ident #generics; fn upgrade(&self) -> Option<Self::Strong> { let Self #destruct = self; Some(#ident #upgrade) } } }; derived.into() }