use std::ops::Deref;
use std::{
fmt::{Debug, Display},
ops::BitOr,
};
use num_traits::{PrimInt, Zero};
use crate::enums::{
buttons::{ControllerInput, EngineInput},
general::Flags,
};
pub trait BitFlags: Into<Self::Other> + Copy {
type Other: PrimInt;
#[inline]
fn contains(self, other: Self::Other) -> bool {
Into::<Self::Other>::into(self) & other == other
}
#[inline]
fn contained_by(self, other: Self::Other) -> bool {
let temp = Into::<Self::Other>::into(self);
temp & other == temp
}
#[inline]
fn intersects(self, other: Self::Other) -> bool {
Into::<Self::Other>::into(self) & other != Self::Other::zero()
}
#[inline]
fn count_ones(self) -> u32 {
Into::<Self::Other>::into(self).count_ones()
}
#[inline]
fn count_zeroes(self) -> u32 {
Into::<Self::Other>::into(self).count_zeros()
}
}
pub trait Buttons {}
impl Debug for EngineInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
["EngineInput{", &self.pretty_print(), "}"].join("")
)
}
}
impl Display for EngineInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.pretty_print())
}
}
impl From<u32> for EngineInput {
fn from(val: u32) -> Self {
assert_eq!(
val & 0x7F00_E080,
0,
"Invalid bits, cannot construct EngineBtn value from {val}"
);
Self::Raw(val)
}
}
impl From<EngineInput> for u32 {
#[inline]
fn from(val: EngineInput) -> u32 {
use EngineInput::*;
match val {
Raw(x) => x,
_ => unsafe { *(&val as *const EngineInput as *const u32) }
}
}
}
impl Buttons for EngineInput {}
impl BitFlags for EngineInput {
type Other = u32;
}
impl BitOr for EngineInput {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self::Output {
EngineInput::Raw(*self | *rhs)
}
}
impl Deref for EngineInput {
type Target = u32;
#[inline]
fn deref(&self) -> &u32 {
use EngineInput as EI;
match self {
EI::Raw(x) => x,
_ => unsafe { &(*(self as *const EngineInput as *const u32)) },
}
}
}
impl EngineInput {
#[inline]
fn _to_raw(&mut self) {
*self = Self::Raw(u32::from(*self));
}
fn pretty_print(&self) -> String {
if **self == 0 {
return "None".to_string();
}
let mut result: Vec<&str> = Vec::new();
if self.contains(*Self::DPAD_LEFT) {
result.push("DPAD_LEFT");
}
if self.contains(*Self::DPAD_RIGHT) {
result.push("DPAD_RIGHT");
}
if self.contains(*Self::DPAD_DOWN) {
result.push("DPAD_DOWN");
}
if self.contains(*Self::DPAD_UP) {
result.push("DPAD_UP");
}
if self.contains(*Self::Z) {
result.push("Z");
}
if self.contains(*Self::R) {
result.push("R");
}
if self.contains(*Self::L) {
result.push("L");
}
if self.contains(*Self::A) {
result.push("A");
}
if self.contains(*Self::B) {
result.push("B");
}
if self.contains(*Self::X) {
result.push("X");
}
if self.contains(*Self::Y) {
result.push("Y");
}
if self.contains(*Self::START) {
result.push("START");
}
if self.contains(*Self::JOYSTICK_UP) {
result.push("JOYSTICK_UP");
}
if self.contains(*Self::JOYSTICK_DOWN) {
result.push("JOYSTICK_DOWN");
}
if self.contains(*Self::JOYSTICK_LEFT) {
result.push("JOYSTICK_LEFT");
}
if self.contains(*Self::JOYSTICK_RIGHT) {
result.push("JOYSTICK_RIGHT");
}
if self.contains(*Self::CSTICK_UP) {
result.push("CSTICK_UP");
}
if self.contains(*Self::CSTICK_DOWN) {
result.push("CSTICK_DOWN");
}
if self.contains(*Self::CSTICK_LEFT) {
result.push("CSTICK_LEFT");
}
if self.contains(*Self::CSTICK_RIGHT) {
result.push("CSTICK_RIGHT");
}
if self.contains(*Self::ANY_TRIGGER) {
result.push("ANY_TRIGGER");
}
result.join("|")
}
}
impl From<u16> for ControllerInput {
#[inline]
fn from(val: u16) -> Self {
Self::Raw(val)
}
}
impl From<ControllerInput> for u16 {
#[inline]
fn from(val: ControllerInput) -> Self {
use ControllerInput as CI;
match val {
CI::Raw(x) => x,
_ => unsafe { *(&val as *const ControllerInput as *const u16) },
}
}
}
impl Buttons for ControllerInput {}
impl BitFlags for ControllerInput {
type Other = u16;
}
impl BitOr for ControllerInput {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self::Output {
ControllerInput::Raw(*self | *rhs)
}
}
impl Deref for ControllerInput {
type Target = u16;
#[inline]
fn deref(&self) -> &u16 {
use ControllerInput as CI;
match self {
CI::Raw(x) => x,
_ => unsafe { &(*(self as *const ControllerInput as *const u16)) },
}
}
}
impl ControllerInput {
fn pretty_print(&self) -> String {
if **self == 0 {
return "None".to_string();
}
let mut result: Vec<&str> = Vec::new();
if self.contains(Self::DPAD_LEFT.into()) {
result.push("DPAD_LEFT");
}
if self.contains(Self::DPAD_RIGHT.into()) {
result.push("DPAD_RIGHT");
}
if self.contains(Self::DPAD_DOWN.into()) {
result.push("DPAD_DOWN");
}
if self.contains(Self::DPAD_UP.into()) {
result.push("DPAD_UP");
}
if self.contains(Self::Z.into()) {
result.push("Z");
}
if self.contains(Self::R.into()) {
result.push("R");
}
if self.contains(Self::L.into()) {
result.push("L");
}
if self.contains(Self::A.into()) {
result.push("A");
}
if self.contains(Self::B.into()) {
result.push("B");
}
if self.contains(Self::X.into()) {
result.push("X");
}
if self.contains(Self::Y.into()) {
result.push("Y");
}
if self.contains(Self::START.into()) {
result.push("START");
}
result.join("|")
}
}
impl Debug for ControllerInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
["ControllerInput{", &self.pretty_print(), "}"].join("")
)
}
}
impl Display for ControllerInput {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.pretty_print())
}
}
impl From<u64> for Flags {
#[inline]
fn from(val: u64) -> Self {
assert_eq!(
val & 0xFFFF_FF00_0000_0000,
0,
"Cannot construct flags, value '{val}' contains invalid bits"
);
Self::Raw(val)
}
}
impl From<Flags> for u64 {
#[inline]
fn from(val: Flags) -> Self {
match val {
Flags::Raw(x) => x,
_ => unsafe { *(&val as *const Flags as *const u64) },
}
}
}
impl BitFlags for Flags {
type Other = u64;
}
impl BitOr for Flags {
type Output = Self;
#[inline]
fn bitor(self, rhs: Self) -> Self::Output {
Flags::Raw(*self | *rhs)
}
}
impl Deref for Flags {
type Target = u64;
#[inline]
fn deref(&self) -> &u64 {
match self {
Flags::Raw(x) => x,
_ => unsafe { &(*(self as *const Flags as *const u64)) },
}
}
}
impl Flags {
fn pretty_print(&self) -> String {
if **self == 0 {
return "None".to_string();
}
let mut result: Vec<&str> = Vec::new();
if self.contains(Self::ABSORB_BUBBLE.into()) {
result.push("ABSORB_BUBBLE");
}
if self.contains(Self::REFLECT_BUBBLE.into()) {
result.push("REFLECT_BUBBLE");
}
if self.contains(Self::REFLECT_NO_STEAL.into()) {
result.push("REFLECT_NO_STEAL");
}
if self.contains(Self::ALLOW_INTERRUPT.into()) {
result.push("ALLOW_INTERRUPT")
}
if self.contains(Self::SUBACTION_INVULN.into()) {
result.push("SUBACTION_INVULN");
}
if self.contains(Self::FASTFALL.into()) {
result.push("FASTFALL");
}
if self.contains(Self::DEFENDER_HITLAG.into()) {
result.push("DEFENDER_HITLAG");
}
if self.contains(Self::HITLAG.into()) {
result.push("HITLAG");
}
if self.contains(Self::GRAB_HOLD.into()) {
result.push("GRAB_HOLD");
}
if self.contains(Self::GUARD_BUBBLE.into()) {
result.push("GUARD_BUBBLE");
}
if self.contains(Self::SHIELDING.into()) {
result.push("SHIELDING");
}
if self.contains(Self::HITSTUN.into()) {
result.push("HITSTUN");
}
if self.contains(Self::HITBOX_TOUCHING_SHIELD.into()) {
result.push("HITBOX_TOUCHING_SHIELD");
}
if self.contains(Self::POWERSHIELD_BUBBLE.into()) {
result.push("POWERSHIELD_BUBBLE");
}
if self.contains(Self::CLOAKING_DEVICE.into()) {
result.push("CLOAKING_DEVICE");
}
if self.contains(Self::FOLLOWER.into()) {
result.push("FOLLOWER");
}
if self.contains(Self::INACTIVE.into()) {
result.push("INACTIVE");
}
if self.contains(Self::DEAD.into()) {
result.push("DEAD");
}
if self.contains(Self::OFFSCREEN.into()) {
result.push("OFFSCREEN");
}
if self.contains(Self::BIT_1_1.into()) {
result.push("BIT_1_1");
}
if self.contains(Self::BIT_1_3.into()) {
result.push("BIT_1_3");
}
if self.contains(Self::BIT_1_6.into()) {
result.push("BIT_1_6");
}
if self.contains(Self::BIT_1_7.into()) {
result.push("BIT_1_7");
}
if self.contains(Self::BIT_2_2.into()) {
result.push("BIT_2_2");
}
if self.contains(Self::BIT_2_7.into()) {
result.push("BIT_2_7");
}
if self.contains(Self::BIT_2_8.into()) {
result.push("BIT_2_8");
}
if self.contains(Self::BIT_3_1.into()) {
result.push("BIT_3_1");
}
if self.contains(Self::BIT_3_2.into()) {
result.push("BIT_3_2");
}
if self.contains(Self::BIT_3_4.into()) {
result.push("BIT_3_4");
}
if self.contains(Self::BIT_3_5.into()) {
result.push("BIT_3_5");
}
if self.contains(Self::BIT_3_6.into()) {
result.push("BIT_3_6");
}
if self.contains(Self::BIT_3_7.into()) {
result.push("BIT_3_7");
}
if self.contains(Self::BIT_4_1.into()) {
result.push("BIT_4_1");
}
if self.contains(Self::BIT_4_4.into()) {
result.push("BIT_4_4");
}
if self.contains(Self::BIT_4_5.into()) {
result.push("BIT_4_5");
}
if self.contains(Self::BIT_4_7.into()) {
result.push("BIT_4_7");
}
if self.contains(Self::BIT_4_8.into()) {
result.push("BIT_4_8");
}
if self.contains(Self::BIT_5_1.into()) {
result.push("BIT_5_1");
}
if self.contains(Self::BIT_5_3.into()) {
result.push("BIT_5_3");
}
if self.contains(Self::BIT_5_6.into()) {
result.push("BIT_5_6");
}
result.join("|")
}
}
impl Debug for Flags {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", ["Flags{", &self.pretty_print(), "}"].join(""))
}
}
impl Display for Flags {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.pretty_print())
}
}