ethnum/macros/
fmt.rs

1//! Module containing macros for implementing `core::fmt` traits.
2
3macro_rules! impl_fmt {
4    (impl Fmt for $int:ident;) => {
5        __impl_fmt_base! { Binary   for $int }
6        __impl_fmt_base! { Octal    for $int }
7        __impl_fmt_base! { LowerHex for $int }
8        __impl_fmt_base! { UpperHex for $int }
9
10        impl ::core::fmt::Debug for $int {
11            #[inline]
12            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
13                // NOTE: Work around `Formatter::debug_{lower,upper}_hex` being private
14                // and not stabilized.
15                #[allow(deprecated)]
16                let flags = f.flags();
17                const DEBUG_LOWER_HEX: u32 = 1 << 4;
18                const DEBUG_UPPER_HEX: u32 = 1 << 5;
19
20                if flags & DEBUG_LOWER_HEX != 0 {
21                    ::core::fmt::LowerHex::fmt(self, f)
22                } else if flags & DEBUG_UPPER_HEX != 0 {
23                    ::core::fmt::UpperHex::fmt(self, f)
24                } else {
25                    ::core::fmt::Display::fmt(self, f)
26                }
27            }
28        }
29
30        impl ::core::fmt::Display for $int {
31            #[allow(unused_comparisons, unused_imports)]
32            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
33                use $crate::uint::AsU256;
34
35                let is_nonnegative = *self >= 0;
36                let n = if is_nonnegative {
37                    self.as_u256()
38                } else {
39                    // convert the negative num to positive by summing 1 to it's 2 complement
40                    (!self.as_u256()).wrapping_add($crate::uint::U256::ONE)
41                };
42                $crate::fmt::fmt_u256(n, is_nonnegative, f)
43            }
44        }
45
46        impl ::core::fmt::LowerExp for $int {
47            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
48                // TODO(nlordell): Ideally this should be implemented similarly
49                // to the primitive integer types as seen here:
50                // https://doc.rust-lang.org/src/core/fmt/num.rs.html#274
51                // Unfortunately, just porting this implementation is not
52                // possible as it requires private standard library items. For
53                // now, just convert to a `f64` as an approximation.
54                ::core::fmt::LowerExp::fmt(&self.as_f64(), f)
55            }
56        }
57
58        impl ::core::fmt::UpperExp for $int {
59            fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
60                ::core::fmt::UpperExp::fmt(&self.as_f64(), f)
61            }
62        }
63    };
64}
65
66macro_rules! __impl_fmt_base {
67    ($base:ident for $int:ident) => {
68        impl ::core::fmt::$base for $int {
69            #[allow(unused_imports)]
70            fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
71                use $crate::{fmt::GenericRadix, uint::AsU256};
72                let (abs, is_nonnegative) = if *self < 0 && f.sign_minus() {
73                    // NOTE(nlordell): This is non-standard break from the Rust
74                    // standard integer types, but allows `format!("{val:-#x")`
75                    // notation for formating a number as `-0x...` (and in
76                    // in general prefix with a `-` sign for negative numbers
77                    // with radix formatting.
78                    (self.wrapping_neg(), false)
79                } else {
80                    (*self, true)
81                };
82                $crate::fmt::$base.fmt_u256(abs.as_u256(), is_nonnegative, f)
83            }
84        }
85    };
86}