resonata/notes/name/
utils.rs1use std::{fmt::{self, Display, Formatter, Debug}, str::FromStr, ops::{Add, Sub, AddAssign, SubAssign}};
2use super::super::*;
3
4impl From<u8> for NoteName {
5 fn from(value: u8) -> Self {
6 match value % 7 {
7 0 => C,
8 1 => D,
9 2 => E,
10 3 => F,
11 4 => G,
12 5 => A,
13 6 => B,
14 _ => unreachable!(),
15 }
16 }
17}
18
19impl From<NoteName> for u8 {
20 fn from(name: NoteName) -> Self {
21 match name {
22 C => 0,
23 D => 2,
24 E => 4,
25 F => 5,
26 G => 7,
27 A => 9,
28 B => 11,
29 }
30 }
31}
32
33impl Add<u8> for NoteName {
34 type Output = Self;
35
36 fn add(self, n: u8) -> Self::Output {
37 Self::from(u8::from(self) + n % 6)
38 }
39}
40
41impl AddAssign<u8> for NoteName {
42 fn add_assign(&mut self, n: u8) {
43 *self = Self::from(u8::from(*self) + n % 6)
44 }
45}
46
47impl Sub<u8> for NoteName {
48 type Output = Self;
49
50 fn sub(self, n: u8) -> Self::Output {
51 Self::from((u8::from(self) as i8 - n as i8).abs() as u8 % 6)
52 }
53}
54
55impl SubAssign<u8> for NoteName {
56 fn sub_assign(&mut self, n: u8) {
57 *self = Self::from((u8::from(*self) as i8 - n as i8).abs() as u8 % 6)
58 }
59}
60
61impl FromStr for NoteName {
62 type Err = ResonataError;
63
64 fn from_str(s: &str) -> Result<Self, Self::Err> {
65 match s.to_ascii_lowercase().as_str() {
66 "c" => Ok(C),
67 "d" => Ok(D),
68 "e" => Ok(E),
69 "f" => Ok(F),
70 "g" => Ok(G),
71 "a" => Ok(A),
72 "b" => Ok(B),
73 _ => nope!(InvalidNoteName)
74 }
75 }
76}
77
78impl Display for NoteName {
79 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
80 let token = match self {
81 C => "C",
82 D => "D",
83 E => "E",
84 F => "F",
85 G => "G",
86 A => "A",
87 B => "B",
88 };
89 write!(f, "{}", token)
90 }
91}
92
93impl Debug for NoteName {
94 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
95 write!(f, "{}", self.to_string())
96 }
97}