1mod private {
16 pub struct Sealed;
18}
19
20pub trait HexLiteral {
22 #[doc(hidden)]
28 fn hex_impl_(
29 self,
30 fmt: ::core::fmt::Arguments,
31 sealed: private::Sealed,
32 ) -> syn::LitInt;
33
34 fn hex_suffixed(self) -> syn::LitInt;
36
37 fn hex_unsuffixed(self) -> syn::LitInt;
39
40 fn hex_padded_suffixed(self) -> syn::LitInt;
44
45 fn hex_padded_unsuffixed(self) -> syn::LitInt;
49}
50
51macro_rules! generate_hex_literal_impls {
52 ( $( ($ty:ty, $name:literal, $fmt_suffixed:literal, $fmt_unsuffixed:literal) ),* $(,)? ) => {
53 $(
54 impl HexLiteral for $ty {
55 fn hex_impl_(self, fmt: ::core::fmt::Arguments, _sealed: private::Sealed) -> syn::LitInt {
56 ::syn::LitInt::new(
57 &::std::format!("{}", fmt),
58 proc_macro2::Span::call_site()
59 )
60 }
61
62 fn hex_suffixed(self) -> syn::LitInt {
63 self.hex_impl_(::core::format_args!("0x{:X}_{}", self, $name), private::Sealed)
64 }
65
66 fn hex_unsuffixed(self) -> syn::LitInt {
67 self.hex_impl_(::core::format_args!("0x{:X}", self), private::Sealed)
68 }
69
70 fn hex_padded_suffixed(self) -> syn::LitInt {
71 self.hex_impl_(::core::format_args!($fmt_suffixed, self, $name), private::Sealed)
72 }
73
74 fn hex_padded_unsuffixed(self) -> syn::LitInt {
75 self.hex_impl_(::core::format_args!($fmt_unsuffixed, self), private::Sealed)
76 }
77 }
78 )*
79 };
80}
81#[rustfmt::skip]
82generate_hex_literal_impls!(
83 (::core::primitive::i8 , "i8", "0x{:02X}_{}", "0x{:02X}"),
84 (::core::primitive::u8 , "u8", "0x{:02X}_{}", "0x{:02X}"),
85 (::core::primitive::i16, "i16", "0x{:04X}_{}", "0x{:04X}"),
86 (::core::primitive::u16, "u16", "0x{:04X}_{}", "0x{:04X}"),
87 (::core::primitive::i32, "i32", "0x{:08X}_{}", "0x{:08X}"),
88 (::core::primitive::u32, "u32", "0x{:08X}_{}", "0x{:08X}"),
89 (::core::primitive::i64, "i64", "0x{:016X}_{}", "0x{:016X}"),
90 (::core::primitive::u64, "u64", "0x{:016X}_{}", "0x{:016X}"),
91 (::core::primitive::i128, "i128", "0x{:032X}_{}", "0x{:032X}"),
92 (::core::primitive::u128, "u128", "0x{:032X}_{}", "0x{:032X}"),
93);
94#[cfg(target_pointer_width = "16")]
95generate_hex_literal_impls!(
96 (::core::primitive::usize, "usize", "0x{:04X}_{}", "0x{:04X}"),
97 (::core::primitive::isize, "isize", "0x{:04X}_{}", "0x{:04X}"),
98);
99#[cfg(target_pointer_width = "32")]
100generate_hex_literal_impls!(
101 (::core::primitive::usize, "usize", "0x{:08X}_{}", "0x{:08X}"),
102 (::core::primitive::isize, "isize", "0x{:08X}_{}", "0x{:08X}"),
103);
104#[cfg(target_pointer_width = "64")]
105generate_hex_literal_impls!(
106 (::core::primitive::usize, "usize", "0x{:16X}_{}", "0x{:16X}"),
107 (::core::primitive::isize, "isize", "0x{:16X}_{}", "0x{:16X}"),
108);
109
110#[cfg(test)]
111mod tests {
112 use super::HexLiteral as _;
113 use quote::quote;
114
115 fn assert_quote(given: syn::LitInt, expected: &str) {
116 assert_eq!(quote!(#given).to_string(), expected);
117 }
118
119 #[test]
120 fn simple() {
121 let value = 0x42_i32;
122 assert_eq!(quote!(#value).to_string(), "66i32");
123 assert_quote(value.hex_suffixed(), "0x42_i32");
124 assert_quote(value.hex_unsuffixed(), "0x42");
125 assert_quote(value.hex_padded_suffixed(), "0x00000042_i32");
126 assert_quote(value.hex_padded_unsuffixed(), "0x00000042");
127 }
128
129 #[test]
130 fn code_cafe() {
131 let value = 0xC0DE_CAFE_u32;
132 assert_quote(value.hex_suffixed(), "0xC0DECAFE_u32");
133 assert_quote(value.hex_padded_suffixed(), "0xC0DECAFE_u32");
134 assert_quote(value.hex_unsuffixed(), "0xC0DECAFE");
135 assert_quote(value.hex_padded_unsuffixed(), "0xC0DECAFE");
136 }
137}