reweb3_num/buint/fmt.rs
1use crate::digit;
2use alloc::string::String;
3use core::fmt::Write;
4use core::fmt::{Binary, Debug, Display, Formatter, LowerExp, LowerHex, Octal, UpperExp, UpperHex};
5
6macro_rules! fmt {
7 ($BUint: ident, $BInt: ident, $Digit: ident) => {
8 macro_rules! fmt_method {
9 ($format: expr, $format_pad: expr, $pad: expr, $prefix: expr) => {
10 #[inline]
11 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
12 let mut format_string = String::new();
13 for digit in self.digits.iter().rev() {
14 if format_string.is_empty() {
15 if digit != &0 {
16 write!(format_string, $format, digit)?;
17 }
18 } else {
19 write!(format_string, $format_pad, digit, $pad)?;
20 }
21 }
22 f.pad_integral(
23 true,
24 $prefix,
25 if format_string.is_empty() {
26 "0"
27 } else {
28 &format_string
29 },
30 )
31 }
32 };
33 }
34
35 impl<const N: usize> Binary for $BUint<N> {
36 /*#[inline]
37 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
38 f.pad_integral(true, "0b", &self.to_str_radix(2))
39 }*/
40 fmt_method!("{:b}", "{:01$b}", digit::$Digit::BITS as usize, "0b");
41 }
42
43 impl<const N: usize> Debug for $BUint<N> {
44 #[inline]
45 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
46 Display::fmt(&self, f)
47 }
48 }
49
50 impl<const N: usize> Display for $BUint<N> {
51 /*#[inline]
52 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
53 if self.is_zero() {
54 return f.pad_integral(true, "", "0");
55 }
56 fn digit_to_byte(d: $Digit) -> u8 {
57 match d {
58 0 => 0 + 48,
59 1 => 1 + 48,
60 2 => 2 + 48,
61 3 => 3 + 48,
62 4 => 4 + 48,
63 5 => 5 + 48,
64 6 => 6 + 48,
65 7 => 7 + 48,
66 8 => 8 + 48,
67 9 => 9 + 48,
68 _ => unreachable!(),
69 }
70 }
71 let mut v: alloc::vec::Vec<u8> = alloc::vec::Vec::new();
72 let mut u = *self;
73 while !u.is_zero() {
74 let (q, r) = u.div_rem_digit(10);
75 v.push(digit_to_byte(r));
76 u = q;
77 }
78 v.reverse();
79 let s = unsafe { String::from_utf8_unchecked(v) };
80 //s.push(digit_to_char(u.digits[0]));
81 f.pad_integral(true, "", &s)
82 }*/
83 #[inline]
84 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
85 f.pad_integral(true, "", &self.to_str_radix(10))
86 }
87 }
88
89 macro_rules! exp_fmt {
90 ($e: expr) => {
91 #[inline]
92 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
93 let decimal_str = self.to_str_radix(10);
94 let buf = if decimal_str == "0" {
95 format!("{}{}0", 0, $e)
96 } else {
97 let exp = decimal_str.len() - 1;
98 let decimal_str = decimal_str.trim_end_matches('0');
99 if decimal_str.len() == 1 {
100 format!("{}{}{}", &decimal_str[0..1], $e, exp)
101 } else {
102 format!(
103 "{}.{}{}{}",
104 &decimal_str[0..1],
105 &decimal_str[1..],
106 $e,
107 exp
108 )
109 }
110 };
111 f.pad_integral(true, "", &buf)
112 }
113 };
114 }
115
116 impl<const N: usize> LowerExp for $BUint<N> {
117 exp_fmt!("e");
118 }
119
120 impl<const N: usize> LowerHex for $BUint<N> {
121 fmt_method!("{:x}", "{:01$x}", digit::$Digit::HEX_PADDING, "0x");
122 }
123
124 impl<const N: usize> Octal for $BUint<N> {
125 #[inline]
126 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
127 let string = self.to_str_radix(8);
128 f.pad_integral(true, "0o", &string)
129 }
130 }
131
132 impl<const N: usize> UpperExp for $BUint<N> {
133 exp_fmt!("E");
134 }
135
136 impl<const N: usize> UpperHex for $BUint<N> {
137 fmt_method!("{:X}", "{:01$X}", digit::$Digit::HEX_PADDING, "0x");
138 }
139
140 };
141}
142
143crate::macro_impl!(fmt);