上一篇文章中,简单介绍了 Rhai 脚本引擎的作用和功能,详见 Rhai - Rust 的嵌入式脚本引擎。
本文我们从最简单的字符串应用入手,来看看 Rhai 脚本的编写是多么简单。主要从三个应用点入手:在 Rust 程序中调用嵌入的 Rhai 脚本;独立的 Rhai 脚本;web 开发方面,结合模板引擎,调用 Rhai 脚本,进行模板的渲染辅助。
- 在 Rust 程序中调用嵌入的 Rhai 脚本
首先,我们要在 Cargo.toml 中增加依赖项:
代码语言:javascript复制[dependencies]
rhai = "0.19.10"
然后,在 Rust 代码中,我们就可以对嵌入的 Rhai 脚本进行计算。示例是对字符串中的数字进行计算
代码语言:javascript复制use rhai::{Engine, EvalAltResult, INT};
fn main() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
let result = engine.eval::<INT>("40 2")?;
println!("计算结果:{}", result); // 将会打印 42
Ok(())
}
计算结果可以传递给其它 Rust 代码、Rhai 脚本,以及其它 Python 脚本、web 前端等,和 Rust 代码的写法基本相同。
- 独立的 Rhai 脚本
下面的示例是纯粹的 Rhai 脚本示例,也是字符串处理,请注意 Rhai 作为 no-std 的 Rust 脚本引擎,引入了具有动态类型,因此写法是和 Rust 代码很相似,但更为容易:易写、易读。
代码语言:javascript复制// 本脚本测试字符串操作
print("您好!"); // 注意 Rust 代码中,使用宏 print! 或 println!
print("这样n非常 \ 棒!"); // 嵌入换行符
print("40 16 进制为:x40"); // 转换为 16 进制
print("unicode:u2764"); // Unicode
print("unicode:U0001F603"); // Unicode
print("成都" "->" "三亚"); // 使用字符串构建字符串
print("foo" < "bar"); // 字符串比较,Rhai 中仅支持 ==、<、> 等
print("您" >= "你"); // 字符串比较,Rhai 中不支持 eq、lt、gt 等
print("输出结果为:" 42); // 使用非字符串类型的字符串构建
let s = "u2764 hello, world! U0001F603"; // 字符串变量
print("长度=" s.len); // 结果打印为 17
s[s.len-3] = '?'; // 修改字符串
print("修改结果为:" s); // 将打印 '修改结果为:hello, world?'
- 结合模板引擎,调用 Rhai 脚本,进行模板的渲染辅助
下面的示例为在支持 Rhai 脚本解析(即模板依赖 crate 包含 Rhai)的模板引擎中,使用独立的 Rhai 脚本进行渲染辅助。
首先,在对模板的响应 handler 中,我们需要注册脚本助手,可以注册多个。如下实例我们注册 2 个,分别处理模板渲染时根据用户个人站点类别,展示对应的站点所属 svg,以及对用户博客名称进行处理:
代码语言:javascript复制pub async fn user_index(req: Request<State>) -> tide::Result {
let mut user_tpl: Tpl = Tpl::new("users/index").await;
user_tpl.reg.register_script_helper_file(
"website-svg",
format!("{}{}", rhai_dir().await, "website-svg.rhai"),
)?;
user_tpl.reg.register_script_helper_file(
"blog-name",
format!("{}{}", rhai_dir().await, "blog-name.rhai"),
)?;
...
...
然后,独立的 Rhai 脚本 website-svg.rhai 为:
代码语言:javascript复制let website = params[0];
let is_github = website.contains("github.com");
if is_github {
"M8 0C3.58 0 0 3.58 0 ..."
} else {
"M6.5 14.5v-3.505c0-...."
}
脚本 blog-name.rhai 我们就省略了。
最后,在模板文件(即 html、jinja2、hbs 等)中,我们使用变量解析类似的方法进行调用:
代码语言:javascript复制<div class="col-4 text-center">
<a class="blog-header-logo text-dark" href="{{ user.website }}" target="_blank">
{{ blog-name user.blogName }}
<svg width="28" height="28" viewBox="0 0 18 18" fill="currentColor">
<path d="{{ website-svg user.website }}" />
</svg>
</a>
</div>
服务器端在对模板渲染时,模板引擎内置的 rhai 依赖 crate 将对 rahi 脚本进行计算。和文中第一个 rhai 应用途径——Rust 代码中嵌入 Rhai 脚本——类似。
通过三个途径的应用示例,我们可以发现:Rhai 总体应用范畴来说,目前还很狭小。并且除了性能特别出色这个优点外,其它优势并非特别明显。
体验者大多基于对 Rust 语言性能的信赖,从而作为将复杂问题简单化的以辅助。比如笔者目前的应用,也主要聚焦于模板渲染辅助方面。
对于特别看重性能的应用来说,Rhai 脚本引擎是个非常值得考虑的。其余考量点来说,技术栈也会多了一个选项。感兴趣的朋友可以访问网站:https://rhai.budshome.com,以作详细了解。