use once_cell::sync::Lazy;
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::core::base::HasStaticName;
pub trait HasIsDominant {
fn is_dominant(&self) -> bool;
}
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u8)]
pub enum Degree {
Seven,
Nine,
Eleven,
Thirteen,
}
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u8)]
pub enum Modifier {
Minor,
Flat5,
Augmented5,
Major7,
Dominant(Degree),
Flat9,
Sharp9,
Sharp11,
Diminished,
}
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug, Ord, PartialOrd)]
#[repr(u8)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "wasm", wasm_bindgen(js_name = KordExtension))]
pub enum Extension {
Sus2,
Sus4,
Flat11,
Flat13,
Sharp13,
Add2,
Add4,
Add6,
Add9,
Add11,
Add13,
}
impl HasIsDominant for Modifier {
fn is_dominant(&self) -> bool {
matches!(self, Modifier::Dominant(_))
}
}
impl HasStaticName for Degree {
#[coverage(off)]
fn static_name(&self) -> &'static str {
match self {
Degree::Seven => "7",
Degree::Nine => "9",
Degree::Eleven => "11",
Degree::Thirteen => "13",
}
}
}
impl HasStaticName for Modifier {
#[coverage(off)]
fn static_name(&self) -> &'static str {
match self {
Modifier::Minor => "m",
Modifier::Flat5 => "♭5",
Modifier::Augmented5 => "+",
Modifier::Major7 => "maj7",
Modifier::Dominant(dominant) => dominant.static_name(),
Modifier::Flat9 => "♭9",
Modifier::Sharp9 => "♯9",
Modifier::Sharp11 => "♯11",
Modifier::Diminished => "°",
}
}
}
impl HasStaticName for Extension {
#[coverage(off)]
fn static_name(&self) -> &'static str {
match self {
Extension::Sus2 => "sus2",
Extension::Sus4 => "sus4",
Extension::Flat11 => "♭11",
Extension::Flat13 => "♭13",
Extension::Sharp13 => "♯13",
Extension::Add2 => "add2",
Extension::Add4 => "add4",
Extension::Add6 => "add6",
Extension::Add9 => "add9",
Extension::Add11 => "add11",
Extension::Add13 => "add13",
}
}
}
pub fn known_modifier_sets() -> &'static [Vec<Modifier>] {
KNOWN_MODIFIER_SETS.as_ref()
}
pub fn one_off_modifier_sets() -> &'static [Vec<Modifier>] {
ONE_OFF_MODIFIER_SETS.as_ref()
}
pub fn likely_extension_sets() -> &'static [Vec<Extension>] {
LIKELY_EXTENSION_SETS.as_ref()
}
static KNOWN_MODIFIER_SETS: Lazy<[Vec<Modifier>; 35]> = Lazy::new(|| {
[
vec![],
vec![Modifier::Minor],
vec![Modifier::Major7],
vec![Modifier::Dominant(Degree::Seven)],
vec![Modifier::Dominant(Degree::Nine)],
vec![Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Dominant(Degree::Thirteen)],
vec![Modifier::Minor, Modifier::Major7],
vec![Modifier::Minor, Modifier::Dominant(Degree::Seven)],
vec![Modifier::Minor, Modifier::Dominant(Degree::Nine)],
vec![Modifier::Minor, Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Minor, Modifier::Dominant(Degree::Thirteen)],
vec![Modifier::Sharp11, Modifier::Dominant(Degree::Seven)],
vec![Modifier::Sharp11, Modifier::Dominant(Degree::Nine)],
vec![Modifier::Sharp11, Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Sharp11, Modifier::Dominant(Degree::Thirteen)],
vec![Modifier::Augmented5],
vec![Modifier::Augmented5, Modifier::Major7],
vec![Modifier::Augmented5, Modifier::Dominant(Degree::Seven)],
vec![Modifier::Augmented5, Modifier::Dominant(Degree::Nine)],
vec![Modifier::Augmented5, Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Augmented5, Modifier::Dominant(Degree::Thirteen)],
vec![Modifier::Minor, Modifier::Flat5, Modifier::Dominant(Degree::Seven)],
vec![Modifier::Minor, Modifier::Flat5, Modifier::Dominant(Degree::Nine)],
vec![Modifier::Minor, Modifier::Flat5, Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Minor, Modifier::Flat5, Modifier::Dominant(Degree::Thirteen)],
vec![Modifier::Diminished],
vec![Modifier::Flat9, Modifier::Dominant(Degree::Seven)],
vec![Modifier::Flat9, Modifier::Dominant(Degree::Nine)],
vec![Modifier::Flat9, Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Flat9, Modifier::Dominant(Degree::Thirteen)],
vec![Modifier::Sharp9, Modifier::Dominant(Degree::Seven)],
vec![Modifier::Sharp9, Modifier::Dominant(Degree::Nine)],
vec![Modifier::Sharp9, Modifier::Dominant(Degree::Eleven)],
vec![Modifier::Sharp9, Modifier::Dominant(Degree::Thirteen)],
]
});
static ONE_OFF_MODIFIER_SETS: Lazy<[Vec<Modifier>; 6]> = Lazy::new(|| {
[
vec![],
vec![Modifier::Sharp11],
vec![Modifier::Augmented5],
vec![Modifier::Flat5],
vec![Modifier::Flat9],
vec![Modifier::Sharp9],
]
});
static LIKELY_EXTENSION_SETS: Lazy<[Vec<Extension>; 12]> = Lazy::new(|| {
[
vec![],
vec![Extension::Sus2],
vec![Extension::Sus4],
vec![Extension::Add2],
vec![Extension::Add4],
vec![Extension::Add6],
vec![Extension::Add9],
vec![Extension::Add11],
vec![Extension::Add13],
vec![Extension::Flat11],
vec![Extension::Flat13],
vec![Extension::Sharp13],
]
});