Skip to main content

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