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相关推荐

  1. 梦想Android版CAD控件2022.11.14更新(安卓CAD控件,苹果CAD控件)

    下载试用地址:https://www.mxdraw.com/ndetail_30232.html 1.增加SetUserInputArrowLineWidth,setUserInputCircleTy ...

  2. 文献阅读笔记(2022.11.14)

    1 基本信息 文献名:<Subjective sleep alterations in healthy subjects worldwide during COVID-19 pandemic: ...

  3. 2022.11.14每日刷题打卡

    过山车 原题链接:传送门 二分图最大匹配模板题,但sb了数组开小了一直TLE,虽然是模板但很长教训. #include <bits/stdc++.h> using namespace st ...

  4. 第11章 Go语言文件处理

    本章我们将带领大家深入了解一下 Go语言中的文件处理,重点在于文件而非目录或者通用的文件系统,特别是如何读写标准格式(如 XML 和 JSON 格式)的文件以及自定义的纯文本和二进制格式文件. 由于前 ...

  5. 腾讯通报内部反腐情况:开出48人惩治名单;华为预计2022年全员每股分红1.61元;Chromium使用Rust语言|极客头条

    「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 梦依丹 出品 | CSDN(ID:CSDNnews ...

  6. RUST语言的编程范式

    总是有很多很多人来问我对Rust语言怎么看的问题,在各种地方被at,其实,我不是很想表达我的想法.因为在不同的角度,你会看到不同的东西.编程语言这个东西,老实说很难评价,在学术上来说,Lisp就是很好 ...

  7. 想要改变世界的 Rust 语言

    一门编程语言就像一个小宇宙,语言中的各种语法概念就像一颗颗星辰.对于初学者来说,看这些语法概念与看星罗棋布时产生的迷惑是相似的.幸亏编程语言是由人类创造的,编程语言的作者可以被找到,编程语言的源码也可 ...

  8. 思科学院cisco独家整理题库(2022.11.7更新)

    1.必须通过 IPv6 访问控制列表允许哪些两种 ICMPv6 消息类型才能将第 3 层地址解析为第 2 层 MAC 地址?(选择两个). 邻居招揽 回声请求 邻居广告 回声回复 路由器请求 路由器播 ...

  9. 腾讯云运维工程师认证TCA--真题(最新2022.11)

    腾讯云运维工程师认证TCA题库,覆盖95%题目. 1.TSF控制台的配置中心,目前支持以下哪一种格式的配置文件? JSON格式 XML格式 YAML格式 Properties配置格式 正确答案:C 解 ...

最新文章

  1. MIT提出Liquid机器学习系统,可像液体一样适应动态变化
  2. Java多线程闲聊(五):AQS
  3. Visual Studio 15.4发布,新增多平台支持
  4. virtualBox linux操作系统centos 挂载光盘
  5. python中冒号报错_python中一些常见的错误_后端开发
  6. JS switch 分支语句
  7. JAVA浅层复制深层复制理解-java_01_20160824
  8. cad刷新快捷键_100个快捷键50个CAD技巧,助你玩转CAD
  9. 项目汇报模板—再也不怕撕逼了
  10. linux两台服务器文件实时同步
  11. “店小二”精神国际化步伐23年成就巨无霸
  12. 使用STAR进行RNA-seq数据比对
  13. 使用MySql计算两个日期的时间差函数:TIMESTAMPDIFF
  14. php+条形码在线怎么生成,php实现在线生成条形码示例分享(条形码生成器)
  15. 使用HttpURLConnection 越过ssl证书访问htts协议接口
  16. 方法参数中pass by reference(传引用)和 pass by value(传值)的区别
  17. iBus拼音输入法导入搜狗词库
  18. 支持向量机 4 模式识别的方法
  19. Centos 7 装 Steam( 需要:libva-intel-driver(x86-32))
  20. VC动态更改窗口图标

热门文章

  1. android 图片闪光动画_剖析Android动画(图片闪烁、左右摇摆、上下晃动等效果) | 学步园...
  2. 二次元人物头发怎么画?男性头发如何上色?
  3. Excel 将数字格式中的e+14转换为文本数字格式
  4. 一个简洁的高自定义的H5播放器
  5. 太好了!好多好多偏方
  6. NAudio 播放流、字节数组(非wav、mp3、aiff格式)
  7. Vue最新状态管理工具Pinia——彻底搞懂Pinia是什么
  8. 用Python写了个绝地求生(附源码)
  9. linux跑火车的命令sl
  10. vue 图片指定大小压缩