1use super::*;
2
3impl Writer {
4 pub fn write_cpp_handle(&self, def: TypeDef) -> TokenStream {
5 let tn = def.type_name();
6 let name = to_ident(def.name());
7 let ty = def.underlying_type();
8 let ty_name = ty.write_name(self);
9
10 if self.config.sys {
11 quote! {
12 pub type #name = #ty_name;
13 }
14 } else {
15 let mut derive = quote! { Clone, Copy, Debug, PartialEq, Eq, };
16
17 let default = if ty.is_pointer() {
18 quote! {
19 impl Default for #name {
20 fn default() -> Self {
21 unsafe { core::mem::zeroed() }
22 }
23 }
24 }
25 } else {
26 derive.combine(quote! { Default, });
27 quote! {}
28 };
29
30 let invalid = def.invalid_values();
31
32 let is_invalid = if ty.is_pointer() && (invalid.is_empty() || invalid == [0]) {
33 quote! {
34 impl #name {
35 pub fn is_invalid(&self) -> bool {
36 self.0.is_null()
37 }
38 }
39 }
40 } else if invalid.is_empty() {
41 quote! {}
42 } else {
43 let invalid = invalid.iter().map(|value| {
44 let literal = Literal::i64_unsuffixed(*value);
45
46 if ty.is_pointer() || (*value < 0 && ty.is_unsigned()) {
47 quote! { self.0 == #literal as _ }
48 } else {
49 quote! { self.0 == #literal }
50 }
51 });
52 quote! {
53 impl #name {
54 pub fn is_invalid(&self) -> bool {
55 #(#invalid)||*
56 }
57 }
58 }
59 };
60
61 let free = if let Some(function) = def.free_function() {
62 if is_invalid.is_empty() {
63 // TODO: https://github.com/microsoft/win32metadata/issues/1891
64 quote! {}
65 } else {
66 let link = function.write_link(self, true);
67 let free = to_ident(function.method.name());
68 let signature = function.method.signature(def.namespace(), &[]);
69
70 // BCryptCloseAlgorithmProvider has an unused trailing parameter.
71 let tail = if signature.params.len() > 1 {
72 quote! { , 0 }
73 } else {
74 quote! {}
75 };
76
77 quote! {
78 impl windows_core::Free for #name {
79 #[inline]
80 unsafe fn free(&mut self) {
81 if !self.is_invalid() {
82 #link
83 unsafe { #free(self.0 #tail); }
84 }
85 }
86 }
87 }
88 }
89 } else {
90 quote! {}
91 };
92
93 let must_use = if matches!(
94 tn,
95 TypeName::BOOL | TypeName::NTSTATUS | TypeName::RPC_STATUS
96 ) {
97 quote! { #[must_use] }
98 } else {
99 quote! {}
100 };
101
102 let mut result = quote! {
103 #must_use
104 #[repr(transparent)]
105 #[derive(#derive)]
106 pub struct #name(pub #ty_name);
107 #is_invalid
108 #free
109 #default
110 };
111
112 if let Some(attribute) = def.find_attribute("AlsoUsableForAttribute") {
113 if let Some((_, Value::Str(type_name))) = attribute.args().first() {
114 let ty = def.reader().unwrap_full_name(def.namespace(), type_name);
115
116 let ty = ty.write_name(self);
117
118 result.combine(quote! {
119 impl windows_core::imp::CanInto<#ty> for #name {}
120 impl From<#name> for #ty {
121 fn from(value: #name) -> Self {
122 Self(value.0)
123 }
124 }
125 });
126 }
127 }
128
129 result
130 }
131 }
132}
133