1#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
12#[repr(u32)]
13pub enum PointerButton {
14 Primary = 1,
16 Secondary = 1 << 1,
18 Auxiliary = 1 << 2,
20 X1 = 1 << 3,
22 X2 = 1 << 4,
24 PenEraser = 1 << 5,
26 B7 = 1 << 6,
28 B8 = 1 << 7,
30 B9 = 1 << 8,
32 B10 = 1 << 9,
34 B11 = 1 << 10,
36 B12 = 1 << 11,
38 B13 = 1 << 12,
40 B14 = 1 << 13,
42 B15 = 1 << 14,
44 B16 = 1 << 15,
46 B17 = 1 << 16,
48 B18 = 1 << 17,
50 B19 = 1 << 18,
52 B20 = 1 << 19,
54 B21 = 1 << 20,
56 B22 = 1 << 21,
58 B23 = 1 << 22,
60 B24 = 1 << 23,
62 B25 = 1 << 24,
64 B26 = 1 << 25,
66 B27 = 1 << 26,
68 B28 = 1 << 27,
70 B29 = 1 << 28,
72 B30 = 1 << 29,
74 B31 = 1 << 30,
76 B32 = 1 << 31,
78}
79
80#[derive(Clone, Copy, Default, Eq, PartialEq)]
82pub struct PointerButtons(u32);
83
84impl PointerButtons {
85 #[inline]
87 pub fn new() -> Self {
88 Self(0)
89 }
90
91 #[inline]
93 pub fn insert(&mut self, button: PointerButton) {
94 self.0 |= button as u32;
95 }
96
97 #[inline]
99 pub fn remove(&mut self, button: PointerButton) {
100 self.0 &= !(button as u32);
101 }
102
103 #[inline]
105 pub fn contains(self, button: PointerButton) -> bool {
106 (self.0 & button as u32) != 0
107 }
108
109 #[inline]
111 pub fn is_empty(self) -> bool {
112 self.0 == 0
113 }
114
115 #[inline]
117 pub fn contains_all(self, buttons: Self) -> bool {
118 self.0 & buttons.0 == buttons.0
119 }
120
121 pub fn extend(&mut self, buttons: Self) {
123 self.0 |= buttons.0;
124 }
125
126 #[inline]
128 pub fn clear(&mut self) {
129 self.0 = 0;
130 }
131
132 #[inline]
134 pub fn count(self) -> u32 {
135 self.0.count_ones()
136 }
137}
138
139const NONZERO_VARIANTS: [PointerButton; 32] = [
140 PointerButton::Primary,
141 PointerButton::Secondary,
142 PointerButton::Auxiliary,
143 PointerButton::X1,
144 PointerButton::X2,
145 PointerButton::PenEraser,
146 PointerButton::B7,
147 PointerButton::B8,
148 PointerButton::B9,
149 PointerButton::B10,
150 PointerButton::B11,
151 PointerButton::B12,
152 PointerButton::B13,
153 PointerButton::B14,
154 PointerButton::B15,
155 PointerButton::B16,
156 PointerButton::B17,
157 PointerButton::B18,
158 PointerButton::B19,
159 PointerButton::B20,
160 PointerButton::B21,
161 PointerButton::B22,
162 PointerButton::B23,
163 PointerButton::B24,
164 PointerButton::B25,
165 PointerButton::B26,
166 PointerButton::B27,
167 PointerButton::B28,
168 PointerButton::B29,
169 PointerButton::B30,
170 PointerButton::B31,
171 PointerButton::B32,
172];
173
174impl core::fmt::Debug for PointerButtons {
175 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
176 if self.is_empty() {
177 return f.write_str("PointerButtons(None)");
178 }
179
180 f.write_str("PointerButtons(")?;
181
182 if f.alternate() && self.count() > 2 {
183 f.write_str("\n ")?;
184 }
185
186 let mut first = true;
187 for button in NONZERO_VARIANTS {
188 if self.contains(button) {
189 if !first {
190 if f.alternate() && self.count() > 2 {
191 f.write_str("\n | ")?;
192 } else {
193 f.write_str(" | ")?;
194 }
195 }
196 first = false;
197 button.fmt(f)?;
198 }
199 }
200
201 if f.alternate() && self.count() > 2 {
202 f.write_str("\n)")
203 } else {
204 f.write_str(")")
205 }
206 }
207}
208impl core::fmt::Binary for PointerButtons {
209 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
210 core::fmt::Binary::fmt(&self.0, f)
211 }
212}
213
214impl core::ops::BitOr for PointerButton {
215 type Output = PointerButtons;
216
217 fn bitor(self, rhs: Self) -> Self::Output {
218 PointerButtons(self as u32 | rhs as u32)
219 }
220}
221
222impl core::ops::BitOr<PointerButton> for PointerButtons {
223 type Output = Self;
224
225 fn bitor(self, rhs: PointerButton) -> Self {
226 Self(self.0 | rhs as u32)
227 }
228}
229
230impl core::ops::BitOrAssign<PointerButton> for PointerButtons {
231 fn bitor_assign(&mut self, rhs: PointerButton) {
232 self.0 |= rhs as u32;
233 }
234}
235
236impl From<PointerButton> for PointerButtons {
237 fn from(button: PointerButton) -> Self {
238 Self(button as u32)
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 #[test]
246 fn debug_fmt() {
247 use crate::pointer::{PointerButton, PointerButtons};
248 extern crate std;
249 use std::format;
250
251 assert_eq!(
252 format!("{:?}", PointerButtons::default()),
253 "PointerButtons(None)"
254 );
255 assert_eq!(
256 format!("{:?}", PointerButtons::from(PointerButton::Primary)),
257 "PointerButtons(Primary)"
258 );
259 assert_eq!(
260 format!("{:?}", PointerButton::Primary | PointerButton::Auxiliary),
261 "PointerButtons(Primary | Auxiliary)"
262 );
263 assert_eq!(
264 format!(
265 "{:?}",
266 PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary
267 ),
268 "PointerButtons(Primary | Secondary | Auxiliary)"
269 );
270 assert_eq!(
271 format!(
272 "{:#?}",
273 (
274 PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary,
275 PointerButton::B7 | PointerButton::X2
276 )
277 ),
278 "(
279 PointerButtons(
280 Primary
281 | Secondary
282 | Auxiliary
283 ),
284 PointerButtons(X2 | B7),
285)"
286 );
287 assert_eq!(
288 format!("{:?}", PointerButton::B32 | PointerButton::Primary),
289 "PointerButtons(Primary | B32)"
290 );
291 }
292
293 #[test]
295 fn option_niche_opt() {
296 use crate::pointer::PointerButton;
297 use core::mem::size_of;
298 assert_eq!(
299 size_of::<Option<PointerButton>>(),
300 size_of::<PointerButton>()
301 );
302 }
303}