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