使用Proc宏在Rust中进行快速简单的渲染

使用Proc宏在Rust中进行快速简单的渲染

我最近一直在从事一个名为Thruster的项目,并且需要一种开发人员可以合理使用模板的方式。 Thruster是一个用Rust编写的基于中间件的Web服务器(得到它,th-rust-er吗?我正在The Apollo上度过业余5晚上的紧缩5),因此,我需要一种加载HTML模板并插入的方法变量以一种高效的方式进入它们。 与其四处逛逛现有的众多库,然后选择一个我不认识的人制造的库,不如说是陌生的危险! 我决定自己做。 本文是关于这一旅程的,这是在Rust中编写我的第一个proc_macro_derive令人难以置信的惊险冒险。 提示印第安纳琼斯音乐

您需要知道的第一件事是,我不是我所说的系统专家。 我之所以选择rust,是因为我想要一种基于性能的更新语言,但实际上我是一名Web开发人员。 我已经可以通过互联网管道听到你的盐分了; “为什么我会从网络开发人员那里征求意见? 他可能只想谈论箭头功能以及他这一代人如何发现功能编程 。” 好吧,你是对的。 我只是想谈一谈,但是我也在鳄梨烤面包中,我的生活教练说我应该专心致志,而不是谈论榆木。

我之所以说自己是一名Web开发人员,是因为我在Web框架中寻找的第一件事之一就是该框架的开发有多么复杂,以及框架的组成和移动部分有多容易。 有时候,我希望能够复制/粘贴已经在不同项目中编写的代码,而不必重新计算将人送上月球的轨迹。

您应该知道的第二件事是Rust很棒,即使我什至看起来要谈论它的存储安全性或超快的速度,我的同事们都想砸死我的鞋子,但我对它的热爱仍在继续比一千个太阳更明亮。

太好了,既然the悔室已经挡不住了,我们实际上可以深入研究该项目的实质; proc_macro_derive 程序宏(以及通常的宏)是令人着迷的生物。 许多来自其他语言的开发人员会睁大眼睛,并记得每次调试一个神秘的宏时都需要记住,但是Rust却有所不同。 从文档:

…铁锈有卫生的宏观体系 每个宏扩展都发生在不同的“语法上下文”中,并且每个变量都在引入变量的语法上下文中进行了标记。

这是我想为宏完成的工作:

  • 它应该在编译过程中而不是在运行时从文件中提取模板。
  • 它是类型安全的,即我不会惊慌! 或在运行时期间渲染的模板中出现一些奇怪的undefined类型文本。
  • 很快

不幸的是,这里的第一个要点是仅对常规的旧宏打折,因此我不得不开始研究程序宏。 本质上具有额外逻辑的宏可以在编译过程中引入,并实际上会更改代码的AST。

程序宏是特殊的野兽,因此,首先,我需要声明我的代码是Cargo.toml文件中的特殊雪花:

[lib]
proc-macro = true

我还提供了一些方便的花花公子包,用于从人类代码(oxymoron?)转换为生锈的AST,然后再次返回synquote

syn = "0.13.1"
quote = "0.5.1"

接下来,我启动了实际宏的代码。 这里要做出的重要区别是不同类型的过程宏之间的区别。 我将其保留在这里,因为有人已经在Rust Dark Arts书: The Unstable Book中为我完成了工作。

长话短说-我决定制作一个自定义派生程序宏! 这意味着我的代码看起来像这样开始:

至此,我有一种方法可以将自定义实现添加到结构中,而这正是您要为其使用派生的对象。 很好,但是我仍然希望能够从文件中加载模板。 问题是,世界上如何获取要加载的模板的名称?

好吧,对我们来说幸运的是,我们在编译器领域(比Candy Land更糟糕),因此我们也可以添加额外的属性。 这是带有添加的TemplateName属性的代码,用于获取模板

是的,我知道顶部有点乱。 就像我的车库和我的办公桌在工作一样,我会在有空的时候去清理它。 我在这里所做的是遍历传递的结构上的属性,以便找到TemplateName属性。 然后,我基于该字符串加载文件的内容,并将其传递到我们用quote!令牌流中quote!

最后一步是进行实际的插值,虽然有点混乱,但操作起来相对简单。 要记住的重要一点是,从quote!传回的内容之外的所有内容quote! 将在编译时完成,反之亦然。 请注意,上面的示例实际上并未包含插值,而是指向GitHub上已发布包的源的链接

您已经完成了。 您遵循了我分散的逻辑,并用强硬的言辞将最终的表情从纳粹的脸上融化了(您不认为我在第一段中就忘记了印第安纳·琼斯的提法,对吗?)锈; 它们具有安全卫生的类型,但不是灵丹妙药。 对于开发人员的安全以及任何必须维护您的代码的人来说,它们的能力受到限制。 但是,如果存在在编译时可以确定的问题,那么它们是一个非常不错的工具。

您可以在以下位置找到代码: https : //github.com/trezm/fuel-line和此处的合适货运包装: https : //crates.io/crates/fuel_line和此处: https : //crates.io/crates/ fuel_line_derive

From: https://hackernoon.com/fast-and-simple-rendering-in-rust-using-proc-macros-f0d919eb6475