Rust WebAssembly 绑定输入类型(基于 Serde)

前言

单位有个项目要共享前后端检查策略后端用的正好也是 Rust,但是 Rust 默认的 wasm-bindgen 包中提供的转换操作非常少,像 Vec<T> <=> Array<T> 或者 Box<dyn T> <=> T 的转换就不行了。但是可以从 Typescript 构建这些类型,然后通过序列化的好朋友的 serde 把他们转换回 Rust 来问题。

项目结构

Cargo.toml
src
│  algorithms.rs 共享的算法
│  lib.rs
│  models.rs 共享的数据结构
└─wasm
        mod.rs
        model_bridge.rs 共享数据结构与自定接口的转换
        typescript_custom_types.rs Typescript 中的自定接口
        utils.rs

Cargo.toml 中添加新依赖

[dependencies]
# serde 是各种项目必备的,这个是 Rust 各种序列化的基础
serde = { version = "1.0", features = ["derive"] }
# Wasm 绑定工具,需要 Serde 转换特性
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }

typescript_custom_types.rs 中编写自定义的数据结构

use wasm_bindgen::prelude::*;

#[wasm_bindgen(typescript_custom_section)]
pub const IMODEL_TSTEXT: &'static str = r#"
interface IModel {
    id: string,
    name: string,
}
"#;

编写模型结构体和算法

//! models.rs 
use serde::*;

/// 模型类
/// 这里一定要用 `Serialize`, `Deserialize` 转换类型的关键
/// 用 camelCase 则是让 Typescript 和 rust 的命名系统相互转换
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Model {
    pub id: String,
    pub name: String,
}

算法没有什么好讲的,写很日常的一个方法就可以

model_bridge.rs 编写转换或者绑定方法

use crate::models::*;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    /// 绑定 Typescript 中刚才定义的 IModel
    #[wasm_bindgen(typescript_type = "IModel")]
    pub type IModel;
}

/// 转换
impl From<IModel> for Model {
    fn from(f: IModel) -> Model {
        model.into_serde().unwrap()
    }
}

/// 入口
/// `js_name` 是方法在 Typescript 里显示的名称
#[wasm_bindgen(js_name = "testModel")]
pub fn test_model(model: IModel) -> bool {
    let m: Model = model.into_serde().unwrap();
    crate::algorithms::test_model(m)
}

检查生成的文件

/*
* 手动定义的接口
*/
interface IModel {
    id: string,
    name: string,
}
/*
* 自动生成的绑定
*/
export function testModel(model: IModel): boolean;

参考

  1. Express "Duck-Typed Interface" as trait
  2. How do you use a Rust struct with a String field?
  3. Add typescript_type attribute
posted @ 2022-05-08 00:36  Aoba_xu  阅读(148)  评论(0编辑  收藏  举报