1use crate::note::Note;
2use std::ops::Add;
3
4#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub enum Accidental {
18 None,
19 DoubleFlat,
20 Flat,
21 Natural,
22 Sharp,
23 DoubleSharp,
24}
25
26impl Accidental {
27 pub const fn unicode(&self) -> &'static str {
28 match self {
29 Self::None => "",
30 Self::DoubleFlat => "𝄫",
31 Self::Flat => "♭",
32 Self::Natural => "",
33 Self::Sharp => "♯",
34 Self::DoubleSharp => "𝄪",
35 }
36 }
37}
38
39impl Default for Accidental {
40 fn default() -> Self {
41 Self::Natural
42 }
43}
44
45impl Add<Note> for Accidental {
46 type Output = Note;
47
48 fn add(self, rhs: Note) -> Self::Output {
49 match self {
50 Self::None => rhs,
51 Self::DoubleFlat => rhs.decrement_by(2),
52 Self::Flat => rhs.decrement(),
53 Self::Natural => rhs,
54 Self::Sharp => rhs.increment(),
55 Self::DoubleSharp => rhs.increment_by(2),
56 }
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use crate::Alphabet;
63
64 #[test]
65 fn test_accidental() {
66 use super::*;
67 let note = Note::new(Alphabet::A, Accidental::Sharp, 4);
68 assert_eq!(
69 Accidental::Sharp + note,
70 Note::new(Alphabet::B, Accidental::Natural, 4)
71 );
72 assert_eq!(
73 Accidental::Sharp + note,
74 Note::new(Alphabet::B, Accidental::Natural, 4)
75 );
76 assert_eq!(
77 Accidental::Natural + note,
78 Note::new(Alphabet::A, Accidental::Sharp, 4)
79 );
80 assert_eq!(
81 Accidental::DoubleSharp + note,
82 Note::new(Alphabet::B, Accidental::Sharp, 4)
83 );
84 assert_eq!(
85 Accidental::Flat + note,
86 Note::new(Alphabet::A, Accidental::default(), 4)
87 );
88 }
89}