1 个不稳定版本
0.1.0 | 2019年8月25日 |
---|
#1814 在 过程宏
2,056 每月下载量
在 3 个 crate 中使用(2 个直接使用)
47KB
868 代码行数(不含注释)
serde_syn
serde_syn 是一个用于在过程宏内部解析 Rust 语法的 serde 后端。例如,您可以将自定义 derive 的参数从属性直接解析到结构体中。目标是消除编写过程宏时所需的解析样板代码。
serde_syn 的接口相当简单。以下是一些使用方法
- syn 需要
Parser
实现来处理已解析/访问过的 attributes 内部的语法。函数parser
正好可以做到这一点! - 如果您正在直接处理
proc_macro/
标记流或字符串,也应使用proc_macro2
parser
。 - 如果您正在自己实现 syn 的 Parse trait,则应使用
from_stream
函数,它接受一个ParseStream
。
config
模块内部存在许多针对常见语法(如 JSON 类似、属性类似、表达式类似等)的预先配置,或者您可以组合标志来构建自己的配置。
示例 derive 实现
在这里,您可以看到一个简单的 derive 宏实现。更多示例,请参阅 示例目录。
#
#
/// The format of `named` attributes.
#[derive(Deserialize)]
struct Props {
rename: Option<String>, // #[named(rename="hello")]
lowercase: Option<()>, // #[named(lowercase)]
}
#[proc_macro_derive(NamedType, attributes(named))]
pub fn my_macro(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let mut name = input.ident.to_string();
for attr in input.attrs.iter().filter(|a| a.path.is_ident("named")) {
let parser = parser::<Props>(config::RUSTY_META);
let props = match attr.parse_args_with(parser) {
Ok(props) => props,
Err(err) => return err.to_compile_error().into(),
};
if let Some(rename) = props.rename { name = rename; }
if props.lowercase.is_some() { name = name.to_lowercase(); }
}
let ident = &input.ident;
(quote! {
impl NamedType for #ident {
fn name() -> &'static str { #name }
}
}).into()
}
错误处理
反序列化错误在从parser
和from_stream
返回之前,会自动分配一个"span"(无法解析的源代码区域),然后以普通syn::Error
的形式返回。当该错误报告给Rust编译器时,正确的代码区域将被突出显示
error: unknown field `lowrcase`, expected `rename` or `lowercase`
--> named_type.rs:4:13
|
4 | #[named(lowrcase)]
| ^^^^^^^^
如果您直接使用Deserializer
,serde_syn会尽力分配一个span,但总是可以使用serde所需的custom
函数创建一个没有span的错误。
限制
serde_syn处于早期开发阶段,因此仍然存在一些问题。例如,如果您尝试将数据反序列化到serde_json Value
,serde_syn将会抛出一个错误,因为它还不支持自我描述。
如果您发现任何错误,有任何想法,或者有空闲时间帮助随机的开源项目,请访问存储库。
依赖关系
~2MB
~43K SLoC