use core::fmt::Debug;
use core::fmt::Display;
use core::ops::BitAnd;
use sys::ffi::PDButtons;
#[const_trait]
pub trait PDButtonsExt: Sized + BitAnd<Self> {
#![allow(non_snake_case)]
fn contains(&self, other: Self) -> bool;
fn contains_ref(&self, other: &Self) -> bool;
fn any(&self) -> bool;
fn is_empty(&self) -> bool;
#[inline(always)]
fn left(&self) -> bool { self.contains(Self::Left()) }
#[inline(always)]
fn right(&self) -> bool { self.contains(Self::Right()) }
#[inline(always)]
fn up(&self) -> bool { self.contains(Self::Up()) }
#[inline(always)]
fn down(&self) -> bool { self.contains(Self::Down()) }
#[inline(always)]
fn b(&self) -> bool { self.contains(Self::B()) }
#[inline(always)]
fn a(&self) -> bool { self.contains(Self::A()) }
fn Left() -> Self;
fn Right() -> Self;
fn Up() -> Self;
fn Down() -> Self;
fn B() -> Self;
fn A() -> Self;
}
impl const PDButtonsExt for PDButtons {
#![allow(non_snake_case)]
#[inline(always)]
fn contains(&self, other: Self) -> bool { (self.0 & other.0) != 0 }
#[inline(always)]
fn contains_ref(&self, other: &Self) -> bool { (self.0 & other.0) != 0 }
#[inline(always)]
fn any(&self) -> bool { self.0 > 0 }
#[inline(always)]
fn is_empty(&self) -> bool { self.0 == 0 }
#[inline(always)]
fn Left() -> Self { Self::kButtonLeft }
#[inline(always)]
fn Right() -> Self { Self::kButtonRight }
#[inline(always)]
fn Up() -> Self { Self::kButtonUp }
#[inline(always)]
fn Down() -> Self { Self::kButtonDown }
#[inline(always)]
fn B() -> Self { Self::kButtonB }
#[inline(always)]
fn A() -> Self { Self::kButtonA }
}
pub trait PDButtonsIntoIter {
type Item;
type IntoIter: Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter;
}
impl PDButtonsIntoIter for PDButtons {
type Item = &'static Self;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter {
static ALL: [PDButtons; 6] = [
PDButtons::kButtonLeft,
PDButtons::kButtonRight,
PDButtons::kButtonUp,
PDButtons::kButtonDown,
PDButtons::kButtonB,
PDButtons::kButtonA,
];
ALL[..].into_iter()
.filter(move |possible| (self.0 & possible.0) != 0)
}
}
pub trait PDButtonsIter<'t> {
type Item;
type Iter: Iterator<Item = Self::Item>;
fn iter(&'t self) -> Self::Iter;
}
impl<'t> PDButtonsIter<'t> for PDButtons {
type Item = &'static PDButtons;
type Iter = impl Iterator<Item = Self::Item> + 't;
fn iter(&'t self) -> Self::Iter {
static ALL: [PDButtons; 6] = [
PDButtons::kButtonLeft,
PDButtons::kButtonRight,
PDButtons::kButtonUp,
PDButtons::kButtonDown,
PDButtons::kButtonB,
PDButtons::kButtonA,
];
ALL[..].into_iter()
.filter(move |possible| self.contains_ref(possible))
}
}
pub trait PDButtonsFmt: for<'t> PDButtonsIter<'t> {
fn display(&self) -> PDButtonsDisplay<'_>;
}
impl PDButtonsFmt for PDButtons {
fn display(&self) -> PDButtonsDisplay<'_> { PDButtonsDisplay(self) }
}
pub struct PDButtonsDisplay<'t>(&'t PDButtons);
impl<'t> Debug for PDButtonsDisplay<'t> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut fmt = f.debug_tuple(&format!("PDButtons[{:08b}]", self.0 .0));
let iter = self.0.iter().singles();
for item in iter {
fmt.field(&item);
}
fmt.finish()
}
}
impl<'t> Display for PDButtonsDisplay<'t> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "(")?;
let mut iter = self.0.iter().singles();
if let Some(first) = iter.next() {
write!(f, "{first:?}")?;
}
for item in iter {
write!(f, ", {:?}", item)?;
}
write!(f, ")")
}
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Button {
Left,
Right,
Up,
Down,
B,
A,
}
impl Into<PDButtons> for Button {
fn into(self) -> PDButtons {
match self {
Button::Left => PDButtons::Left(),
Button::Right => PDButtons::Right(),
Button::Up => PDButtons::Up(),
Button::Down => PDButtons::Down(),
Button::B => PDButtons::B(),
Button::A => PDButtons::A(),
}
}
}
impl PartialEq<PDButtons> for Button {
fn eq(&self, other: &PDButtons) -> bool {
match self {
Button::Left => other.contains_ref(&PDButtons::Left()),
Button::Right => other.contains_ref(&PDButtons::Right()),
Button::Up => other.contains_ref(&PDButtons::Up()),
Button::Down => other.contains_ref(&PDButtons::Down()),
Button::B => other.contains_ref(&PDButtons::B()),
Button::A => other.contains_ref(&PDButtons::A()),
}
}
}
pub trait IterSingleButtons {
type Iter: Iterator<Item = Button>;
fn singles(self) -> Self::Iter;
}
impl<T: Iterator<Item = <PDButtons as PDButtonsIntoIter>::Item>> IterSingleButtons for T {
type Iter = impl Iterator<Item = Button>;
fn singles(self) -> Self::Iter {
static ALL: [Button; 6] = [
Button::Left,
Button::Right,
Button::Up,
Button::Down,
Button::B,
Button::A,
];
self.flat_map(|buttons| ALL.into_iter().filter(move |single| single == buttons))
}
}