klavier_core/
grid.rs

1use std::fmt;
2
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub enum GridError {
6    ParseError(String),
7}
8
9#[derive(serde::Deserialize, serde::Serialize)]
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct Grid {
12    value: u32,
13}
14
15impl Grid {
16    pub fn value_of(s: &str) -> Result<Self, GridError> {
17        s.parse::<u32>()
18            .map_err(|_| {
19                GridError::ParseError(s.to_owned())
20            })
21            .and_then(|i| {
22                Self::from_u32(i)
23            })
24    }
25
26    #[inline]
27    pub fn from_u32(i: u32) -> Result<Self, GridError> {
28        if i == 0 {
29            Err(GridError::ParseError("0".to_owned()))
30        } else {
31            Ok(Self { value: i })
32        }
33    }
34
35    #[inline]
36    pub fn as_u32(self) -> u32 {
37        self.value
38    }
39
40    #[inline]
41    pub fn snap(self, tick: i64) -> i64 {
42        let i = self.value as i64;
43        if tick < 0 {
44            i * ((tick - i / 2) / i)
45        } else {
46            i * ((tick + i / 2) / i)
47        }
48    }
49}
50
51impl Default for Grid {
52    fn default() -> Self {
53        Self { value: 60 }
54    }
55}
56
57impl fmt::Display for Grid {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(f, "{}", self.value)
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use crate::grid::{Grid, GridError};
66
67    #[test]
68    fn empty_str() {
69        assert_eq!(Grid::value_of(""), Err(GridError::ParseError("".to_owned())));
70    }
71
72
73    #[test]
74    fn non_numerical_str() {
75        assert_eq!(Grid::value_of("1a"), Err(GridError::ParseError("1a".to_owned())));
76    }
77
78    #[test]
79    fn zero() {
80        assert_eq!(Grid::value_of("0"), Err(GridError::ParseError("0".to_owned())));
81    }
82
83    #[test]
84    fn ok() {
85        assert_eq!(Grid::value_of("120"), Ok(Grid { value: 120 }));
86    }
87
88    #[test]
89    fn snap() {
90        assert_eq!(Grid::from_u32(100).unwrap().snap(49), 0);
91        assert_eq!(Grid::from_u32(100).unwrap().snap(50), 100);
92        assert_eq!(Grid::from_u32(100).unwrap().snap(99), 100);
93        assert_eq!(Grid::from_u32(100).unwrap().snap(149), 100);
94        assert_eq!(Grid::from_u32(100).unwrap().snap(150), 200);
95        assert_eq!(Grid::from_u32(100).unwrap().snap(199), 200);
96        assert_eq!(Grid::from_u32(100).unwrap().snap(249), 200);
97 
98        assert_eq!(Grid::from_u32(100).unwrap().snap(-49), 0);
99        assert_eq!(Grid::from_u32(100).unwrap().snap(-50), -100);
100    }
101}