7个版本
0.3.1 | 2023年4月24日 |
---|---|
0.3.0 | 2023年3月21日 |
0.2.0 | 2021年10月27日 |
0.1.3 | 2021年8月27日 |
0.1.0 | 2021年6月25日 |
#95 in 过程宏
每月下载量116,302
在 2 个crates中使用(通过 cucumber-codegen)
110KB
2.5K SLoC
synthez
Steroids for syn
, quote
and proc_macro2
crates.
Cargo功能
full
与 syn
crate 的 full
功能相同。
启用支持表示所有有效Rust源代码语法树的复杂数据结构,包括项和表达式。
proc_macro_derive
编写示例
这是使用此库编写简化 proc_macro_derive
以生成 From
实现的示例。
# use std::collections::HashMap;
#
# use synthez::{proc_macro2::{Span, TokenStream}, quote::quote, syn};
use synthez::{DataExt as _, ParseAttrs, ToTokens};
pub fn derive(input: syn::DeriveInput) -> syn::Result<TokenStream> {
let attrs = Attrs::parse_attrs("from", &input)?;
match (attrs.forward.is_some(), !attrs.custom.is_empty()) {
(true, true) => Err(syn::Error::new_spanned(
input,
"`forward` and `on` arguments are mutually exclusive",
)),
(false, false) => Err(syn::Error::new_spanned(
input,
"either `forward` or `on` argument is expected",
)),
// #[from(forward)]
(true, _) => {
if !matches!(&input.data, syn::Data::Struct(_)) {
return Err(syn::Error::new_spanned(
input,
"only tuple structs can forward-derive From",
));
}
let fields = input.data.unnamed_fields()?;
if fields.len() > 1 {
return Err(syn::Error::new_spanned(
fields,
"only single-field tuple structs can forward-derive \
From",
));
}
let definition = ForwardDefinition {
ty: input.ident,
inner_ty: fields.into_iter().last().unwrap().ty,
};
Ok(quote! {
#definition
})
}
// #[from(on <type> = <func>)]
(_, true) => {
let definitions =
CustomDefinitions { ty: input.ident, funcs: attrs.custom };
Ok(quote! {
#definitions
})
}
}
}
#[derive(Default, ParseAttrs)]
struct Attrs {
#[parse(ident)]
forward: Option<syn::Ident>,
#[parse(map, arg = on)]
custom: HashMap<syn::Type, syn::Expr>,
}
#[derive(ToTokens)]
#[to_tokens(append(impl_from))]
struct ForwardDefinition {
ty: syn::Ident,
inner_ty: syn::Type,
}
impl ForwardDefinition {
fn impl_from(&self) -> TokenStream {
let (ty, inner_ty) = (&self.ty, &self.inner_ty);
quote! {
impl<T> From<T> for #ty where #inner_ty: From<T> {
fn from(v: T) -> Self {
Self(v.into())
}
}
}
}
}
#[derive(ToTokens)]
#[to_tokens(append(impl_froms))]
struct CustomDefinitions {
ty: syn::Ident,
funcs: HashMap<syn::Type, syn::Expr>,
}
impl CustomDefinitions {
fn impl_froms(&self) -> TokenStream {
let ty = &self.ty;
// We sort here for tests below not failing due to undetermined
// order only. Real implementation may omit this.
let mut sorted = self.funcs.iter().collect::<Vec<_>>();
sorted.sort_unstable_by(|(ty1, _), (ty2, _)| {
quote!(#ty1).to_string().cmp("e!(#ty2).to_string())
});
let impls = sorted.into_iter().map(move |(from_ty, func)| {
quote! {
impl From<#from_ty> for #ty {
fn from(v: #from_ty) -> Self {
#func(v)
}
}
}
});
quote! { #( #impls )* }
}
}
# fn main() {
let input = syn::parse_quote! {
#[derive(From)]
#[from(forward)]
struct Id(u64);
};
let output = quote! {
impl<T> From<T> for Id where u64: From<T> {
fn from(v: T) -> Self {
Self(v.into())
}
}
};
assert_eq!(derive(input).unwrap().to_string(), output.to_string());
let input = syn::parse_quote! {
#[derive(From)]
#[from(on bool = Self::parse_bool)]
#[from(on u8 = from_u8_to_maybe)]
enum Maybe {
Yes,
No,
}
};
let output = quote! {
impl From<bool> for Maybe {
fn from(v: bool) -> Self {
Self::parse_bool(v)
}
}
impl From<u8> for Maybe {
fn from(v: u8) -> Self {
from_u8_to_maybe(v)
}
}
};
assert_eq!(derive(input).unwrap().to_string(), output.to_string());
# }
许可证
此软件受 Blue Oak Model License 1.0.0 条款的约束。如果此文件未附带 BlueOak-1.0.0 许可证的副本,您可以从 https://blueoakcouncil.org/license/1.0.0 获取一个。
依赖项
~335–800KB
~19K SLoC