rust_fixed_point_decimal/
format.rs1use std::{
11 cmp::{min, Ordering},
12 fmt,
13};
14
15use num::{integer::div_mod_floor, Integer};
16use rust_fixed_point_decimal_core::ten_pow;
17
18use crate::{
19 prec_constraints::{PrecLimitCheck, True},
20 rounding::div_i128_rounded,
21 Decimal, MAX_PREC,
22};
23
24impl<const P: u8> fmt::Debug for Decimal<P>
25where
26 PrecLimitCheck<{ P <= MAX_PREC }>: True,
27{
28 fn fmt(&self, form: &mut fmt::Formatter<'_>) -> fmt::Result {
29 if P == 0 {
30 write!(form, "Dec!({})", self.coeff)
31 } else {
32 let (int, frac) = div_mod_floor(self.coeff, ten_pow(P));
33 write!(form, "Dec!({}.{:0width$})", int, frac, width = P as usize)
34 }
35 }
36}
37
38#[cfg(test)]
39mod test_fmt_debug {
40 use super::*;
41
42 #[test]
43 fn test_fmt() {
44 let d = Decimal::<3>::new_raw(1234567890002);
45 assert_eq!(format!("{:?}", d), "Dec!(1234567890.002)");
46 let d = Decimal::<9>::new_raw(-1230000000000);
47 assert_eq!(format!("{:?}", d), "Dec!(-1230.000000000)");
48 let d = Decimal::<0>::new_raw(1234567890002);
49 assert_eq!(format!("{:?}", d), "Dec!(1234567890002)");
50 }
51}
52
53impl<const P: u8> fmt::Display for Decimal<P>
54where
55 PrecLimitCheck<{ P <= MAX_PREC }>: True,
56{
57 fn fmt(&self, form: &mut fmt::Formatter<'_>) -> fmt::Result {
75 let tmp: String;
76 let prec = match form.precision() {
77 Some(prec) => min(prec, MAX_PREC as usize),
78 None => P as usize,
79 };
80 if P == 0 {
81 if prec > 0 {
82 tmp =
83 format!("{}.{:0width$}", self.coeff.abs(), 0, width = prec);
84 } else {
85 tmp = self.coeff.abs().to_string();
86 }
87 } else {
88 let (int, frac) = match prec.cmp(&(P as usize)) {
89 Ordering::Equal => self.coeff.abs().div_mod_floor(&ten_pow(P)),
90 Ordering::Less => {
91 let coeff = div_i128_rounded(
93 self.coeff,
94 ten_pow(P - prec as u8),
95 None,
96 );
97 coeff.abs().div_mod_floor(&ten_pow(prec as u8))
98 }
99 Ordering::Greater => {
100 let (int, frac) =
101 self.coeff.abs().div_mod_floor(&ten_pow(P));
102 (int, frac * ten_pow(prec as u8 - P))
103 }
104 };
105 if prec > 0 {
106 tmp = format!("{}.{:0width$}", int, frac, width = prec);
107 } else {
108 tmp = int.to_string();
109 }
110 }
111 form.pad_integral(!self.is_negative(), "", &tmp)
112 }
113}
114
115#[cfg(test)]
116mod test_fmt_display {
117 use super::*;
118
119 #[test]
120 fn test_fmt_decimal_0() {
121 let d = Decimal::<0>::new_raw(1234567890002);
122 assert_eq!(d.to_string(), "1234567890002");
123 assert_eq!(format!("{}", d), "1234567890002");
124 assert_eq!(format!("{:<15}", d), "1234567890002 ");
125 assert_eq!(format!("{:^15}", d), " 1234567890002 ");
126 assert_eq!(format!("{:>15}", d), " 1234567890002");
127 assert_eq!(format!("{:15}", d), " 1234567890002");
128 assert_eq!(format!("{:015}", d), "001234567890002");
129 assert_eq!(format!("{:010.2}", d), "1234567890002.00");
130 let d = Decimal::<0>::new_raw(-12345);
131 assert_eq!(d.to_string(), "-12345");
132 assert_eq!(format!("{}", d), "-12345");
133 assert_eq!(format!("{:10}", d), " -12345");
134 assert_eq!(format!("{:010}", d), "-000012345");
135 assert_eq!(format!("{:012.3}", d), "-0012345.000");
136 }
137
138 #[test]
139 fn test_fmt_decimal_without_rounding() {
140 let d = Decimal::<4>::new_raw(1234567890002);
141 assert_eq!(d.to_string(), "123456789.0002");
142 assert_eq!(format!("{}", d), "123456789.0002");
143 assert_eq!(format!("{:<15}", d), "123456789.0002 ");
144 assert_eq!(format!("{:^17}", d), " 123456789.0002 ");
145 assert_eq!(format!("{:>15}", d), " 123456789.0002");
146 assert_eq!(format!("{:15}", d), " 123456789.0002");
147 assert_eq!(format!("{:015}", d), "0123456789.0002");
148 assert_eq!(format!("{:010.7}", d), "123456789.0002000");
149 let d = Decimal::<2>::new_raw(-12345);
150 assert_eq!(d.to_string(), "-123.45");
151 assert_eq!(format!("{}", d), "-123.45");
152 assert_eq!(format!("{:10}", d), " -123.45");
153 assert_eq!(format!("{:010}", d), "-000123.45");
154 assert_eq!(format!("{:012.3}", d), "-0000123.450");
155 let d = Decimal::<7>::new_raw(-12345);
156 assert_eq!(d.to_string(), "-0.0012345");
157 assert_eq!(format!("{}", d), "-0.0012345");
158 }
159
160 #[test]
161 fn test_fmt_decimal_with_rounding() {
162 let d = Decimal::<5>::new_raw(1234567890002);
163 assert_eq!(format!("{:.4}", d), "12345678.9000");
164 assert_eq!(format!("{:<15.2}", d), "12345678.90 ");
165 assert_eq!(format!("{:.0}", d), "12345679");
166 let d = Decimal::<7>::new_raw(-12347);
167 assert_eq!(format!("{:.3}", d), "-0.001");
168 assert_eq!(format!("{:10.5}", d), " -0.00123");
169 assert_eq!(format!("{:010.6}", d), "-00.001235");
170 }
171}