rstmt_nrt/traits/
triad_type.rs

1/*
2    Appellation: triad_kind <module>
3    Created At: 2025.12.23:14:15:46
4    Contrib: @FL03
5*/
6use crate::Triads;
7/// The [`Relative`] trait is used to define a relationship between two distinct triad
8/// classifications
9pub trait Relative {
10    type Rel;
11
12    private! {}
13
14    fn rel(&self) -> Self::Rel;
15}
16
17/// The [`TriadType`] trait is used to represent the various classifications of a triad
18/// considered by the Neo-Riemannian theory.
19pub trait TriadType
20where
21    Self: 'static + Copy + Relative + Send + Sync + core::fmt::Debug + core::fmt::Display,
22{
23    private! {}
24
25    fn new() -> Self
26    where
27        Self: Sized;
28
29    fn root(&self) -> usize;
30
31    fn fifth(&self) -> usize;
32
33    fn third(&self) -> usize;
34    /// consumes the instance, returning a variant of the [`TriadClass`] enum
35    fn dynamic(&self) -> crate::Triads {
36        if self.is_major() {
37            Triads::Major
38        } else if self.is_minor() {
39            Triads::Minor
40        } else if self.is_augmented() {
41            Triads::Augmented
42        } else if self.is_diminished() {
43            Triads::Diminished
44        } else {
45            unreachable!("invalid triad type")
46        }
47    }
48
49    fn is_major(&self) -> bool {
50        false
51    }
52
53    fn is_minor(&self) -> bool {
54        false
55    }
56
57    fn is_augmented(&self) -> bool {
58        false
59    }
60
61    fn is_diminished(&self) -> bool {
62        false
63    }
64}
65
66pub trait RelTriad: TriadType + Relative
67where
68    Self::Rel: TriadType,
69{
70    private! {}
71
72    fn relative(&self) -> Self::Rel;
73}
74
75/*
76 ************* Implementations *************
77*/
78
79impl<A, B> RelTriad for A
80where
81    A: TriadType + Relative<Rel = B>,
82    B: TriadType,
83{
84    seal! {}
85
86    fn relative(&self) -> B {
87        <B>::new()
88    }
89}
90
91impl Relative for Triads {
92    type Rel = Triads;
93
94    seal! {}
95
96    fn rel(&self) -> Self::Rel {
97        self.relative()
98    }
99}
100
101impl TriadType for Triads {
102    seal! {}
103
104    fn new() -> Self {
105        Self::default()
106    }
107
108    fn is_major(&self) -> bool {
109        matches!(self, Triads::Major)
110    }
111
112    fn is_minor(&self) -> bool {
113        matches!(self, Triads::Minor)
114    }
115
116    fn is_augmented(&self) -> bool {
117        matches!(self, Triads::Augmented)
118    }
119
120    fn is_diminished(&self) -> bool {
121        matches!(self, Triads::Diminished)
122    }
123
124    fn root(&self) -> usize {
125        self.root()
126    }
127
128    fn fifth(&self) -> usize {
129        self.fifth()
130    }
131
132    fn third(&self) -> usize {
133        self.third()
134    }
135}
136
137macro_rules! triad_kind {
138    (impl $trait:ident for {$($($name:ident)::*<Rel = $rel:ty>::<[$($v:literal),* $(,)?]> $({$($rest:tt)*})?),* $(,)?}) => {
139        $(triad_kind! { @impl $trait for $($name)::*<Rel = $rel>::<[$($v),*]> $({$($rest)*})? })*
140    };
141    (@impl $trait:ident for $($name:ident)::* <Rel = $rel:ty>::<[$r:literal, $f:literal, $t:literal]> $({$($rest:tt)*})?) => {
142        impl $trait for $($name)::* {
143            // type Rel = $rel;
144
145            seal! {}
146
147            fn new() -> Self {
148                Self::default()
149            }
150
151            fn root(&self) -> usize {
152                $r
153            }
154
155            fn fifth(&self) -> usize {
156                $f
157            }
158
159            fn third(&self) -> usize {
160                $t
161            }
162
163            $($($rest)*)?
164        }
165
166        impl Relative for $($name)::* {
167            type Rel = $rel;
168
169            seal! {}
170
171            fn rel(&self) -> Self::Rel {
172                <$rel>::default()
173            }
174        }
175    };
176}
177
178triad_kind! {
179    impl TriadType for {
180        rstmt_core::Augmented<Rel = rstmt_core::Diminished>::<[4, 8, 4]> {
181            fn is_augmented(&self) -> bool {
182                true
183            }
184        },
185        rstmt_core::Diminished<Rel = rstmt_core::Augmented>::<[3, 6, 3]> {
186            fn is_diminished(&self) -> bool {
187                true
188            }
189        },
190        rstmt_core::Major<Rel = rstmt_core::Minor>::<[4, 7, 3]> {
191            fn is_major(&self) -> bool {
192                true
193            }
194        },
195        rstmt_core::Minor<Rel = rstmt_core::Major>::<[3, 7, 4]> {
196            fn is_minor(&self) -> bool {
197                true
198            }
199        }
200    }
201}