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相关推荐
- 梦想Android版CAD控件2022.11.14更新(安卓CAD控件,苹果CAD控件)
下载试用地址:https://www.mxdraw.com/ndetail_30232.html 1.增加SetUserInputArrowLineWidth,setUserInputCircleTy ...
- 文献阅读笔记(2022.11.14)
1 基本信息 文献名:<Subjective sleep alterations in healthy subjects worldwide during COVID-19 pandemic: ...
- 2022.11.14每日刷题打卡
过山车 原题链接:传送门 二分图最大匹配模板题,但sb了数组开小了一直TLE,虽然是模板但很长教训. #include <bits/stdc++.h> using namespace st ...
- 第11章 Go语言文件处理
本章我们将带领大家深入了解一下 Go语言中的文件处理,重点在于文件而非目录或者通用的文件系统,特别是如何读写标准格式(如 XML 和 JSON 格式)的文件以及自定义的纯文本和二进制格式文件. 由于前 ...
- 腾讯通报内部反腐情况:开出48人惩治名单;华为预计2022年全员每股分红1.61元;Chromium使用Rust语言|极客头条
「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 梦依丹 出品 | CSDN(ID:CSDNnews ...
- RUST语言的编程范式
总是有很多很多人来问我对Rust语言怎么看的问题,在各种地方被at,其实,我不是很想表达我的想法.因为在不同的角度,你会看到不同的东西.编程语言这个东西,老实说很难评价,在学术上来说,Lisp就是很好 ...
- 想要改变世界的 Rust 语言
一门编程语言就像一个小宇宙,语言中的各种语法概念就像一颗颗星辰.对于初学者来说,看这些语法概念与看星罗棋布时产生的迷惑是相似的.幸亏编程语言是由人类创造的,编程语言的作者可以被找到,编程语言的源码也可 ...
- 思科学院cisco独家整理题库(2022.11.7更新)
1.必须通过 IPv6 访问控制列表允许哪些两种 ICMPv6 消息类型才能将第 3 层地址解析为第 2 层 MAC 地址?(选择两个). 邻居招揽 回声请求 邻居广告 回声回复 路由器请求 路由器播 ...
- 腾讯云运维工程师认证TCA--真题(最新2022.11)
腾讯云运维工程师认证TCA题库,覆盖95%题目. 1.TSF控制台的配置中心,目前支持以下哪一种格式的配置文件? JSON格式 XML格式 YAML格式 Properties配置格式 正确答案:C 解 ...
最新文章
- MIT提出Liquid机器学习系统,可像液体一样适应动态变化
- Java多线程闲聊(五):AQS
- Visual Studio 15.4发布,新增多平台支持
- virtualBox linux操作系统centos 挂载光盘
- python中冒号报错_python中一些常见的错误_后端开发
- JS switch 分支语句
- JAVA浅层复制深层复制理解-java_01_20160824
- cad刷新快捷键_100个快捷键50个CAD技巧,助你玩转CAD
- 项目汇报模板—再也不怕撕逼了
- linux两台服务器文件实时同步
- “店小二”精神国际化步伐23年成就巨无霸
- 使用STAR进行RNA-seq数据比对
- 使用MySql计算两个日期的时间差函数:TIMESTAMPDIFF
- php+条形码在线怎么生成,php实现在线生成条形码示例分享(条形码生成器)
- 使用HttpURLConnection 越过ssl证书访问htts协议接口
- 方法参数中pass by reference(传引用)和 pass by value(传值)的区别
- iBus拼音输入法导入搜狗词库
- 支持向量机 4 模式识别的方法
- Centos 7 装 Steam( 需要:libva-intel-driver(x86-32))
- VC动态更改窗口图标