playdate_controls/
buttons.rs

1use 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	/// Contains `other` button.
11	///
12	/// Note, `other` can contains one or many buttons.
13	/// In case of there's many buttons, returns `true` if
14	/// at least one button of `other` is contained in this.
15	fn contains(&self, other: Self) -> bool;
16
17	/// Contains `other` button.
18	/// Same as [`Self::contains`] but not taking ownership of `other`.
19	fn contains_ref(&self, other: &Self) -> bool;
20
21	/// Contains any buttons, opposite of [`Self::is_empty`].
22	fn any(&self) -> bool;
23
24	/// There's no buttons
25	fn is_empty(&self) -> bool;
26
27	#[inline(always)]
28	/// Contains `left` button.
29	fn left(&self) -> bool { self.contains(Self::Left()) }
30
31	#[inline(always)]
32	/// Contains `right` button.
33	fn right(&self) -> bool { self.contains(Self::Right()) }
34
35	#[inline(always)]
36	/// Contains `up` button.
37	fn up(&self) -> bool { self.contains(Self::Up()) }
38
39	#[inline(always)]
40	/// Contains `down` button.
41	fn down(&self) -> bool { self.contains(Self::Down()) }
42
43	#[inline(always)]
44	/// Contains `b` button.
45	fn b(&self) -> bool { self.contains(Self::B()) }
46
47	#[inline(always)]
48	/// Contains `a` button.
49	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/// Represents single button of [`PDButtons`].
185#[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	/// Map each [`PDButtons`] to many [`Button`]s.
226	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}