music_note/staff/
key.rs

1use crate::{Interval, Pitch};
2use core::fmt::{self, Write};
3
4/// A key signature represented as the total number of sharps or flats.
5#[derive(Clone, Copy, Debug)]
6pub struct Key {
7    sharps: u8,
8}
9
10impl Key {
11    /// ```
12    /// use music_note::{Key, Pitch};
13    ///
14    /// let key = Key::major(Pitch::D);
15    /// assert_eq!(key.to_string(), "##")
16    /// ```
17    ///
18    /// ```
19    /// use music_note::{Key, Pitch};
20    ///
21    /// let key = Key::major(Pitch::F);
22    /// assert_eq!(key.to_string(), "b")
23    /// ```
24    pub fn major(root: Pitch) -> Self {
25        let mut pitch = Pitch::C;
26        let mut alteration = 0;
27        while pitch != root {
28            pitch = pitch + Interval::PERFECT_FIFTH;
29            alteration += 1;
30        }
31
32        Self { sharps: alteration }
33    }
34
35    /// Returns the number of sharps in this key.
36    pub fn sharps(self) -> u8 {
37        self.sharps
38    }
39
40    /// Returns the number of flats in this key.
41    pub fn flats(self) -> u8 {
42        Pitch::B.into_byte() - self.sharps
43    }
44}
45
46impl fmt::Display for Key {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        if self.sharps <= 6 {
49            for _ in 0..self.sharps {
50                f.write_char('#')?;
51            }
52        } else {
53            for _ in self.sharps..=Pitch::B.into_byte() {
54                f.write_char('b')?;
55            }
56        }
57
58        Ok(())
59    }
60}