note_pen/
scale_degree.rs

1use crate::key::{Key, Scale};
2use crate::note::Note;
3use crate::Accidental;
4use std::num::NonZeroU8;
5
6#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct ScaleDegree {
9    pub degree: NonZeroU8,
10    pub quality: Accidental,
11}
12
13impl ScaleDegree {
14    pub const fn new(degree: u8, quality: Accidental) -> Self {
15        Self {
16            degree: NonZeroU8::new(degree).expect("0 is not a valid scale degree"),
17            quality,
18        }
19    }
20
21    pub fn from_note(note: &Note, key: &Key) -> Option<Self> {
22        let scale = Scale::from(key);
23        scale
24            .notes
25            .iter()
26            .enumerate()
27            .find(|(_, &n)| n.id().simple() == note.id().simple())
28            .map(|(i, _)| Self::new(i as u8 + 1, Accidental::None))
29    }
30}
31
32impl Default for ScaleDegree {
33    fn default() -> Self {
34        Self {
35            degree: NonZeroU8::new(1).expect("1 is not 0 ..."),
36            quality: Accidental::Natural,
37        }
38    }
39}