proc-macro-workshop:builder-1

基础宏分类

  1. 申明宏
    申明宏主要是macro_rules!所定义的符合rust语法的词法替换工具。
    常用的有format!println!等等
  2. 过程宏
    过程宏相较于申明宏,不仅是类别更多,更多应用场景,也更为复杂,你甚至可以自定义额外语法。
    • 派生宏:常用的使用derive进行标记的宏,rust自动提供的诸如Debug,Eq等。
    • 属性宏:和派生宏#[derive(XXX)]相似,但是整体结构为#[...]内部信息都可以自定义,比如#[sorted]
    • 函数式宏:函数式宏使用方法和申明宏相似seq!,但是功能天差地别,你甚至可以自定义语法,而申明宏不能。(如果你不在申明宏中调用过程宏的话)。

proc-macro-workshop

proc-macro-workshopdtolnay大神为菜鸟学习rust-macro而创建的教学性质仓库。根据提示不断的进行学习和作答,从而逐渐掌握rust宏的编写。

因为常见的rust代码、框架中总是充斥着各种各样的宏,总是勾引我的好奇心,分散注意力,因此我觉得有必要先对基本的宏进行学习,只有明白它的实现原理,能基本实现简单的宏,在使用的时候才能做到“手有余粮,心中不慌”的坦然境界。

基础工程

  1. 独立项目:自定义宏一般不能在当前项目中,因为需要提前编译
  2. 基础引入:
    proc-macro-workshop:builder-1
    需要申明使用基础的proc-macro
  3. 常用的三方库:synquote都是dtolany大佬的作品,这让我们自定义宏的时候更加的方便。
    cargo install cargo-edit cargo-expand

    安装 cargo-edit以后,我们可以简单的引入第三方依赖cargo add syn quote
    安装cargo-expand以后,我们可以通过cargo expand对我们宏作用的代码进行展开,观察它具体的作用效果。

  4. 项目结构说明

proc-macro-workshop:builder-1

可以看到,整体项目为我们准备了难题,依次是

  • builder
  • debug
  • seq
  • sorted
  • bitfield
    网上有很多详尽的版本,但是我这里只为应付测试,只做最基础的了解,通过即可。有兴趣的小伙伴可以自行加深,如有受过,还请不吝赐教。

每个项目之下,会有多个测试用例,也就是相当于我们的关卡,完成一关,就在progress.rs中打开一个用例即可。
每个用例中有相关的提示。

builder-1题解

// This test looks for a derive macro with the right name to exist. For now the
// test doesn't require any specific code to be generated by the macro, so
// returning an empty TokenStream should be sufficient.
//
// Before moving on, have your derive macro parse the macro input as a
// syn::DeriveInput syntax tree.
//
// Spend some time exploring the syn::DeriveInput struct on docs.rs by clicking
// through its fields in the documentation to see whether it matches your
// expectations for what information is available for the macro to work with.
//
//
// Resources:
//
//   - The Syn crate for parsing procedural macro input:
//     https://github.com/dtolnay/syn
//
//   - The DeriveInput syntax tree which represents input of a derive macro:
//     https://docs.rs/syn/1.0/syn/struct.DeriveInput.html
//
//   - An example of a derive macro implemented using Syn:
//     https://github.com/dtolnay/syn/tree/master/examples/heapsize

use derive_builder::Builder;

#[derive(Builder)]
pub struct Command {
    executable: String,
    args: Vec<String>,
    env: Vec<String>,
    current_dir: String,
}

fn main() {}

提示中说了,我们不需要做任何操作,只需要returning an empty TokenStream,但是建议我们先解析一下syn::DeriveInput和熟悉一下这三个东西

有兴趣的小伙伴可以自行阅读,这里还是以为测试用例为主线,只关注涉及的相关知识。

#[proc_macro_derive(Builder)]

pub  fn  derive(input: proc_macro::TokenStream) ->  proc_macro::TokenStream {
    // 解析一下input as DeriveInput
    let _ = syn::parse_macro_input!(input as syn::DeriveInput);
    // 返回一下空结果
    proc_macro::TokenStream::new()
}

做刚好的问题的解就好,后续每一关,单独拎出来详细讲解,慢慢水下去。

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!