glib_macros/downgrade_derive/
structs.rs

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