diff --git a/src/note.rs b/src/note.rs index 0284302..da9958c 100644 --- a/src/note.rs +++ b/src/note.rs @@ -1,5 +1,6 @@ use core::fmt; use std::fmt::Formatter; +use crate::Error; #[derive(Clone, Debug, PartialEq)] pub enum RelativeNote { @@ -23,6 +24,35 @@ pub struct Note { octave: u8, // upper limit? 8? } +impl Note { + fn from(str: &str) -> Result { + let mut chars: Vec = str.chars().collect(); + + // last char may or may not be present / may or may not be an octave number + let octave = chars.pop().unwrap_or('4').to_string().parse().unwrap_or(4); + + let chars: String = chars.into_iter().collect(); + + let relative = match chars.as_ref() { + "C" => RelativeNote::C, + "C#" => RelativeNote::CSharp, + "D" => RelativeNote::D, + "D#" => RelativeNote::DSharp, + "E" => RelativeNote::E, + "F" => RelativeNote::F, + "F#" => RelativeNote::FSharp, + "G" => RelativeNote::G, + "G#" => RelativeNote::GSharp, + "A" => RelativeNote::A, + "A#" => RelativeNote::ASharp, + "B" => RelativeNote::B, + _ => { return Err(Error::RelativeNote); } + }; + + Ok(Note { relative, octave }) + } +} + impl fmt::Display for Note { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( @@ -60,4 +90,20 @@ mod test { fn a_sharp_0() { assert_eq!(Note { relative: RelativeNote::ASharp, octave: 0 }.to_string(), "A#0"); } + + #[test] + fn c_sharp_3_from_str() { + assert_eq!( + Note::from("C#3").unwrap(), + Note { relative: RelativeNote::CSharp, octave: 3 } + ); + } + + #[test] + fn b_0_from_str() { + assert_eq!( + Note::from("B0").unwrap(), + Note { relative: RelativeNote::B, octave: 0 } + ); + } }