如何使用 quote crate 发出具有非十进制基数的整数文字?
How can I emit an integer literal with a non-decimal base using the quote crate?
我正在使用 quote 生成代码来解码汇编操作。我的芯片的使用说明书使用二进制值来描述操作,所以我希望我生成的代码也将文字表示为二进制值,以便我更容易抽查正确性。
我找不到指定它的方法。 proc_macro2::Literal
提供了多种方法来控制文字的 后缀 (u8
、i32
等),但我没有看到任何控制文字基础的东西。
我理想的格式是以 2 为基数,每四位使用一个下划线,并以适当的后缀结尾,但只需要基数。
use quote::quote; // 1.0.6
fn main() {
let value = 0b0101_0101_u8;
let code = format!("{}", quote! { #value });
assert_eq!("0b0101_0101_u8", code);
}
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `"0b0101_0101_u8"`,
right: `"85u8"`', src/main.rs:8:5
您可以使用 format!
将数字格式化为字符串,然后从中构造一个 TokenStream
,然后您可以在 quote!
:
中使用它
use proc_macro2::TokenStream;
use quote::quote; // 1.0.6
use std::str::FromStr;
fn main() {
let value = 0b0101_0101_u8;
let value_formatted = TokenStream::from_str(&format!("0b{:08b}_u8", value)).unwrap();
let code = format!(
"{}",
quote! {
#value_formatted
}
);
assert_eq!("0b01010101_u8", code);
}
format!
宏不支持下划线,但可以轻松扩展以使用自定义格式化程序插入下划线。
这是我制作的包装器类型,利用实现 with the underscore suggestion from E_net4:
use quote::quote; // 1.0.6
fn main() {
let value = AsBits(0b0101_0101_u8);
let code = format!("{}", quote! { #value });
assert_eq!("0b0101_0101_u8", code);
}
use proc_macro2::TokenStream; // 1.0.17
use quote::ToTokens; // 1.0.6
use std::str::FromStr;
struct AsBits<T>(T);
impl ToTokens for AsBits<u8> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let b = format!(
"0b{:04b}_{:04b}_u8",
(self.0 & 0xF0) >> 4,
(self.0 & 0x0F) >> 0,
);
tokens.extend(TokenStream::from_str(&b).unwrap());
}
}
我正在使用 quote 生成代码来解码汇编操作。我的芯片的使用说明书使用二进制值来描述操作,所以我希望我生成的代码也将文字表示为二进制值,以便我更容易抽查正确性。
我找不到指定它的方法。 proc_macro2::Literal
提供了多种方法来控制文字的 后缀 (u8
、i32
等),但我没有看到任何控制文字基础的东西。
我理想的格式是以 2 为基数,每四位使用一个下划线,并以适当的后缀结尾,但只需要基数。
use quote::quote; // 1.0.6
fn main() {
let value = 0b0101_0101_u8;
let code = format!("{}", quote! { #value });
assert_eq!("0b0101_0101_u8", code);
}
thread 'main' panicked at 'assertion failed: `(left == right)`
left: `"0b0101_0101_u8"`,
right: `"85u8"`', src/main.rs:8:5
您可以使用 format!
将数字格式化为字符串,然后从中构造一个 TokenStream
,然后您可以在 quote!
:
use proc_macro2::TokenStream;
use quote::quote; // 1.0.6
use std::str::FromStr;
fn main() {
let value = 0b0101_0101_u8;
let value_formatted = TokenStream::from_str(&format!("0b{:08b}_u8", value)).unwrap();
let code = format!(
"{}",
quote! {
#value_formatted
}
);
assert_eq!("0b01010101_u8", code);
}
format!
宏不支持下划线,但可以轻松扩展以使用自定义格式化程序插入下划线。
这是我制作的包装器类型,利用实现
use quote::quote; // 1.0.6
fn main() {
let value = AsBits(0b0101_0101_u8);
let code = format!("{}", quote! { #value });
assert_eq!("0b0101_0101_u8", code);
}
use proc_macro2::TokenStream; // 1.0.17
use quote::ToTokens; // 1.0.6
use std::str::FromStr;
struct AsBits<T>(T);
impl ToTokens for AsBits<u8> {
fn to_tokens(&self, tokens: &mut TokenStream) {
let b = format!(
"0b{:04b}_{:04b}_u8",
(self.0 & 0xF0) >> 4,
(self.0 & 0x0F) >> 0,
);
tokens.extend(TokenStream::from_str(&b).unwrap());
}
}