1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use proc_macro::TokenStream; |
4 | use quote::{format_ident, quote}; |
5 | use syn::{Generics, Ident}; |
6 | |
7 | use super::fields::{derive_downgrade_fields, DowngradeStructParts}; |
8 | use 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 | /// ``` |
84 | pub 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 | } |
124 | |