#![allow(clippy::cast_possible_wrap)]
use Match::*;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct Pckn {
pub port_index: Match<u16>,
pub channel: Match<u16>,
pub key: Match<u16>,
pub note_id: Match<u32>,
}
impl Pckn {
pub fn new(
port: impl Into<Match<u16>>,
channel: impl Into<Match<u16>>,
key: impl Into<Match<u16>>,
note_id: impl Into<Match<u32>>,
) -> Self {
Self {
port_index: port.into(),
channel: channel.into(),
key: key.into(),
note_id: note_id.into(),
}
}
#[inline]
pub const fn match_all() -> Self {
Self {
port_index: All,
channel: All,
key: All,
note_id: All,
}
}
pub const fn matches_all(&self) -> bool {
self.port_index.is_all()
&& self.channel.is_all()
&& self.key.is_all()
&& self.note_id.is_all()
}
pub fn matches(&self, other: &Pckn) -> bool {
self.port_index.matches(other.port_index)
&& self.channel.matches(other.channel)
&& self.key.matches(other.key)
&& self.note_id.matches(other.note_id)
}
#[inline]
pub const fn from_raw(port: i16, channel: i16, key: i16, note_id: i32) -> Self {
Self {
port_index: Match::<u16>::from_raw(port),
channel: Match::<u16>::from_raw(channel),
key: Match::<u16>::from_raw(key),
note_id: Match::<u32>::from_raw(note_id),
}
}
#[inline]
pub const fn raw_port_index(&self) -> i16 {
match self.port_index {
Specific(p) => p as i16,
All => -1,
}
}
#[inline]
pub const fn raw_channel(&self) -> i16 {
match self.channel {
Specific(p) => p as i16,
All => -1,
}
}
#[inline]
pub const fn raw_key(&self) -> i16 {
match self.key {
Specific(p) => p as i16,
All => -1,
}
}
#[inline]
pub const fn raw_note_id(&self) -> i32 {
match self.note_id {
Specific(p) => p as i32,
All => -1,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum Match<T> {
Specific(T),
All,
}
impl<T> Match<T> {
pub const fn as_specific(&self) -> Option<&T> {
match self {
Specific(v) => Some(v),
All => None,
}
}
pub fn into_specific(self) -> Option<T> {
match self {
Specific(v) => Some(v),
All => None,
}
}
#[inline]
pub const fn is_all(&self) -> bool {
matches!(self, All)
}
#[inline]
pub const fn is_specific(&self) -> bool {
matches!(self, Specific(_))
}
}
impl<T> From<T> for Match<T> {
#[inline]
fn from(value: T) -> Self {
Specific(value)
}
}
impl From<u8> for Match<u16> {
#[inline]
fn from(value: u8) -> Self {
Specific(value.into())
}
}
impl From<u8> for Match<u32> {
#[inline]
fn from(value: u8) -> Self {
Specific(value.into())
}
}
impl From<u16> for Match<u32> {
#[inline]
fn from(value: u16) -> Self {
Specific(value.into())
}
}
impl From<ClapId> for Match<u32> {
#[inline]
fn from(value: ClapId) -> Self {
Specific(value.get())
}
}
impl<T: PartialEq> Match<T> {
#[inline]
pub fn matches(&self, other: impl Into<Match<T>>) -> bool {
match (self, other.into()) {
(Specific(x), Specific(y)) => *x == y,
_ => true,
}
}
}
impl Match<u16> {
#[inline]
pub const fn from_raw(raw: i16) -> Self {
if raw < 0 {
All
} else {
Specific(raw.unsigned_abs())
}
}
#[inline]
pub const fn to_raw(&self) -> i16 {
match self {
Specific(raw) => *raw as i16,
All => -1,
}
}
}
impl Match<u32> {
#[inline]
pub const fn from_raw(raw: i32) -> Self {
if raw < 0 {
All
} else {
Specific(raw.unsigned_abs())
}
}
#[inline]
pub const fn to_raw(&self) -> i32 {
match self {
Specific(raw) => *raw as i32,
All => -1,
}
}
}
macro_rules! impl_event_pckn {
(self.$($raw_event:ident).*) => {
#[inline]
pub const fn pckn(&self) -> crate::events::Pckn {
Pckn::from_raw(
self.$($raw_event).*.port_index,
self.$($raw_event).*.channel,
self.$($raw_event).*.key,
self.$($raw_event).*.note_id,
)
}
#[inline]
pub const fn set_pckn(&mut self, pckn: crate::events::Pckn) {
self.$($raw_event).*.port_index = pckn.raw_port_index();
self.$($raw_event).*.channel = pckn.raw_channel();
self.$($raw_event).*.key = pckn.raw_key();
self.$($raw_event).*.note_id = pckn.raw_note_id();
}
#[inline]
pub const fn with_pckn(mut self, pckn: crate::events::Pckn) -> Self {
self.set_pckn(pckn);
self
}
#[inline]
pub const fn port_index(&self) -> Match<u16> {
Match::<u16>::from_raw(self.$($raw_event).*.port_index)
}
#[inline]
pub const fn set_port_index(&mut self, port_index: Match<u16>) {
self.$($raw_event).*.port_index = port_index.to_raw()
}
#[inline]
pub const fn with_port_index(mut self, port_index: Match<u16>) -> Self {
self.$($raw_event).*.port_index = port_index.to_raw();
self
}
#[inline]
pub const fn channel(&self) -> Match<u16> {
Match::<u16>::from_raw(self.$($raw_event).*.channel)
}
#[inline]
pub const fn set_channel(&mut self, channel: Match<u16>) {
self.$($raw_event).*.channel = channel.to_raw();
}
#[inline]
pub const fn with_channel(mut self, channel: Match<u16>) -> Self {
self.$($raw_event).*.channel = channel.to_raw();
self
}
#[inline]
pub const fn key(&self) -> Match<u16> {
Match::<u16>::from_raw(self.$($raw_event).*.key)
}
#[inline]
pub const fn set_key(&mut self, key: Match<u16>) {
self.$($raw_event).*.key = key.to_raw();
}
#[inline]
pub const fn with_key(mut self, key: Match<u16>) -> Self {
self.$($raw_event).*.key = key.to_raw();
self
}
#[inline]
pub const fn note_id(&self) -> Match<u32> {
Match::<u32>::from_raw(self.$($raw_event).*.note_id)
}
#[inline]
pub const fn set_note_id(&mut self, note_id: Match<u32>) {
self.$($raw_event).*.note_id = note_id.to_raw();
}
#[inline]
pub const fn with_note_id(mut self, note_id: Match<u32>) -> Self {
self.$($raw_event).*.note_id = note_id.to_raw();
self
}
};
}
use crate::utils::ClapId;
pub(crate) use impl_event_pckn;