playdate_controls/
buttons.rs1use core::fmt::Debug;
2use core::fmt::Display;
3use core::ops::BitAnd;
4use sys::ffi::PDButtons;
5
6
7pub trait PDButtonsExt: Sized + BitAnd<Self> {
8 #![allow(non_snake_case)]
9
10 fn contains(&self, other: Self) -> bool;
16
17 fn contains_ref(&self, other: &Self) -> bool;
20
21 fn any(&self) -> bool;
23
24 fn is_empty(&self) -> bool;
26
27 #[inline(always)]
28 fn left(&self) -> bool { self.contains(Self::Left()) }
30
31 #[inline(always)]
32 fn right(&self) -> bool { self.contains(Self::Right()) }
34
35 #[inline(always)]
36 fn up(&self) -> bool { self.contains(Self::Up()) }
38
39 #[inline(always)]
40 fn down(&self) -> bool { self.contains(Self::Down()) }
42
43 #[inline(always)]
44 fn b(&self) -> bool { self.contains(Self::B()) }
46
47 #[inline(always)]
48 fn a(&self) -> bool { self.contains(Self::A()) }
50
51
52 fn Left() -> Self;
53 fn Right() -> Self;
54 fn Up() -> Self;
55 fn Down() -> Self;
56 fn B() -> Self;
57 fn A() -> Self;
58}
59
60
61impl PDButtonsExt for PDButtons {
62 #![allow(non_snake_case)]
63
64 #[inline(always)]
65 fn contains(&self, other: Self) -> bool { (self.0 & other.0) != 0 }
66
67 #[inline(always)]
68 fn contains_ref(&self, other: &Self) -> bool { (self.0 & other.0) != 0 }
69
70 #[inline(always)]
71 fn any(&self) -> bool { self.0 > 0 }
72
73 #[inline(always)]
74 fn is_empty(&self) -> bool { self.0 == 0 }
75
76
77 #[inline(always)]
78 fn Left() -> Self { Self::kButtonLeft }
79
80 #[inline(always)]
81 fn Right() -> Self { Self::kButtonRight }
82
83 #[inline(always)]
84 fn Up() -> Self { Self::kButtonUp }
85
86 #[inline(always)]
87 fn Down() -> Self { Self::kButtonDown }
88
89 #[inline(always)]
90 fn B() -> Self { Self::kButtonB }
91
92 #[inline(always)]
93 fn A() -> Self { Self::kButtonA }
94}
95
96
97pub trait PDButtonsIntoIter {
98 type Item;
99 type IntoIter: Iterator<Item = Self::Item>;
100
101 fn into_iter(self) -> Self::IntoIter;
102}
103
104impl PDButtonsIntoIter for PDButtons {
105 type Item = &'static Self;
106 type IntoIter = impl Iterator<Item = Self::Item>;
107
108 fn into_iter(self) -> Self::IntoIter {
109 static ALL: [PDButtons; 6] = [
110 PDButtons::kButtonLeft,
111 PDButtons::kButtonRight,
112 PDButtons::kButtonUp,
113 PDButtons::kButtonDown,
114 PDButtons::kButtonB,
115 PDButtons::kButtonA,
116 ];
117 ALL[..].into_iter()
118 .filter(move |possible| (self.0 & possible.0) != 0)
119 }
120}
121
122pub trait PDButtonsIter<'t> {
123 type Item;
124 type Iter: Iterator<Item = Self::Item>;
125
126 fn iter(&'t self) -> Self::Iter;
127}
128
129impl<'t> PDButtonsIter<'t> for PDButtons {
130 type Item = &'static PDButtons;
131 type Iter = impl Iterator<Item = Self::Item> + 't;
132
133 fn iter(&'t self) -> Self::Iter {
134 static ALL: [PDButtons; 6] = [
135 PDButtons::kButtonLeft,
136 PDButtons::kButtonRight,
137 PDButtons::kButtonUp,
138 PDButtons::kButtonDown,
139 PDButtons::kButtonB,
140 PDButtons::kButtonA,
141 ];
142 ALL[..].into_iter()
143 .filter(move |possible| self.contains_ref(possible))
144 }
145}
146
147
148pub trait PDButtonsFmt: for<'t> PDButtonsIter<'t> {
149 fn display(&self) -> PDButtonsDisplay<'_>;
150}
151
152impl PDButtonsFmt for PDButtons {
153 fn display(&self) -> PDButtonsDisplay<'_> { PDButtonsDisplay(self) }
154}
155
156pub struct PDButtonsDisplay<'t>(&'t PDButtons);
157
158impl<'t> Debug for PDButtonsDisplay<'t> {
159 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
160 let mut fmt = f.debug_tuple(&format!("PDButtons[{:08b}]", self.0.0));
161 let iter = self.0.iter().singles();
162 for item in iter {
163 fmt.field(&item);
164 }
165 fmt.finish()
166 }
167}
168
169impl<'t> Display for PDButtonsDisplay<'t> {
170 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
171 write!(f, "(")?;
172 let mut iter = self.0.iter().singles();
173 if let Some(first) = iter.next() {
174 write!(f, "{first:?}")?;
175 }
176 for item in iter {
177 write!(f, ", {:?}", item)?;
178 }
179 write!(f, ")")
180 }
181}
182
183
184#[derive(PartialEq, Eq, Clone, Copy, Debug)]
186pub enum Button {
187 Left,
188 Right,
189 Up,
190 Down,
191 B,
192 A,
193}
194
195impl Into<PDButtons> for Button {
196 fn into(self) -> PDButtons {
197 match self {
198 Button::Left => PDButtons::Left(),
199 Button::Right => PDButtons::Right(),
200 Button::Up => PDButtons::Up(),
201 Button::Down => PDButtons::Down(),
202 Button::B => PDButtons::B(),
203 Button::A => PDButtons::A(),
204 }
205 }
206}
207
208impl PartialEq<PDButtons> for Button {
209 fn eq(&self, other: &PDButtons) -> bool {
210 match self {
211 Button::Left => other.contains_ref(&PDButtons::Left()),
212 Button::Right => other.contains_ref(&PDButtons::Right()),
213 Button::Up => other.contains_ref(&PDButtons::Up()),
214 Button::Down => other.contains_ref(&PDButtons::Down()),
215 Button::B => other.contains_ref(&PDButtons::B()),
216 Button::A => other.contains_ref(&PDButtons::A()),
217 }
218 }
219}
220
221
222pub trait IterSingleButtons {
223 type Iter: Iterator<Item = Button>;
224
225 fn singles(self) -> Self::Iter;
227}
228
229impl<T: Iterator<Item = <PDButtons as PDButtonsIntoIter>::Item>> IterSingleButtons for T {
230 type Iter = impl Iterator<Item = Button>;
231
232 fn singles(self) -> Self::Iter {
233 static ALL: [Button; 6] = [
234 Button::Left,
235 Button::Right,
236 Button::Up,
237 Button::Down,
238 Button::B,
239 Button::A,
240 ];
241 self.flat_map(|buttons| ALL.into_iter().filter(move |single| single == buttons))
242 }
243}