chordcalc/parsing/
notes.rs1use core::str::FromStr;
2
3use crate::notes::Note;
4
5use super::Error;
6
7impl FromStr for Note {
8 type Err = Error;
9
10 fn from_str(s: &str) -> Result<Self, Self::Err> {
11 match s {
12 "A" => Ok(Self::A),
13 "B" => Ok(Self::B),
14 "C" => Ok(Self::C),
15 "D" => Ok(Self::D),
16 "E" => Ok(Self::E),
17 "F" => Ok(Self::F),
18 "G" => Ok(Self::G),
19 "DO" => Ok(Self::C),
20 "Do" => Ok(Self::C),
21 "do" => Ok(Self::C),
22 "RE" => Ok(Self::D),
23 "Re" => Ok(Self::D),
24 "re" => Ok(Self::D),
25 "MI" => Ok(Self::E),
26 "Mi" => Ok(Self::E),
27 "mi" => Ok(Self::E),
28 "FA" => Ok(Self::F),
29 "Fa" => Ok(Self::F),
30 "fa" => Ok(Self::F),
31 "SOL" => Ok(Self::G),
32 "Sol" => Ok(Self::G),
33 "sol" => Ok(Self::G),
34 "LA" => Ok(Self::A),
35 "La" => Ok(Self::A),
36 "la" => Ok(Self::A),
37 "SI" => Ok(Self::B),
38 "Si" => Ok(Self::B),
39 "si" => Ok(Self::B),
40 _ => Err(Error::UnknownNote),
41 }
42 }
43}
44
45#[cfg(test)]
46#[cfg(test)]
47mod tests {
48 use crate::{notes::Note, parsing::Error};
49
50 #[test]
51 fn parse_notes() {
52 let result = &[
53 Note::A,
54 Note::B,
55 Note::C,
56 Note::D,
57 Note::E,
58 Note::F,
59 Note::G,
60 ];
61 for (note, expected) in ["A", "B", "C", "D", "E", "F", "G"]
62 .iter()
63 .zip(result.iter())
64 {
65 let parsed = note.parse();
66 assert_eq!(parsed, Ok(*expected));
67 }
68 }
69 #[test]
70 fn parse_romance_notes() {
71 let result = &[
72 Note::A,
73 Note::B,
74 Note::C,
75 Note::D,
76 Note::E,
77 Note::F,
78 Note::G,
79 ];
80 for (note, expected) in ["La", "Si", "Do", "Re", "Mi", "Fa", "Sol"]
81 .iter()
82 .zip(result.iter())
83 {
84 let parsed = note.parse();
85 assert_eq!(parsed, Ok(*expected));
86 let parsed = note.to_uppercase().parse();
87 assert_eq!(parsed, Ok(*expected));
88 let parsed = note.to_ascii_lowercase().parse();
89 assert_eq!(parsed, Ok(*expected));
90 }
91 }
92 #[test]
93 fn parse_unexisting_notes() {
94 for note in &["H", "ABC"] {
95 let parsed: Result<Note, Error> = note.parse();
96 assert_eq!(parsed, Err(Error::UnknownNote));
97 }
98 }
99}