1use core::fmt;
2use core::mem::MaybeUninit;
3
4use crate::{Decimal, UnderlyingInt};
5
6impl<I: UnderlyingInt> fmt::Display for Decimal<I> {
24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25 let (sign, scale, man) = self.unpack();
26
27 let mut buf: [MaybeUninit<u8>; 80] = [MaybeUninit::uninit(); 80];
28 assert!(scale <= 36);
29
30 let offset = display_num(man, scale, f.precision(), &mut buf);
31
32 let buf = unsafe { buf[offset..].assume_init_ref() };
34
35 let s = unsafe { str::from_utf8_unchecked(buf) };
37
38 f.pad_integral(sign == 0 || man == I::ZERO, "", s)
39 }
40}
41
42fn display_num<I: UnderlyingInt>(
43 uns: I,
44 scale: u32,
45 precision: Option<usize>,
46 buf: &mut [MaybeUninit<u8>],
47) -> usize {
48 let precision = precision.unwrap_or(scale as usize);
49
50 if scale == 0 {
51 let mut offset = buf.len();
52 if precision > 0 {
53 offset = pad_zeros(precision, buf);
55 offset -= 1;
56 buf[offset].write(b'.');
57 }
58 return dump_single(uns, &mut buf[..offset]);
59 }
60
61 let scale = scale as usize;
62
63 if precision >= scale {
64 let (int, frac) = uns.div_rem_exp(scale as u32);
65 let offset = pad_zeros(precision.min(I::MAX_SCALE as usize) - scale, buf);
66 dump_decimal(int, frac, scale, &mut buf[..offset])
67 } else {
68 let uns = uns.div_exp((scale - precision) as u32);
69 if precision == 0 {
70 dump_single(uns, buf)
71 } else {
72 let (int, frac) = uns.div_rem_exp(precision as u32);
73 dump_decimal(int, frac, precision, buf)
74 }
75 }
76}
77
78fn dump_decimal<I: UnderlyingInt>(
80 int: I,
81 frac: I,
82 scale: usize,
83 buf: &mut [MaybeUninit<u8>],
84) -> usize {
85 let mut offset = dump_single(frac, buf);
86
87 offset = pad_zeros(scale - (buf.len() - offset), &mut buf[..offset]);
88
89 offset -= 1;
90 buf[offset].write(b'.');
91
92 dump_single(int, &mut buf[..offset])
93}
94
95fn dump_single<I: UnderlyingInt>(n: I, buf: &mut [MaybeUninit<u8>]) -> usize {
98 static DECIMAL_PAIRS: &[u8; 200] = b"\
99 0001020304050607080910111213141516171819\
100 2021222324252627282930313233343536373839\
101 4041424344454647484950515253545556575859\
102 6061626364656667686970717273747576777879\
103 8081828384858687888990919293949596979899";
104
105 let mut offset = buf.len();
106 let mut remain = n;
107
108 while remain >= I::TEN {
110 offset -= 2;
111
112 let pair: usize = (remain % I::HUNDRED).as_u32() as usize;
113 remain = remain / I::HUNDRED;
114 buf[offset + 0].write(DECIMAL_PAIRS[pair * 2 + 0]);
115 buf[offset + 1].write(DECIMAL_PAIRS[pair * 2 + 1]);
116 }
117
118 if remain != I::ZERO || n == I::ZERO {
120 offset -= 1;
121 let remain: u8 = remain.as_u32() as u8;
122 buf[offset].write(b'0' + remain);
123 }
124
125 offset
126}
127
128fn pad_zeros(n: usize, buf: &mut [MaybeUninit<u8>]) -> usize {
129 let mut offset = buf.len();
130 for _ in 0..n {
131 offset -= 1;
132 buf[offset].write(b'0');
133 }
134 offset
135}