livesplit_core/timing/formatter/
segment_time.rs1use super::{
2 format_padded, Accuracy, TimeFormatter, DASH, MINUS, SECONDS_PER_HOUR, SECONDS_PER_MINUTE,
3};
4use crate::TimeSpan;
5use core::fmt::{Display, Formatter, Result};
6
7pub struct Inner {
8 time: Option<TimeSpan>,
9 accuracy: Accuracy,
10}
11
12pub struct SegmentTime {
26 accuracy: Accuracy,
27}
28
29impl SegmentTime {
30 pub const fn new() -> Self {
33 SegmentTime {
34 accuracy: Accuracy::Hundredths,
35 }
36 }
37
38 pub const fn with_accuracy(accuracy: Accuracy) -> Self {
41 SegmentTime { accuracy }
42 }
43}
44
45impl Default for SegmentTime {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51impl TimeFormatter<'_> for SegmentTime {
52 type Inner = Inner;
53
54 fn format<T>(&self, time: T) -> Self::Inner
55 where
56 T: Into<Option<TimeSpan>>,
57 {
58 Inner {
59 time: time.into(),
60 accuracy: self.accuracy,
61 }
62 }
63}
64
65impl Display for Inner {
66 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
67 if let Some(time) = self.time {
68 let (total_seconds, nanoseconds) = time.to_seconds_and_subsec_nanoseconds();
69 let (total_seconds, nanoseconds) = if (total_seconds | nanoseconds as i64) < 0 {
70 f.write_str(MINUS)?;
71 ((-total_seconds) as u64, (-nanoseconds) as u32)
72 } else {
73 (total_seconds as u64, nanoseconds as u32)
74 };
75 let seconds = (total_seconds % SECONDS_PER_MINUTE) as u8;
80 let minutes = ((total_seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE) as u8;
81 let hours = total_seconds / SECONDS_PER_HOUR;
82
83 let mut buffer = itoa::Buffer::new();
84
85 if hours > 0 {
86 f.write_str(buffer.format(hours))?;
87 f.write_str(":")?;
88 f.write_str(format_padded(minutes))?;
89 f.write_str(":")?;
90 f.write_str(format_padded(seconds))?;
91 } else if minutes > 0 {
92 f.write_str(buffer.format(minutes))?;
93 f.write_str(":")?;
94 f.write_str(format_padded(seconds))?;
95 } else {
96 f.write_str(buffer.format(seconds))?;
97 }
98 self.accuracy.format_nanoseconds(nanoseconds).fmt(f)
99 } else {
100 f.write_str(DASH)
101 }
102 }
103}
104
105#[test]
106fn test() {
107 let time = "4:20.69".parse::<TimeSpan>().unwrap();
108 let formatted = SegmentTime::new().format(time).to_string();
109 assert_eq!(formatted, "4:20.69");
110}