2 个版本
0.1.1 | 2022年10月2日 |
---|---|
0.1.0 | 2022年4月9日 |
#15 in #neon
262 每月下载量
3KB
56 行
Neon Frame
一个高度定制的框架,用于构建基于 Neon 的 Rust 库以供 Node 使用。 Neon Frame 为 Rust 库提供一个标准的接口,以便响应 JavaScript。它负责处理错误并将响应转换回 JS。
Neon Frame 通过统一处理和转换结果和错误的方式简化了处理器的逻辑。现在您只需编写一个返回 Result<T, E>
的常规方法,它就会自动转换为 Node 并返回。
您可以选择使用通道,在这种情况下,Neon Frame 的 JavaScript 端会包装这些调用以获得一个普通的 Promise<T>
。
安装
.Cargo.toml [来源,toml]
[dependencies]
neon-frame = "0.1"
neon-frame-macro = "0.1"
.package.json [来源,json]
"dependencies": {
"@emeraldpay/neon-frame": "^0.1.1"
}
.JS 导入 [来源,typescript]
import {neonFrameCall} from "@emeraldpay/neon-frame";
关于其用法的简要介绍
Rust 端
.现在您可以使用 #[neon_frame_fn]
宏标记一个函数:[来源,rust]
#[macro_use]
extern crate neon_frame_macro;
#[neon_frame_fn]
pub fn function_hello_world(_cx: &mut FunctionContext) -> Result<String, Errors> {
Ok("Hello World".to_string())
}
该宏会自动将 Rust 类型转换为 Node 类型。除了 String
之外,它可以是任何 Serializable
结构。内部它只是将其包装成一个 JSON,这可以在 Node 端轻松处理。
JavaScript 端
[来源,typescript]
import {neonFrameDirectCall} from "@emeraldpay/neon-frame";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const addon = require('path/to/index.node');
export function helloWorld(): string {
return neonFrameDirectCall<string>(addon, "function_hello_world", []);
}
如果您想在单独的线程中处理某些内容怎么办?例如,在 JavaScript 中异步地作为 Promise 获取它?
Rust 端使用通道
.使用 #[neon_frame_fn)
宏,它为您提供了一个回调函数:[来源,rust]
#[neon_frame_fn(channel)]
pub fn function_default_channel<H>(_cx: &mut FunctionContext, handler: H) -> Result<(), Errors>
where
H: FnOnce(Result<String, Errors>) + Send + 'static {
std::thread::spawn(move || {
let result = "Hello World".to_string();
handler(Ok(result));
});
Ok(())
}
JavaScript 端使用 Promise
[来源,typescript]
import {neonFrameHandlerCall} from "@emeraldpay/neon-frame";
// eslint-disable-next-line @typescript-eslint/no-var-requires
const addon = require('path/to/index.node');
export function default_channel(): Promise<string> {
return neonFrameHandlerCall<string>(addon, "function_default_channel", []);
}
示例
在 /integration-tests
目录中,您可以找到交互测试,这些测试也可以作为实现示例。
如何工作及细节
作为响应,它使用类似于 JSON 的格式:[来源,json]
{
"succeeded": true,
"result": {
"foo": "bar"
}
}
其中 {"foo": "bar"}
表示实际结果。
如果方法失败,则返回类似的内容。
[source, json]
{
"succeeded": false,
"error": {
"code": 100,
"message": "Invalid input value for #0"
}
}
作为一个 TypeScript 类型,它是
[来源,typescript]
type Status<T> = {
succeeded: boolean,
result: T | undefined,
error: {
code: number,
message: string
} | undefined
}
要使用 Neon Frame,只需在方法上添加注解 #[neon_frame_fn]
[source, rust]
#[neon_frame_fn]
pub fn hello_world(cx: &mut FunctionContext) -> Result<String, MyError> {
Ok("Hello World".to_string())
}
注意:该方法预期使用 cx: &mut FunctionContext
而不是 mut cx: FunctionContext
。
此外,您需要编写一个从 MyError
到 (usize, String)
的转换器。即实现以下 trait:impl From<MyError> for (usize, String)
[source, rust]
impl From<MyError> for (usize, String) {
fn from(err: MyError) -> Self {
todo!()
}
}
除了标准的同步调用外,库还为 Channel 处理程序提供了相同的简化。在这种情况下,您使用 #[neon_frame_fn(channel)]
宏,并为处理响应的 FnOnce
函数提供额外的参数
[source, rust]
// function called from JS as:
//
// hello_world((x) => { ... });
//
#[neon_frame_fn(channel)]
pub fn hello_world<H>(cx: &mut FunctionContext, handler: H) -> Result<(), MyError>
where
H: FnOnce(Result<String, MyError>) + Send + 'static {
std::thread::spawn(move || {
handler(Ok("Hello World".to_string()));
});
Ok(())
}
默认情况下,它使用第一个 JS 参数作为处理函数。但如果您需要在不同的位置使用它,可以将其指定为参数,例如 #[neon_frame_fn(channel=2)]
[source, rust]
// function called from JS as:
//
// hello_world("hi", "there", (x) => { ... });
//
// i.e. with handler at the 3rd position, which is 2 starting from zero
//
#[neon_frame_fn(channel=2)]
pub fn hello_world<H>(cx: &mut FunctionContext, handler: H) -> Result<(), MyError>
where
H: FnOnce(Result<String, MyError>) + Send + 'static {
todo!()
}
许可
版权所有 2022 EmeraldPay, Inc
根据 Apache License,版本 2.0(“许可”)许可;除非遵守许可,否则您不得使用此文件。您可以在以下位置获取许可副本:
https://apache.ac.cn/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则在许可下分发的软件按“原样”基础分发,不提供任何明示或暗示的保证或条件。有关许可的具体语言,请参阅许可。
依赖项
~0.6–1.4MB
~32K SLoC