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