]> git.proxmox.com Git - rustc.git/blob - vendor/windows-bindgen/src/rust/enums.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / windows-bindgen / src / rust / enums.rs
1 use super::*;
2
3 pub fn writer(writer: &Writer, def: TypeDef) -> TokenStream {
4 let type_name = writer.reader.type_def_type_name(def);
5 let ident = to_ident(type_name.name);
6 let underlying_type = writer.reader.type_def_underlying_type(def);
7 let underlying_type = writer.type_name(&underlying_type);
8
9 // TODO: unscoped enums should be removed from metadata
10 let is_scoped = writer.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) || writer.reader.has_attribute(def, "ScopedEnumAttribute");
11
12 let cfg = type_def_cfg(writer.reader, def, &[]);
13 let doc = writer.cfg_doc(&cfg);
14 let features = writer.cfg_features(&cfg);
15
16 let fields: Vec<(TokenStream, TokenStream)> = writer
17 .reader
18 .type_def_fields(def)
19 .filter_map(|field| {
20 if writer.reader.field_flags(field).contains(FieldAttributes::Literal) {
21 let field_name = to_ident(writer.reader.field_name(field));
22 let constant = writer.reader.field_constant(field).unwrap();
23 let value = writer.value(&writer.reader.constant_value(constant));
24
25 Some((field_name, value))
26 } else {
27 None
28 }
29 })
30 .collect();
31
32 let eq = if writer.sys {
33 quote! {}
34 } else {
35 quote! {
36 // Unfortunately, Rust requires these to be derived to allow constant patterns.
37 #[derive(::core::cmp::PartialEq, ::core::cmp::Eq)]
38 }
39 };
40
41 let mut tokens = if is_scoped || !writer.sys {
42 quote! {
43 #doc
44 #features
45 #[repr(transparent)]
46 #eq
47 pub struct #ident(pub #underlying_type);
48 }
49 } else {
50 quote! {
51 #doc
52 #features
53 pub type #ident = #underlying_type;
54 }
55 };
56
57 if is_scoped {
58 let fields = fields.iter().map(|(field_name, value)| {
59 quote! {
60 pub const #field_name: Self = Self(#value);
61 }
62 });
63
64 tokens.combine(&quote! {
65 #features
66 impl #ident {
67 #(#fields)*
68 }
69 });
70 }
71
72 if is_scoped || !writer.sys {
73 tokens.combine(&quote! {
74 #features
75 impl ::core::marker::Copy for #ident {}
76 #features
77 impl ::core::clone::Clone for #ident {
78 fn clone(&self) -> Self {
79 *self
80 }
81 }
82 });
83 }
84
85 if !writer.sys {
86 tokens.combine(&quote! {
87 #features
88 impl ::core::default::Default for #ident {
89 fn default() -> Self {
90 Self(0)
91 }
92 }
93 });
94 }
95
96 if !writer.sys {
97 let name = type_name.name;
98 tokens.combine(&quote! {
99 #features
100 impl ::windows_core::TypeKind for #ident {
101 type TypeKind = ::windows_core::CopyType;
102 }
103 #features
104 impl ::core::fmt::Debug for #ident {
105 fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
106 f.debug_tuple(#name).field(&self.0).finish()
107 }
108 }
109 });
110
111 // Win32 enums use the Flags attribute. WinRT enums don't have the Flags attribute but are paritioned merely based
112 // on whether they are signed.
113 // TODO: Win32 metadata should just follow WinRT's example here.
114 let type_def_is_flags = writer.reader.has_attribute(def, "FlagsAttribute") || (writer.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) && writer.reader.type_def_underlying_type(def) == Type::U32);
115
116 if type_def_is_flags {
117 tokens.combine(&quote! {
118 #features
119 impl #ident {
120 pub const fn contains(&self, other: Self) -> bool {
121 self.0 & other.0 == other.0
122 }
123 }
124 #features
125 impl ::core::ops::BitOr for #ident {
126 type Output = Self;
127
128 fn bitor(self, other: Self) -> Self {
129 Self(self.0 | other.0)
130 }
131 }
132 #features
133 impl ::core::ops::BitAnd for #ident {
134 type Output = Self;
135
136 fn bitand(self, other: Self) -> Self {
137 Self(self.0 & other.0)
138 }
139 }
140 #features
141 impl ::core::ops::BitOrAssign for #ident {
142 fn bitor_assign(&mut self, other: Self) {
143 self.0.bitor_assign(other.0)
144 }
145 }
146 #features
147 impl ::core::ops::BitAndAssign for #ident {
148 fn bitand_assign(&mut self, other: Self) {
149 self.0.bitand_assign(other.0)
150 }
151 }
152 #features
153 impl ::core::ops::Not for #ident {
154 type Output = Self;
155
156 fn not(self) -> Self {
157 Self(self.0.not())
158 }
159 }
160 });
161 }
162
163 if writer.reader.type_def_flags(def).contains(TypeAttributes::WindowsRuntime) {
164 let signature = Literal::byte_string(type_def_signature(writer.reader, def, &[]).as_bytes());
165
166 tokens.combine(&quote! {
167 #features
168 impl ::windows_core::RuntimeType for #ident {
169 const SIGNATURE: ::windows_core::imp::ConstBuffer = ::windows_core::imp::ConstBuffer::from_slice(#signature);
170 }
171 });
172 }
173 }
174
175 tokens
176 }