use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Hash)]
pub enum FeatureCategory {
Node(NodeKind),
Feat(FeatKind),
Supr(SupraKind),
}
impl fmt::Display for FeatureCategory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FeatureCategory::Node(x) => write!(f, "{x}"),
FeatureCategory::Feat(x) => write!(f, "{x}"),
FeatureCategory::Supr(x) => write!(f, "{x}"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize, Hash)]
pub enum NodeKind {
Root,
Manner,
Laryngeal,
Place,
Labial,
Coronal,
Dorsal,
Pharyngeal
}
impl NodeKind {
pub(crate) const fn count() -> usize { 8 }
pub(crate) fn from_usize(value: usize) -> Self {
debug_assert!(NodeKind::count() == 8);
use NodeKind::*;
match value {
0 => {debug_assert_eq!(value, Root as usize); Root}
1 => {debug_assert_eq!(value, Manner as usize); Manner}
2 => {debug_assert_eq!(value, Laryngeal as usize); Laryngeal}
3 => {debug_assert_eq!(value, Place as usize); Place}
4 => {debug_assert_eq!(value, Labial as usize); Labial}
5 => {debug_assert_eq!(value, Coronal as usize); Coronal}
6 => {debug_assert_eq!(value, Dorsal as usize); Dorsal}
7 => {debug_assert_eq!(value, Pharyngeal as usize); Pharyngeal},
_ => unreachable!("\nOut of Range converting `{value}` to `NodeType`(max: 7) \nThis is a bug!\n")
}
}
pub(crate) fn as_str(&self) -> &'static str {
match self {
NodeKind::Root => "root",
NodeKind::Manner => "manner",
NodeKind::Laryngeal => "laryngeal",
NodeKind::Place => "place",
NodeKind::Labial => "labial",
NodeKind::Coronal => "coronal",
NodeKind::Dorsal => "dorsal",
NodeKind::Pharyngeal => "pharyngeal",
}
}
}
impl fmt::Display for NodeKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Root => write!(f, "RUT"),
Self::Manner => write!(f, "MAN"),
Self::Laryngeal => write!(f, "LAR"),
Self::Place => write!(f, "PLC"),
Self::Labial => write!(f, "LAB"),
Self::Coronal => write!(f, "COR"),
Self::Dorsal => write!(f, "DOR"),
Self::Pharyngeal => write!(f, "PHR")
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Hash)]
pub enum FeatKind {
Consonantal, Sonorant, Syllabic,
Continuant, Approximant, Lateral, Nasal, DelayedRelease, Strident, Rhotic, Click,
Voice, SpreadGlottis, ConstrGlottis,
Labiodental, Round,
Anterior, Distributed,
Front, Back, High, Low, Tense, Reduced,
AdvancedTongueRoot, RetractedTongueRoot,
}
impl fmt::Display for FeatKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl FeatKind {
pub(crate) const fn count() -> usize { 26 }
pub(crate) fn from_usize(value: usize) -> Self {
match value {
0 => Self::Consonantal,
1 => Self::Sonorant,
2 => Self::Syllabic,
3 => Self::Continuant,
4 => Self::Approximant,
5 => Self::Lateral,
6 => Self::Nasal,
7 => Self::DelayedRelease,
8 => Self::Strident,
9 => Self::Rhotic,
10 => Self::Click,
11 => Self::Voice,
12 => Self::SpreadGlottis,
13 => Self::ConstrGlottis,
14 => Self::Labiodental,
15 => Self::Round,
16 => Self::Anterior,
17 => Self::Distributed,
18 => Self::Front,
19 => Self::Back,
20 => Self::High,
21 => Self::Low,
22 => Self::Tense,
23 => Self::Reduced,
24 => Self::AdvancedTongueRoot,
25 => Self::RetractedTongueRoot,
_ => unreachable!("\nOut of Range Error converting `usize` to `FeatType`\nThis is a bug!\n")
}
}
pub(crate) fn as_str(&self) -> &'static str {
match self {
FeatKind::Consonantal => "consonantal",
FeatKind::Sonorant => "sonorant",
FeatKind::Syllabic => "syllabic",
FeatKind::Continuant => "continuant",
FeatKind::Approximant => "approx.",
FeatKind::Lateral => "lateral",
FeatKind::Nasal => "nasal",
FeatKind::DelayedRelease => "del.rel.",
FeatKind::Strident => "strident",
FeatKind::Rhotic => "rhotic",
FeatKind::Click => "click",
FeatKind::Voice => "voice",
FeatKind::SpreadGlottis => "s.g.",
FeatKind::ConstrGlottis => "c.g.",
FeatKind::Labiodental => "labiodental",
FeatKind::Round => "round",
FeatKind::Anterior => "anterior",
FeatKind::Distributed => "distributed",
FeatKind::Front => "front",
FeatKind::Back => "back",
FeatKind::High => "high",
FeatKind::Low => "low",
FeatKind::Tense => "tense",
FeatKind::Reduced => "reduced",
FeatKind::AdvancedTongueRoot => "atr",
FeatKind::RetractedTongueRoot => "rtr",
}
}
pub const fn as_node_mask(&self) -> (NodeKind, u8) {
match self {
Self::Consonantal => (NodeKind::Root, 0b100),
Self::Sonorant => (NodeKind::Root, 0b010),
Self::Syllabic => (NodeKind::Root, 0b001),
Self::Continuant => (NodeKind::Manner, 0b10000000),
Self::Approximant => (NodeKind::Manner, 0b01000000),
Self::Lateral => (NodeKind::Manner, 0b00100000),
Self::Nasal => (NodeKind::Manner, 0b00010000),
Self::DelayedRelease => (NodeKind::Manner, 0b00001000),
Self::Strident => (NodeKind::Manner, 0b00000100),
Self::Rhotic => (NodeKind::Manner, 0b00000010),
Self::Click => (NodeKind::Manner, 0b00000001),
Self::Voice => (NodeKind::Laryngeal, 0b100),
Self::SpreadGlottis => (NodeKind::Laryngeal, 0b010),
Self::ConstrGlottis => (NodeKind::Laryngeal, 0b001),
Self::Labiodental => (NodeKind::Labial, 0b10),
Self::Round => (NodeKind::Labial, 0b01),
Self::Anterior => (NodeKind::Coronal, 0b10),
Self::Distributed => (NodeKind::Coronal, 0b01),
Self::Front => (NodeKind::Dorsal, 0b100000),
Self::Back => (NodeKind::Dorsal, 0b010000),
Self::High => (NodeKind::Dorsal, 0b001000),
Self::Low => (NodeKind::Dorsal, 0b000100),
Self::Tense => (NodeKind::Dorsal, 0b000010),
Self::Reduced => (NodeKind::Dorsal, 0b000001),
Self::AdvancedTongueRoot => (NodeKind::Pharyngeal, 0b10),
Self::RetractedTongueRoot => (NodeKind::Pharyngeal, 0b01),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Hash)]
pub enum SupraKind {
Long, Overlong, Stress, SecStress, Tone, LengthPair, StressPair, }
impl fmt::Display for SupraKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SupraKind::Long => write!(f, "long"),
SupraKind::Overlong => write!(f, "overlng"),
SupraKind::Stress => write!(f, "str"),
SupraKind::SecStress => write!(f, "secstr"),
SupraKind::Tone => write!(f, "tone"),
SupraKind::LengthPair => write!(f, "lenpair"),
SupraKind::StressPair => write!(f, "strpair"),
}
}
}