1use super::*;
2
3#[derive(Clone, Debug, PartialEq, Eq, Hash)]
4pub struct CppEnum {
5 pub def: TypeDef,
6}
7
8impl Ord for CppEnum {
9 fn cmp(&self, other: &Self) -> Ordering {
10 self.def.name().cmp(other.def.name())
11 }
12}
13
14impl PartialOrd for CppEnum {
15 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
16 Some(self.cmp(other))
17 }
18}
19
20impl CppEnum {
21 pub fn type_name(&self) -> TypeName {
22 self.def.type_name()
23 }
24
25 pub fn write_name(&self, writer: &Writer) -> TokenStream {
26 self.type_name().write(writer, &[])
27 }
28
29 pub fn write(&self, writer: &Writer) -> TokenStream {
30 let tn = self.def.type_name();
31 let is_scoped = self.def.has_attribute("ScopedEnumAttribute");
32
33 if !is_scoped && writer.config.sys {
34 return writer.write_cpp_handle(self.def);
35 }
36
37 let name = to_ident(tn.name());
38 let underlying_type = self.def.underlying_type().write_name(writer);
39
40 let mut derive = DeriveWriter::new(writer, tn);
41 derive.extend(["Copy", "Clone"]);
42
43 if !writer.config.sys {
44 derive.extend(["Default", "Debug", "PartialEq", "Eq"]);
45 }
46
47 let fields = if is_scoped {
48 let fields = self
49 .def
50 .fields()
51 .filter(|field| field.flags().contains(FieldAttributes::Literal))
52 .map(|field| {
53 let name = to_ident(field.name());
54 let value = field.constant().unwrap().value().write();
55
56 quote! {
57 pub const #name: Self = Self(#value);
58 }
59 });
60
61 quote! {
62 impl #name {
63 #(#fields)*
64 }
65 }
66 } else {
67 quote! {}
68 };
69
70 let flags = if writer.config.sys || !self.def.has_attribute("FlagsAttribute") {
71 quote! {}
72 } else {
73 quote! {
74 impl #name {
75 pub const fn contains(&self, other: Self) -> bool {
76 self.0 & other.0 == other.0
77 }
78 }
79 impl core::ops::BitOr for #name {
80 type Output = Self;
81 fn bitor(self, other: Self) -> Self {
82 Self(self.0 | other.0)
83 }
84 }
85 impl core::ops::BitAnd for #name {
86 type Output = Self;
87 fn bitand(self, other: Self) -> Self {
88 Self(self.0 & other.0)
89 }
90 }
91 impl core::ops::BitOrAssign for #name {
92 fn bitor_assign(&mut self, other: Self) {
93 self.0.bitor_assign(other.0)
94 }
95 }
96 impl core::ops::BitAndAssign for #name {
97 fn bitand_assign(&mut self, other: Self) {
98 self.0.bitand_assign(other.0)
99 }
100 }
101 impl core::ops::Not for #name {
102 type Output = Self;
103 fn not(self) -> Self {
104 Self(self.0.not())
105 }
106 }
107
108 }
109 };
110
111 let must_use = if matches!(tn, TypeName::WIN32_ERROR | TypeName::RPC_STATUS) {
112 quote! { #[must_use] }
113 } else {
114 quote! {}
115 };
116
117 quote! {
118 #must_use
119 #[repr(transparent)]
120 #derive
121 pub struct #name(pub #underlying_type);
122 #fields
123 #flags
124 }
125 }
126
127 pub fn dependencies(&self, dependencies: &mut TypeMap) {
128 if let Some(attribute) = self.def.find_attribute("AlsoUsableForAttribute") {
129 if let Some((_, Value::Str(type_name))) = attribute.args().first() {
130 self.def
131 .reader()
132 .unwrap_full_name(self.def.namespace(), type_name)
133 .dependencies(dependencies);
134 }
135 }
136 }
137
138 pub fn size(&self) -> usize {
139 self.def.underlying_type().size()
140 }
141
142 pub fn align(&self) -> usize {
143 self.def.underlying_type().align()
144 }
145}
146