use super::relation::{NonDefaultRelation, NormalRelation};
use crate::{
affix::AffixList,
category::{
AffixShortcut, Ca, Context, Function, NormalCaShortcut, ReferentialCaShortcut,
Specification, Vn,
},
specificity::{AsGeneral, TryAsSpecific},
};
use paste::paste;
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NonShortcutAdditions<AffixShortcutType, SpecificationType> {
pub relation: NormalRelation,
pub affix_shortcut: AffixShortcutType,
pub function: Function,
pub specification: SpecificationType,
pub context: Context,
pub slot_v_affixes: AffixList,
pub ca: Ca,
pub vn: Vn,
}
pub type NormalNonShortcutAdditions = NonShortcutAdditions<AffixShortcut, Specification>;
pub type ReferentialNonShortcutAdditions = NonShortcutAdditions<(), Specification>;
pub type AffixualNonShortcutAdditions = NonShortcutAdditions<(), ()>;
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct CnShortcutAdditions<AffixShortcutType, SpecificationType> {
pub relation: NonDefaultRelation,
pub affix_shortcut: AffixShortcutType,
pub function: Function,
pub specification: SpecificationType,
pub context: Context,
}
pub type NormalCnShortcutAdditions = CnShortcutAdditions<AffixShortcut, Specification>;
pub type ReferentialCnShortcutAdditions = CnShortcutAdditions<(), Specification>;
pub type AffixualCnShortcutAdditions = CnShortcutAdditions<(), ()>;
#[derive(Clone, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct CaShortcutAdditions<CaShortcutType> {
pub relation: NormalRelation,
pub slot_v_affixes: AffixList,
pub ca: CaShortcutType,
pub vn: Vn,
}
pub type NormalCaShortcutAdditions = CaShortcutAdditions<NormalCaShortcut>;
pub type ReferentialCaShortcutAdditions = CaShortcutAdditions<ReferentialCaShortcut>;
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum NormalFormativeAdditions {
Normal(NormalNonShortcutAdditions),
CnShortcut(NormalCnShortcutAdditions),
CaShortcut(NormalCaShortcutAdditions),
}
impl Default for NormalFormativeAdditions {
fn default() -> Self {
NormalFormativeAdditions::Normal(Default::default())
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum ReferentialFormativeAdditions {
Normal(ReferentialNonShortcutAdditions),
CnShortcut(ReferentialCnShortcutAdditions),
CaShortcut(ReferentialCaShortcutAdditions),
}
impl Default for ReferentialFormativeAdditions {
fn default() -> Self {
ReferentialFormativeAdditions::Normal(Default::default())
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum AffixualFormativeAdditions {
Normal(AffixualNonShortcutAdditions),
CnShortcut(AffixualCnShortcutAdditions),
}
impl Default for AffixualFormativeAdditions {
fn default() -> Self {
AffixualFormativeAdditions::Normal(Default::default())
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum ShortcutCheckedFormativeAdditions {
Normal(NormalNonShortcutAdditions),
CnShortcut(NormalCnShortcutAdditions),
CaShortcut(NormalCaShortcutAdditions),
}
macro_rules! as_general_impl {
(
$specific:ident,
$general:ident,
$($ca_name:ident)?,
$($slot_v_affixes_name:ident)?,
$($vn_name:ident)?,
$affix_shortcut_name:ident,
$specification_name:ident,
$affix_shortcut:tt,
$affix_shortcut_value:expr,
$specification:tt,
$specification_value:expr,
) => {
paste! {
#[allow(unused_parens)]
impl AsGeneral<$general> for $specific {
fn as_general(self) -> $general {
#[allow(unused_variables)]
let Self {
$affix_shortcut_name,
$($ca_name,)?
$($vn_name,)?
context,
function,
relation,
$($slot_v_affixes_name,)?
$specification_name,
} = self;
$general {
affix_shortcut: $affix_shortcut,
$($ca_name,)?
$($vn_name,)?
context,
function,
relation,
$($slot_v_affixes_name,)?
specification: $specification,
}
}
}
#[allow(unused_parens)]
impl From<$specific> for $general {
fn from(value: $specific) -> Self {
value.as_general()
}
}
#[allow(unused_parens)]
impl TryAsSpecific<$specific> for $general {
fn try_as_specific(self) -> Option<$specific> {
#[allow(unused_variables)]
if let $general {
$affix_shortcut_name: $affix_shortcut,
$($ca_name,)?
$($vn_name,)?
context,
function,
relation,
$($slot_v_affixes_name,)?
$specification_name: $specification,
} = self {
Some($specific {
$affix_shortcut_name: $affix_shortcut_value,
$($ca_name,)?
$($vn_name,)?
context,
function,
relation,
$($slot_v_affixes_name,)?
$specification_name: $specification_value,
})
} else {
None
}
}
}
}
};
}
as_general_impl!(
ReferentialNonShortcutAdditions, NormalNonShortcutAdditions, ca, slot_v_affixes, vn, affix_shortcut, specification, (AffixShortcut::None), (), (Specification::BSC), (Specification::BSC), );
as_general_impl!(
AffixualNonShortcutAdditions,
NormalNonShortcutAdditions,
ca,
slot_v_affixes,
vn,
affix_shortcut,
specification,
(AffixShortcut::None),
(),
(Specification::BSC),
(),
);
as_general_impl!(
ReferentialCnShortcutAdditions,
NormalCnShortcutAdditions,
,
,
,
affix_shortcut,
specification,
(AffixShortcut::None),
(),
(Specification::BSC),
(Specification::BSC),
);
as_general_impl!(
AffixualCnShortcutAdditions,
NormalCnShortcutAdditions,
,
,
,
affix_shortcut,
specification,
(AffixShortcut::None),
(),
(Specification::BSC),
(),
);
impl AsGeneral<NormalCaShortcutAdditions> for ReferentialCaShortcutAdditions {
fn as_general(self) -> NormalCaShortcutAdditions {
NormalCaShortcutAdditions {
ca: self.ca.as_general(),
relation: self.relation,
slot_v_affixes: self.slot_v_affixes,
vn: self.vn,
}
}
}
impl From<ReferentialCaShortcutAdditions> for NormalCaShortcutAdditions {
fn from(value: ReferentialCaShortcutAdditions) -> Self {
value.as_general()
}
}
impl TryAsSpecific<ReferentialCaShortcutAdditions> for NormalCaShortcutAdditions {
fn try_as_specific(self) -> Option<ReferentialCaShortcutAdditions> {
Some(ReferentialCaShortcutAdditions {
ca: self.ca.try_as_specific()?,
relation: self.relation,
slot_v_affixes: self.slot_v_affixes,
vn: self.vn,
})
}
}
impl AsGeneral<ShortcutCheckedFormativeAdditions> for NormalFormativeAdditions {
fn as_general(self) -> ShortcutCheckedFormativeAdditions {
match self {
Self::Normal(value) => ShortcutCheckedFormativeAdditions::Normal(value),
Self::CnShortcut(value) => ShortcutCheckedFormativeAdditions::CnShortcut(value),
Self::CaShortcut(value) => ShortcutCheckedFormativeAdditions::CaShortcut(value),
}
}
}
impl From<NormalFormativeAdditions> for ShortcutCheckedFormativeAdditions {
fn from(value: NormalFormativeAdditions) -> Self {
value.as_general()
}
}
impl TryAsSpecific<NormalFormativeAdditions> for ShortcutCheckedFormativeAdditions {
fn try_as_specific(self) -> Option<NormalFormativeAdditions> {
Some(match self {
Self::Normal(value) => NormalFormativeAdditions::Normal(value),
Self::CnShortcut(value) => NormalFormativeAdditions::CnShortcut(value),
Self::CaShortcut(value) => NormalFormativeAdditions::CaShortcut(value),
})
}
}
impl AsGeneral<ShortcutCheckedFormativeAdditions> for ReferentialFormativeAdditions {
fn as_general(self) -> ShortcutCheckedFormativeAdditions {
match self {
Self::Normal(value) => ShortcutCheckedFormativeAdditions::Normal(value.as_general()),
Self::CnShortcut(value) => {
ShortcutCheckedFormativeAdditions::CnShortcut(value.as_general())
}
Self::CaShortcut(value) => {
ShortcutCheckedFormativeAdditions::CaShortcut(value.as_general())
}
}
}
}
impl From<ReferentialFormativeAdditions> for ShortcutCheckedFormativeAdditions {
fn from(value: ReferentialFormativeAdditions) -> Self {
value.as_general()
}
}
impl TryAsSpecific<ReferentialFormativeAdditions> for ShortcutCheckedFormativeAdditions {
fn try_as_specific(self) -> Option<ReferentialFormativeAdditions> {
Some(match self {
Self::Normal(value) => ReferentialFormativeAdditions::Normal(value.try_as_specific()?),
Self::CnShortcut(value) => {
ReferentialFormativeAdditions::CnShortcut(value.try_as_specific()?)
}
Self::CaShortcut(value) => {
ReferentialFormativeAdditions::CaShortcut(value.try_as_specific()?)
}
})
}
}
impl AsGeneral<ShortcutCheckedFormativeAdditions> for AffixualFormativeAdditions {
fn as_general(self) -> ShortcutCheckedFormativeAdditions {
match self {
Self::Normal(value) => ShortcutCheckedFormativeAdditions::Normal(value.as_general()),
Self::CnShortcut(value) => {
ShortcutCheckedFormativeAdditions::CnShortcut(value.as_general())
}
}
}
}
impl From<AffixualFormativeAdditions> for ShortcutCheckedFormativeAdditions {
fn from(value: AffixualFormativeAdditions) -> Self {
value.as_general()
}
}
impl TryAsSpecific<AffixualFormativeAdditions> for ShortcutCheckedFormativeAdditions {
fn try_as_specific(self) -> Option<AffixualFormativeAdditions> {
match self {
Self::Normal(value) => {
Some(AffixualFormativeAdditions::Normal(value.try_as_specific()?))
}
Self::CnShortcut(value) => Some(AffixualFormativeAdditions::CnShortcut(
value.try_as_specific()?,
)),
Self::CaShortcut(_) => None,
}
}
}