note_pen/
accidental.rs

1use crate::note::Note;
2use std::ops::Add;
3
4/// Represents an accidental.
5///
6/// # Examples
7/// ```rust
8/// use note_pen::prelude::*;
9/// let sharp = Accidental::Sharp;
10/// let note = Note::new(Alphabet::A, sharp, 4);
11/// let next_note = sharp + note;
12/// assert_eq!(next_note, Note::new(Alphabet::A, Accidental::DoubleSharp, 4));
13/// assert_eq!(sharp + note, Note::new(Alphabet::B, Accidental::default(), 4));
14/// ```
15#[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}