1use std::fmt;
7
8use crate::State;
9
10pub enum Item {
15 Fill(FillItem),
16 Fn(Box<dyn Fn(&State) -> String + Send + Sync>),
17 Literal(String),
18}
19
20pub enum FillItem {
25 Bar,
26 Message,
27}
28
29pub struct FormatFloat {
34 value: f64,
35 ignore_precision: bool,
37}
38
39impl FormatFloat {
40 pub fn new(value: f64, ignore_precision: bool) -> Self {
41 assert!(value >= 0.0);
43
44 Self {
45 value,
46 ignore_precision,
47 }
48 }
49}
50
51impl fmt::Display for FormatFloat {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 if f.alternate() {
57 if self.ignore_precision {
58 f.pad_integral(true, "", &format!("{:.0}", self.value))
59 } else {
60 let scale = if self.value < 10.0 {
61 0
62 } else {
63 self.value.log10().floor() as usize
64 };
65
66 let fit_width = f.precision().unwrap_or(4);
67 let precision = fit_width.saturating_sub(scale + 2);
68 f.pad_integral(true, "", &format!("{:.*}", precision, self.value))
69 }
70 } else {
71 self.value.fmt(f)
72 }
73 }
74}
75
76pub struct FormatInteger<'a> {
81 value: u64,
82 thousands_separator: &'a str,
83}
84
85impl<'a> FormatInteger<'a> {
86 pub fn new(value: u64, thousands_separator: &'a str) -> Self {
87 Self {
88 value,
89 thousands_separator,
90 }
91 }
92}
93
94impl<'a> fmt::Display for FormatInteger<'a> {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 if f.alternate() {
100 f.pad_integral(
101 true,
102 "",
103 &crate::group_digits(self.value, self.thousands_separator),
104 )
105 } else {
106 self.value.fmt(f)
107 }
108 }
109}
110
111pub struct FormatPrefix(&'static str);
116
117impl FormatPrefix {
118 pub fn new(value: &'static str) -> Self {
119 Self(value)
120 }
121}
122
123impl fmt::Display for FormatPrefix {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 if f.alternate() {
129 if self.0.is_empty() {
130 Ok(())
131 } else {
132 write!(f, " {}", self.0)
133 }
134 } else {
135 self.0.fmt(f)
136 }
137 }
138}
139
140#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
151 fn format_float() {
152 assert_eq!(format!("{:#.4}", FormatFloat::new(1.23456, false)), "1.23");
153 assert_eq!(format!("{:#.4}", FormatFloat::new(12.3456, false)), "12.3");
154 assert_eq!(format!("{:#.4}", FormatFloat::new(123.456, false)), "123");
155 assert_eq!(format!("{:#.4}", FormatFloat::new(1234.56, false)), "1235");
156 assert_eq!(format!("{:#.4}", FormatFloat::new(12345.6, false)), "12346");
157 }
158
159 #[test]
160 fn format_float_0() {
161 assert_eq!(format!("{:#.4}", FormatFloat::new(0.0, false)), "0.00");
162 }
163
164 #[test]
165 fn format_float_ignore_precision() {
166 assert_eq!(format!("{:#.4}", FormatFloat::new(12.34, true)), "12");
167 }
168}