61 个版本 (15 个破坏性更新)
新版本 0.17.0 | 2024年8月15日 |
---|---|
0.16.1 | 2024年7月26日 |
0.15.4 | 2024年7月24日 |
0.11.7 | 2024年3月18日 |
0.2.0 | 2023年7月21日 |
#46 in WebAssembly
每月 2,057 次下载
用于 7 个 crates (3 直接使用)
115KB
2.5K SLoC
warpgate
Warpgate 是一个用于下载、解析和管理由 Extism 驱动的 WASM 插件的库。
Warpgate 中的 warp 代表 Web Assembly Runtime Plugins。听起来很棒,对吧。
加载插件
在使用 WASM 文件之前,必须将其加载。根据所使用的定位策略,加载插件可能意味着引用本地文件、从安全的 URL 下载文件,甚至向特定的注册表发送 API 请求。
首先,实例化一个 PluginLoader
,并提供一个用于缓存 .wasm
文件的目录路径,以及一个用于下载和解包文件的临时目录。
use warpgate::PluginLoader;
let root = get_cache_root();
let loader = PluginLoader::new(root.join("plugins"), root.join("temp"));
然后可以使用 load_plugin
方法加载插件,该方法需要一个唯一的 ID(将成为文件名),以及一个 PluginLocator
枚举变体(用于定位 .wasm
文件)。此方法返回主机机器上缓存的 .wasm
文件的绝对路径。
use warpgate::PluginLocator;
let wasm_file = loader.load_plugin(PluginLocator::Url {
url: "https://registry.com/path/to/file.wasm".into(),
});
定位策略
定位策略定义了查找必要的 .wasm
文件的说明,并由 PluginLocator
枚举的变体表示。
此枚举还支持从字符串反序列化(如下面的注释所示),这对于配置文件可能很有用。
以下策略目前受到支持:
本地文件
文件可在本地主机上使用。在反序列化时,必须手动将 path
字段转换为绝对路径。
// file://./path/to/file.wasm
PluginLocator::File {
file: "path/to/file.wasm".into(),
path: Some(PathBuf::from("/absolute/path/to/file.wasm")),
}
安全 URL
从安全的https
URL下载文件。
// https://registry.com/path/to/file.wasm
PluginLocator::Url {
url: "https://registry.com/path/to/file.wasm".into(),
}
GitHub版本发布
从GitHub版本中下载资产。此方法通过GitHub API进行通信,并需要将.wasm
文件作为资产附加。
建议定义一个GITHUB_TOKEN
环境变量以避免速率限制。
// github://org/repo
// github://org/[email protected]
// github://org/repo/project
PluginLocator::GitHub(GitHubLocator{
repo_slug: "org/repo".into(),
project_name: None,
tag: Some("v1.2.3".into()), // Latest if `None`
})
project_name
字段存在是为了支持单仓库(monorepo)。当定义时,它将查找以项目名称开头的标签/版本。例如,如果项目名称是example_plugin
,它将匹配example_plugin-v1.2.3
或example_plugin@v1.2.3
标签。
Extism插件容器
此库的另一种机制是提供PluginContainer
结构体;它是对Extism的Plugin
和Manifest
类型的包装。容器提供方便的方法来调用具有与serde兼容的输入和输出类型的函数,并且缓存结果以供后续调用。这在避免WASM客机和主机之间通信时的不必要开销方面非常有用。
要使用容器,请使用Manifest
和可选的主机函数实例化一个实例。
use warpgate::{Id, PluginContainer, PluginManifest, Wasm};
// Load the plugin and create a manifest
let wasm_file = loader.load_plugin(locator);
let manifest = PluginManifest::new([Wasm::file(wasm_file)]);
// Create a container
let container = PluginContainer::new(Id::new("id")?, manifest, [host, funcs])?;
// Or
let container = PluginContainer::new_without_functions(Id::new("id")?, manifest)?;
从这里,您可以使用call_func
(无输入)和call_func_with
方法调用插件上的函数。要调用并缓存函数,请使用替代的cache_func
和cache_func_with
方法。
此外,这些方法需要一个serde结构体作为输出,可选作为输入。可以使用call
方法处理基于serde的函数。
let output: AddOutput = container.cache_func_with("add", AddInput {
left: 10,
right: 20,
})?;
dbg!(output.sum);
依赖项
~35–55MB
~1M SLoC