rstmt_core/pitch/impls/
impl_pclass_ext.rs

1/*
2    Appellation: impl_pclass_ext <module>
3    Created At: 2025.12.23:16:16:05
4    Contrib: @FL03
5*/
6use crate::error::Error;
7use crate::pitch::pitch_class::PitchClass;
8use crate::pitch::traits::{Accidental, PitchClassRepr, RawAccidental, RawPitchClass};
9
10impl<P, K> core::fmt::Debug for PitchClass<P, K>
11where
12    P: RawPitchClass<Tag = K>,
13    K: RawAccidental,
14{
15    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
16        if self.is_natural() {
17            write!(f, "{}", self.get())
18        } else {
19            write!(f, "{}{}", self.get(), self.kind.symbol())
20        }
21    }
22}
23
24impl<P, K> core::fmt::Display for PitchClass<P, K>
25where
26    P: RawPitchClass<Tag = K>,
27    K: RawAccidental,
28{
29    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
30        if self.is_natural() {
31            write!(f, "{}", self.get())
32        } else {
33            write!(f, "{}{}", self.get(), self.kind.symbol())
34        }
35    }
36}
37
38impl<P, K> core::str::FromStr for PitchClass<P, K>
39where
40    P: PitchClassRepr<Tag = K>,
41    K: Accidental,
42{
43    type Err = Error;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        let (lex_class, lex_kind) = if s.len() > 1 {
47            let (head, tail) = s.split_at(s.len() - 1);
48            (head, tail)
49        } else {
50            (s, "Natural")
51        };
52        let class = lex_class.parse::<P>()?;
53        let kind = lex_kind.parse::<K>()?;
54        Ok(Self { class, kind })
55    }
56}
57impl<P, K> TryFrom<isize> for PitchClass<P, K>
58where
59    P: PitchClassRepr<Tag = K>,
60    K: Accidental,
61{
62    type Error = Error;
63
64    fn try_from(value: isize) -> Result<Self, Self::Error> {
65        if P::is(value) {
66            return Ok(Self {
67                class: P::new(),
68                kind: K::default(),
69            });
70        }
71        Err(Error::MismatchedPitchClasses(value, <P>::IDX))
72    }
73}
74
75impl<P, K> AsRef<isize> for PitchClass<P, K>
76where
77    P: RawPitchClass<Tag = K>,
78    K: RawAccidental,
79{
80    fn as_ref(&self) -> &isize {
81        self.get().as_ref()
82    }
83}
84
85impl<P, K> AsRef<str> for PitchClass<P, K>
86where
87    P: RawPitchClass<Tag = K>,
88    K: RawAccidental,
89{
90    fn as_ref(&self) -> &str {
91        self.get().name()
92    }
93}
94
95impl<P, K> core::borrow::Borrow<isize> for PitchClass<P, K>
96where
97    P: RawPitchClass<Tag = K>,
98    K: RawAccidental,
99{
100    fn borrow(&self) -> &isize {
101        self.get().borrow()
102    }
103}
104
105impl<P, K> core::ops::Deref for PitchClass<P, K>
106where
107    P: RawPitchClass<Tag = K>,
108    K: RawAccidental,
109{
110    type Target = P;
111
112    fn deref(&self) -> &Self::Target {
113        self.get()
114    }
115}
116
117unsafe impl<P, K> Send for PitchClass<P, K>
118where
119    P: RawPitchClass<Tag = K>,
120    K: RawAccidental,
121{
122}
123
124unsafe impl<P, K> Sync for PitchClass<P, K>
125where
126    P: RawPitchClass<Tag = K>,
127    K: RawAccidental,
128{
129}
130
131impl<P, K> PartialEq<isize> for PitchClass<P, K>
132where
133    P: RawPitchClass<Tag = K>,
134    K: RawAccidental,
135{
136    fn eq(&self, other: &isize) -> bool {
137        self.get().index() == *other
138    }
139}
140
141impl<P, K> PartialEq<PitchClass<P, K>> for isize
142where
143    P: RawPitchClass<Tag = K>,
144    K: RawAccidental,
145{
146    fn eq(&self, other: &PitchClass<P, K>) -> bool {
147        *self == other.get().index()
148    }
149}