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);