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 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 f.pad_integral(true, "", &self.to_str_radix(10))
54 }
55 }
56
57 macro_rules! exp_fmt {
58 ($e: expr) => {
59 #[inline]
60 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
61 let decimal_str = self.to_str_radix(10);
62 let buf = if decimal_str == "0" {
63 format!("{}{}0", 0, $e)
64 } else {
65 let exp = decimal_str.len() - 1;
66 let decimal_str = decimal_str.trim_end_matches('0');
67 if decimal_str.len() == 1 {
68 format!("{}{}{}", &decimal_str[0..1], $e, exp)
69 } else {
70 format!(
71 "{}.{}{}{}",
72 &decimal_str[0..1],
73 &decimal_str[1..],
74 $e,
75 exp
76 )
77 }
78 };
79 f.pad_integral(true, "", &buf)
80 }
81 };
82 }
83
84 impl<const N: usize> LowerExp for $BUint<N> {
85 exp_fmt!("e");
86 }
87
88 impl<const N: usize> LowerHex for $BUint<N> {
89 fmt_method!("{:x}", "{:01$x}", digit::$Digit::HEX_PADDING, "0x");
90 }
91
92 impl<const N: usize> Octal for $BUint<N> {
93 #[inline]
94 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
95 let string = self.to_str_radix(8);
96 f.pad_integral(true, "0o", &string)
97 }
98 }
99
100 impl<const N: usize> UpperExp for $BUint<N> {
101 exp_fmt!("E");
102 }
103
104 impl<const N: usize> UpperHex for $BUint<N> {
105 fmt_method!("{:X}", "{:01$X}", digit::$Digit::HEX_PADDING, "0x");
106 }
107 };
108}
109
110#[cfg(test)]
111crate::test::all_digit_tests! {
112 crate::int::fmt::tests!(utest);
113}
114
115crate::macro_impl!(fmt);