Я работаю над проектом, в котором мне нужно обернуть хеш-функцию bcrypt с использованием N-API в Rust. Я написал следующий код, но во время компиляции обнаружил ошибки несоответствия типов. Я был бы признателен за любые советы о том, как исправить эти проблемы или улучшить мой подход.
use bcrypt::hash;
use napi::{bindgen_prelude::*, Env, JsObject, JsString, Result, Task};
use napi_derive::napi;
struct BcryptTask {
password: String,
cost: u32,
}
impl Task for BcryptTask {
type Output = String;
type JsValue = JsString;
fn compute(&mut self) -> Result<Self::Output> {
hash(&self.password, self.cost)
.map_err(|e| Error::new(Status::GenericFailure, format!("Bcrypt error: {:?}", e)))
}
fn resolve(&mut self, env: Env, output: Self::Output) -> Result<JsString> {
env.create_string(&output)
}
}
#[napi]
fn init(mut exports: JsObject) -> Result<()> {
exports.create_named_method("hashPassword", hash_password_wrapper)?;
Ok(())
}
#[napi]
fn hash_password_wrapper(env: Env, password: String, cost: u32) -> Result<JsObject> {
let task = BcryptTask { password, cost };
env.spawn(task)
}
Я получаю следующие ошибки:
> cargo build
Compiling rust_for_node v0.1.0 (C:\rust_for_node)
error[E0308]: mismatched types
--> src\lib.rs:26:49
|
26 | exports.create_named_method("hashPassword", hash_password_wrapper)?;
| ------------------- ^^^^^^^^^^^^^^^^^^^^^ expected "C" fn, found "Rust" fn
| |
| arguments to this method are incorrect
|
= note: expected fn pointer `unsafe extern "C" fn(*mut napi_env__, *mut napi_callback_info__) -> *mut napi_value__`
found fn item `fn(Env, std::string::String, u32) -> Result<JsObject, napi::Error> {hash_password_wrapper}`
note: method defined here
--> C:\Users\xxx\.cargo\registry\src\index.crates.io-6f17d22bba15001f\napi-2.16.2\src\js_values\mod.rs:667:1
|
667 | impl_object_methods!(JsObject);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `impl_object_methods` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0308]: mismatched types
--> src\lib.rs:33:5
|
31 | fn hash_password_wrapper(env: Env, password: String, cost: u32) -> Result<JsObject> {
| ---------------- expected `Result<JsObject, napi::Error>` because of return type
32 | let task = BcryptTask { password, cost };
33 | env.spawn(task)
| ^^^^^^^^^^^^^^^ expected `Result<JsObject, Error>`, found `Result<AsyncWorkPromise, ...>`
|
= note: expected enum `Result<JsObject, _>`
found enum `Result<AsyncWorkPromise, _>`
For more information about this error, try `rustc --explain E0308`.
error: could not compile `rust_for_node` (lib) due to 2 previous errors
Вопросы:
Как устранить ошибку несовпадения типов при использовании экспорта.create_named_method? Кажется, он ожидает функцию «extern C». Для вызова env.spawn(task) он возвращает AsyncWorkPromise вместо JsObject. Как мне справиться с этим, чтобы соответствовать ожидаемому типу возвращаемого значения функции?
Будем очень признательны за любую помощь или предложения о том, как правильно реализовать это в Rust!
Вам нужно вызвать get_c_callback() с помощью функции, сгенерированной napi
:
#[napi]
fn init(mut exports: JsObject) -> Result<()> {
exports.create_named_method("hashPassword", get_c_callback(hash_password_wrapper)?)?;
Ok(())
}
Однако обратите внимание, что napi
автоматически экспортирует функции, помеченные #[napi]
, поэтому вам не нужно для этого добавлять функцию (вы также можете изменить ее имя с помощью #[napi(js_name = "hashPassword")]
).
спасибо, я понял, что если у вашего ржавчины такое же имя, это еще проще: #[napi] fn hash_password(password: String, Cost: u32) -> AsyncTask<BcryptTask> { AsyncTask::new(BcryptTask {пароль, стоимость }) }