Rhai 脚本引擎的简单应用示例

2022-06-30 16:31:32 浏览数 (1)

上一篇文章中,简单介绍了 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,以作详细了解。

0 人点赞