1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
mod event;
mod global_property;
mod property;
mod update;

use std::fmt::Display;

pub use event::{Event, EventKind};
pub use global_property::GlobalProperty;
pub use property::{Color, Coords, Property, Tag};
pub use update::Update;

#[derive(Debug)]
pub enum Record {
    GlobalProperty(GlobalProperty),
    Event(Event),
    Remove(u64),
    Frame(f64),
    Update(Update),
}

impl Display for Record {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Record::GlobalProperty(r) => r.fmt(f),
            Record::Event(r) => r.fmt(f),
            Record::Remove(id) => write!(f, "-{}", id),
            Record::Frame(n) => write!(f, "#{}", n.max_precision(2)),
            Record::Update(r) => r.fmt(f),
        }
    }
}

impl From<GlobalProperty> for Record {
    fn from(p: GlobalProperty) -> Self {
        Self::GlobalProperty(p)
    }
}

impl From<Event> for Record {
    fn from(e: Event) -> Self {
        Self::Event(e)
    }
}

impl From<Update> for Record {
    fn from(u: Update) -> Self {
        Self::Update(u)
    }
}

trait Precision {
    fn max_precision(self, max_precision: u32) -> Self;
}

impl Precision for f64 {
    fn max_precision(self, max_precision: u32) -> Self {
        let p = f64::from(10i32.pow(max_precision));
        (self * p).round() / p
    }
}

impl Precision for Option<f64> {
    fn max_precision(self, max_precision: u32) -> Self {
        self.map(|v| v.max_precision(max_precision))
    }
}

#[cfg(test)]
mod test {
    use super::Precision;

    #[test]
    #[allow(clippy::float_cmp)]
    fn test_max_precision() {
        assert_eq!(12.3456789.max_precision(0), 12.0);
        assert_eq!(12.3456789.max_precision(1), 12.3);
        assert_eq!(12.3456789.max_precision(2), 12.35);
        assert_eq!(12.3456789.max_precision(3), 12.346);
        assert_eq!(12.3.max_precision(6), 12.3);
    }
}