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 #[inline]
123 pub fn extend(&mut self, buttons: Self) {
124 self.0 |= buttons.0;
125 }
126
127 #[inline]
129 pub fn clear(&mut self) {
130 self.0 = 0;
131 }
132
133 #[inline]
135 pub fn count(self) -> u32 {
136 self.0.count_ones()
137 }
138}
139
140const NONZERO_VARIANTS: [PointerButton; 32] = [
141 PointerButton::Primary,
142 PointerButton::Secondary,
143 PointerButton::Auxiliary,
144 PointerButton::X1,
145 PointerButton::X2,
146 PointerButton::PenEraser,
147 PointerButton::B7,
148 PointerButton::B8,
149 PointerButton::B9,
150 PointerButton::B10,
151 PointerButton::B11,
152 PointerButton::B12,
153 PointerButton::B13,
154 PointerButton::B14,
155 PointerButton::B15,
156 PointerButton::B16,
157 PointerButton::B17,
158 PointerButton::B18,
159 PointerButton::B19,
160 PointerButton::B20,
161 PointerButton::B21,
162 PointerButton::B22,
163 PointerButton::B23,
164 PointerButton::B24,
165 PointerButton::B25,
166 PointerButton::B26,
167 PointerButton::B27,
168 PointerButton::B28,
169 PointerButton::B29,
170 PointerButton::B30,
171 PointerButton::B31,
172 PointerButton::B32,
173];
174
175impl core::fmt::Debug for PointerButtons {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 if self.is_empty() {
178 return f.write_str("PointerButtons(None)");
179 }
180
181 f.write_str("PointerButtons(")?;
182
183 if f.alternate() && self.count() > 2 {
184 f.write_str("\n ")?;
185 }
186
187 let mut first = true;
188 for button in NONZERO_VARIANTS {
189 if self.contains(button) {
190 if !first {
191 if f.alternate() && self.count() > 2 {
192 f.write_str("\n | ")?;
193 } else {
194 f.write_str(" | ")?;
195 }
196 }
197 first = false;
198 button.fmt(f)?;
199 }
200 }
201
202 if f.alternate() && self.count() > 2 {
203 f.write_str("\n)")
204 } else {
205 f.write_str(")")
206 }
207 }
208}
209impl core::fmt::Binary for PointerButtons {
210 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211 core::fmt::Binary::fmt(&self.0, f)
212 }
213}
214
215impl core::ops::BitOr for PointerButton {
216 type Output = PointerButtons;
217
218 fn bitor(self, rhs: Self) -> Self::Output {
219 PointerButtons(self as u32 | rhs as u32)
220 }
221}
222
223impl core::ops::BitOr<PointerButton> for PointerButtons {
224 type Output = Self;
225
226 fn bitor(self, rhs: PointerButton) -> Self {
227 Self(self.0 | rhs as u32)
228 }
229}
230
231impl core::ops::BitOrAssign<PointerButton> for PointerButtons {
232 fn bitor_assign(&mut self, rhs: PointerButton) {
233 self.0 |= rhs as u32;
234 }
235}
236
237impl From<PointerButton> for PointerButtons {
238 fn from(button: PointerButton) -> Self {
239 Self(button as u32)
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 #[test]
247 fn debug_fmt() {
248 use crate::pointer::{PointerButton, PointerButtons};
249 extern crate std;
250 use std::format;
251
252 assert_eq!(
253 format!("{:?}", PointerButtons::default()),
254 "PointerButtons(None)"
255 );
256 assert_eq!(
257 format!("{:?}", PointerButtons::from(PointerButton::Primary)),
258 "PointerButtons(Primary)"
259 );
260 assert_eq!(
261 format!("{:?}", PointerButton::Primary | PointerButton::Auxiliary),
262 "PointerButtons(Primary | Auxiliary)"
263 );
264 assert_eq!(
265 format!(
266 "{:?}",
267 PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary
268 ),
269 "PointerButtons(Primary | Secondary | Auxiliary)"
270 );
271 assert_eq!(
272 format!(
273 "{:#?}",
274 (
275 PointerButton::Primary | PointerButton::Auxiliary | PointerButton::Secondary,
276 PointerButton::B7 | PointerButton::X2
277 )
278 ),
279 "(
280 PointerButtons(
281 Primary
282 | Secondary
283 | Auxiliary
284 ),
285 PointerButtons(X2 | B7),
286)"
287 );
288 assert_eq!(
289 format!("{:?}", PointerButton::B32 | PointerButton::Primary),
290 "PointerButtons(Primary | B32)"
291 );
292 }
293
294 #[test]
296 fn option_niche_opt() {
297 use crate::pointer::PointerButton;
298 use core::mem::size_of;
299 assert_eq!(
300 size_of::<Option<PointerButton>>(),
301 size_of::<PointerButton>()
302 );
303 }
304}