1use super::*;
2
3#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
4pub struct Class {
5 pub def: TypeDef,
6}
7
8impl Class {
9 pub fn type_name(&self) -> TypeName {
10 self.def.type_name()
11 }
12
13 pub fn write(&self, writer: &Writer) -> TokenStream {
14 let mut required_interfaces = self.required_interfaces();
15 required_interfaces.sort();
16 let type_name = self.def.type_name();
17 let name = to_ident(type_name.name());
18 let mut dependencies = TypeMap::new();
19
20 if writer.config.package {
21 self.dependencies(&mut dependencies);
22 }
23
24 let cfg = writer.write_cfg(self.def, type_name.namespace(), &dependencies, false);
25 let runtime_name = format!("{type_name}");
26
27 let runtime_name = quote! {
28 #cfg
29 impl windows_core::RuntimeName for #name {
30 const NAME: &'static str = #runtime_name;
31 }
32 };
33
34 let mut methods = quote! {};
35 let mut method_names = MethodNames::new();
36
37 for interface in &required_interfaces {
38 let mut virtual_names = MethodNames::new();
39
40 for method in interface
41 .get_methods(writer)
42 .iter()
43 .filter_map(|method| match &method {
44 MethodOrName::Method(method) => Some(method),
45 _ => None,
46 })
47 {
48 let mut difference = TypeMap::new();
49
50 if writer.config.package {
51 difference = method.dependencies.difference(&dependencies);
52 }
53
54 let cfg = writer.write_cfg(self.def, type_name.namespace(), &difference, false);
55
56 let method = method.write(
57 writer,
58 Some(interface),
59 interface.kind,
60 &mut method_names,
61 &mut virtual_names,
62 );
63
64 methods.combine(quote! {
65 #cfg
66 #method
67 });
68 }
69 }
70
71 let new = self.has_default_constructor().then(||
72 quote! {
73 pub fn new() -> windows_core::Result<Self> {
74 Self::IActivationFactory(|f| f.ActivateInstance::<Self>())
75 }
76 fn IActivationFactory<R, F: FnOnce(&windows_core::imp::IGenericFactory) -> windows_core::Result<R>>(
77 callback: F,
78 ) -> windows_core::Result<R> {
79 static SHARED: windows_core::imp::FactoryCache<#name, windows_core::imp::IGenericFactory> =
80 windows_core::imp::FactoryCache::new();
81 SHARED.call(callback)
82 }
83 }
84 );
85
86 let factories = required_interfaces.iter().filter_map(|interface| match interface.kind {
87 InterfaceKind::Static | InterfaceKind::Composable => {
88 if interface.def.methods().next().is_none() {
89 None
90 } else {
91 let method_name = to_ident(interface.def.name());
92 let interface_type = interface.write_name(writer);
93 let cfg = quote! {};
94
95 Some(quote! {
96 #cfg
97 fn #method_name<R, F: FnOnce(&#interface_type) -> windows_core::Result<R>>(
98 callback: F,
99 ) -> windows_core::Result<R> {
100 static SHARED: windows_core::imp::FactoryCache<#name, #interface_type> =
101 windows_core::imp::FactoryCache::new();
102 SHARED.call(callback)
103 }
104 })
105 }
106 }
107 _ => None,
108 });
109
110 if let Some(default_interface) = self.default_interface() {
111 if default_interface.is_async() {
112 let default_interface = default_interface.write_name(writer);
113
114 return quote! {
115 #cfg
116 pub type #name = #default_interface;
117 };
118 }
119
120 let is_exclusive = default_interface.is_exclusive();
121 let default_interface = default_interface.write_name(writer);
122
123 let interface_hierarchy = if is_exclusive {
124 quote! { windows_core::imp::interface_hierarchy!(#name, windows_core::IUnknown, windows_core::IInspectable); }
125 } else {
126 quote! { windows_core::imp::interface_hierarchy!(#name, windows_core::IUnknown, windows_core::IInspectable, #default_interface); }
127 };
128
129 let required_hierarchy = {
130 let mut interfaces: Vec<_> = required_interfaces
131 .iter()
132 .filter(|ty| !ty.is_exclusive() && ty.kind != InterfaceKind::Default)
133 .map(|ty| ty.write_name(writer))
134 .collect();
135
136 interfaces.extend(self.bases().iter().map(|ty| ty.write_name(writer)));
137
138 if interfaces.is_empty() {
139 quote! {}
140 } else {
141 quote! {
142 #cfg
143 windows_core::imp::required_hierarchy!(#name, #(#interfaces),*);
144 }
145 }
146 };
147
148 let agile = self.def.is_agile().then(|| {
149 quote! {
150 #cfg
151 unsafe impl Send for #name {}
152 #cfg
153 unsafe impl Sync for #name {}
154 }
155 });
156
157 let into_iterator = required_interfaces
158 .iter()
159 .find(|interface| interface.def.type_name() == TypeName::IIterable)
160 .map(|interface| {
161 let ty = interface.generics[0].write_name(writer);
162 let namespace = writer.write_namespace(TypeName::IIterator);
163
164 quote! {
165 #cfg
166 impl IntoIterator for #name {
167 type Item = #ty;
168 type IntoIter = #namespace IIterator<Self::Item>;
169
170 fn into_iter(self) -> Self::IntoIter {
171 IntoIterator::into_iter(&self)
172 }
173 }
174 #cfg
175 impl IntoIterator for &#name {
176 type Item = #ty;
177 type IntoIter = #namespace IIterator<Self::Item>;
178
179 fn into_iter(self) -> Self::IntoIter {
180 self.First().unwrap()
181 }
182 }
183
184 }
185 });
186
187 quote! {
188 #cfg
189 #[repr(transparent)]
190 #[derive(Clone, Debug, Eq, PartialEq)]
191 pub struct #name(windows_core::IUnknown);
192 #cfg
193 #interface_hierarchy
194 #required_hierarchy
195 #cfg
196 impl #name {
197 #new
198 #methods
199 #(#factories)*
200 }
201 #cfg
202 impl windows_core::RuntimeType for #name {
203 const SIGNATURE: windows_core::imp::ConstBuffer = windows_core::imp::ConstBuffer::for_class::<Self, #default_interface>();
204 }
205 #cfg
206 unsafe impl windows_core::Interface for #name {
207 type Vtable = <#default_interface as windows_core::Interface>::Vtable;
208 const IID: windows_core::GUID = <#default_interface as windows_core::Interface>::IID;
209 }
210 #runtime_name
211 #agile
212 #into_iterator
213 }
214 } else {
215 quote! {
216 #cfg
217 pub struct #name;
218 #cfg
219 impl #name {
220 #methods
221 #(#factories)*
222 }
223 #runtime_name
224 }
225 }
226 }
227
228 pub fn write_name(&self, writer: &Writer) -> TokenStream {
229 self.type_name().write(writer, &[])
230 }
231
232 fn default_interface(&self) -> Option<Type> {
233 self.def
234 .interface_impls()
235 .find(|imp| imp.has_attribute("DefaultAttribute"))
236 .map(|imp| imp.ty(&[]))
237 }
238
239 pub fn runtime_signature(&self) -> String {
240 format!(
241 "rc({};{})",
242 self.type_name(),
243 self.default_interface().unwrap().runtime_signature()
244 )
245 }
246
247 pub fn dependencies(&self, dependencies: &mut TypeMap) {
248 for interface in self.required_interfaces() {
249 Type::Interface(interface).dependencies(dependencies);
250 }
251 }
252
253 fn bases(&self) -> Vec<Self> {
254 let mut bases = Vec::new();
255 let mut def = self.def;
256 let reader = def.reader();
257
258 loop {
259 let extends = def.extends().unwrap();
260
261 if extends == TypeName::Object {
262 break;
263 }
264
265 let Type::Class(base) = reader.unwrap_full_name(extends.namespace(), extends.name())
266 else {
267 panic!("type not found: {extends}");
268 };
269
270 def = base.def;
271 bases.push(base);
272 }
273
274 bases
275 }
276
277 pub fn required_interfaces(&self) -> Vec<Interface> {
278 fn walk(def: TypeDef, generics: &[Type], is_base: bool, set: &mut Vec<Interface>) {
279 for imp in def.interface_impls() {
280 let Type::Interface(mut interface) = imp.ty(generics) else {
281 panic!();
282 };
283
284 interface.kind = if !is_base && imp.has_attribute("DefaultAttribute") {
285 InterfaceKind::Default
286 } else if is_base {
287 InterfaceKind::Base
288 } else {
289 InterfaceKind::None
290 };
291
292 if let Some(pos) = set
293 .iter()
294 .position(|existing| existing.def == interface.def)
295 {
296 if interface.kind == InterfaceKind::Default {
297 set[pos].kind = interface.kind;
298 }
299 } else {
300 walk(interface.def, &interface.generics, is_base, set);
301 set.push(interface);
302 }
303 }
304 }
305 let mut set = vec![];
306 walk(self.def, &[], false, &mut set);
307
308 for base in self.bases() {
309 walk(base.def, &[], true, &mut set);
310 }
311
312 for attribute in self.def.attributes() {
313 let kind = match attribute.name() {
314 "StaticAttribute" | "ActivatableAttribute" => InterfaceKind::Static,
315 "ComposableAttribute" => InterfaceKind::Composable,
316 _ => continue,
317 };
318
319 for (_, arg) in attribute.args() {
320 if let Value::TypeName(tn) = arg {
321 let Type::Interface(mut interface) = self
322 .def
323 .reader()
324 .unwrap_full_name(tn.namespace(), tn.name())
325 else {
326 panic!("type not found: {tn}");
327 };
328
329 interface.kind = kind;
330 set.push(interface);
331 break;
332 }
333 }
334 }
335
336 set
337 }
338
339 fn has_default_constructor(&self) -> bool {
340 self.def
341 .attributes()
342 .filter(|attribute| attribute.name() == "ActivatableAttribute")
343 .any(|attribute| {
344 !attribute
345 .args()
346 .iter()
347 .any(|arg| matches!(arg.1, Value::TypeName(_)))
348 })
349 }
350}
351