2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru
Posted 福大大架构师每日一题
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru相关的知识,希望对你有一定的参考价值。
2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。
宏使用如下:
#[derive(Builder)]
pub struct AAA
a: String,
b: i32,
c: f64,
d: Vec<bool>,
宏展开后变成如下代码:
pub struct AAA
a: String,
b: i32,
c: f64,
d: Vec<bool>,
pub struct AAABuilder
a: std::option::Option<String>,
b: std::option::Option<i32>,
c: std::option::Option<f64>,
d: std::option::Option<Vec<bool>>,
impl AAA
pub fn builder() -> AAABuilder
AAABuilder
a: std::option::Option::None,
b: std::option::Option::None,
c: std::option::Option::None,
d: std::option::Option::None,
答案2022-11-14:
这题没啥技巧,自然智慧即可。
代码用rust编写。代码如下:
// builder/src/lib.rs
use proc_macro::TokenStream;
use quote;
use syn::spanned::Spanned;
#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream
let st = syn::parse_macro_input!(input as syn::DeriveInput);
match expand_code(&st)
Ok(token_stream) => token_stream.into(),
Err(e) => e.to_compile_error().into(),
fn get_fields(
st: &syn::DeriveInput,
) -> syn::Result<&syn::punctuated::Punctuated<syn::Field, syn::Token![,]>>
if let syn::Data::Struct(syn::DataStruct
fields: syn::Fields::Named(syn::FieldsNamed ref named, .. ),
..
) = st.data
return Ok(named);
;
Err(syn::Error::new_spanned(st, "必须定义在结构体上"))
fn gen_fields(st: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
let fields = get_fields(st)?;
let idents: Vec<_> = fields.iter().map(|f| &f.ident).collect();
let types: Vec<_> = fields.iter().map(|f| &f.ty).collect();
let ret = quote::quote!(
#( #idents: std::option::Option<#types>),*
);
return Ok(ret);
fn gen_init_clauses(st: &syn::DeriveInput) -> syn::Result<Vec<proc_macro2::TokenStream>>
let fields = get_fields(st)?;
let init_cluase: Vec<_> = fields
.iter()
.map(|f|
let ident = &f.ident;
quote::quote!(
#ident: std::option::Option::None
)
)
.collect();
Ok(init_cluase)
fn expand_code(st: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream>
let struct_name_literal = st.ident.to_string();
let builder_name_literal = format!("Builder", struct_name_literal);
let builder_name_ident = syn::Ident::new(&builder_name_literal, st.span());
let struct_ident = &st.ident;
let builder_struct_field_def = gen_fields(st)?;
let builder_struct_factory_init_clauses = gen_init_clauses(st)?;
let ret = quote::quote!(
pub struct #builder_name_ident
#builder_struct_field_def
impl #struct_ident
pub fn builder() -> #builder_name_ident
#builder_name_ident
#(#builder_struct_factory_init_clauses),*
);
Ok(ret)
# builder.Cargo.toml
[package]
name = "derive_builder"
version = "0.0.0"
autotests = false
edition = "2021"
publish = false
[lib]
proc-macro = true
[[test]]
name = "tests"
path = "tests/progress.rs"
[dev-dependencies]
trybuild = version = "1.0.49", features = ["diff"]
[dependencies]
syn = version="1.0",features=["extra-traits"]
proc-macro2 = version="1.0"
quote = version="1.0"
use derive_builder::Builder;
#[derive(Builder)]
pub struct AAA
a: String,
b: i32,
c: f64,
d: Vec<bool>,
fn main()
let builder = AAA::builder();
let _ = builder;
# Cargo.toml
[package]
name = "proc-macro-workshop"
version = "0.0.0"
edition = "2021"
publish = false
[workspace]
[[bin]]
name = "workshop"
path = "main.rs"
[dependencies]
bitfield = path = "bitfield"
derive_builder = path = "builder"
derive_debug = path = "debug"
seq = path = "seq"
sorted = path = "sorted"
敲cargo expand命令后,打印如下:
以上是关于2022-11-14:rust语言,请使用过程宏给结构体AAA生成结构体AAABuilder和创建AAABuilder实例的方法。 宏使用如下: #[derive(Builder)] pub stru的主要内容,如果未能解决你的问题,请参考以下文章