rust - 使用 syn 获取 proc_macro_derive 结构的枚举字段的属性
问题描述
我正在为结构编写宏并实现基于字段类型的方法。例如u8
,Array
或str
。
假设我将此枚举表示为u32
。
#[repr(u32)]
#[derive(Debug, Clone, Copy)]
pub enum ServerGreetingMode {
Unavailable = 0,
Unauthenticated = 1,
Authenticated = 2,
Encrypted = 4,
}
我ToBytes
在结构字段上应用宏
#[repr(packed)]
#[derive(ToBytes, Debug, Clone, Copy)]
pub struct ServerGreetingFrame {
pub unused: [u8; 12],
pub mode: ServerGreetingMode,
pub challenge: [u8; 16],
pub salt: [u8; 16],
pub count: u32,
pub mbz: [u8; 12],
}
我能够将它放到我获得类型的部分,ServerGreetingMode
但我无法判断它是否是枚举。
这是我目前的实现。
#[proc_macro_derive(ToBytes)]
pub fn derive(tokens: TokenStream) -> TokenStream {
let tokens_item = tokens.clone();
let items = syn::parse_macro_input!(tokens_item as syn::Item);
let output = match items {
syn::Item::Struct(item) => {
let name = &item.ident;
let statements = match &item.fields {
syn::Fields::Named(ref fields) => {
// eprint!("{:#?}", field);
let vary_by_type = fields.named.iter().map(|field| {
let field_name = &field.ident;
let field_type = &field.ty;
let statement = match field_type {
syn::Type::Array(syn::TypeArray { elem, .. }) => {
let ty = elem.as_ref();
match ty {
syn::Type::Path(typepath)
if typepath.qself.is_none()
&& typepath.path.leading_colon.is_none()
&& typepath.path.segments.len() == 1 && typepath.path.is_ident("u8") =>
{
quote! {
bytes.extend_from_slice(&self.#field_name);
}
},
_ => todo!(),
}
}
syn::Type::Path(ty) if ty.path.clone().is_ident("u32") => {
quote! {
bytes.extend_from_slice(&(self.#field_name as u32).to_be_bytes().to_vec());
}
},
_ => todo!(),
};
statement
});
vary_by_type
}
_ => todo!(),
};
quote! {
impl #name {
fn to_bytes(&self) -> Vec<u8> {
let mut bytes: Vec<u8> = Vec::new();
#(
#statements
)*
bytes
}
}
}
}
_ => todo!(),
};
output.into()
// let s = syn::parse_macro_input!(tokens_struct as syn::ItemStruct);
// let n = &s.ident;
// let expanded = quote! {
// impl #n {
// fn to_bytes(&self) -> Vec<u8> {
// let mut bytes: Vec<u8> = Vec::new();
// bytes
// }
// }
// };
// expanded.into()
}
谢谢。
解决方案
推荐阅读
- typescript - 如何在 TypeScript 中键入独立对象?
- javafx - JavaFX 如何处理非常高帧率的输入?
- corda - 连接到设置为生产数据库的 Oracle 数据库时无法启动 Corda 节点
- spring-boot - 将 Spring Boot 2.4.x 连接到 neo4j-3.4.x
- angular - 注入 Angular 应用程序作为 iframe 在 chrome 中工作,但现在在 Mozilla Firefox 上工作
- apache-spark - Apache Spark Column 具有无法使用 PySpark 参与列存储索引的数据类型
- java - 在Java中,当字符串真的很大并且不再使用时,使用 new String() 而不是双引号是否有效?
- grails - 切换用户正在重定向到 grails 中登录控制器的身份验证方法
- javascript - Vanilla Javascript 如何覆盖事件侦听器上添加的功能?
- r - 使用特定条件过滤数据集中的行