2个版本
0.1.1 | 2022年10月2日 |
---|---|
0.1.0 | 2022年4月9日 |
#622 in 过程宏
6KB
121 行
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类型。它可以是任何 Serializable
结构,而不仅仅是 String
。内部它只是将其包装成一个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"}
是一个实际结果。
如果方法失败,返回类似的内容
[源代码,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]
[源代码,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)
的转换器。即实现 impl From<MyError> for (usize, String)
特性。
[源代码,Rust]
impl From<MyError> for (usize, String) {
fn from(err: MyError) -> Self {
todo!()
}
}
除了标准的同步调用之外,该库还为 Channel 处理器提供了同样的简化。在这种情况下,您使用 #[neon_frame_fn(channel)]
宏,并为处理响应的 FnOnce
函数添加额外的参数。
[源代码,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)]
[源代码,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
除非适用法律要求或书面同意,否则在许可证下分发的软件按“原样”提供,不提供任何明示或暗示的保证或条件。有关许可证的具体语言、许可和限制,请参阅许可证。
依赖项
~1.5MB
~34K SLoC