chore(napi): adds support for Rc<T> / Arc<T> / Mutex<T> (#1573)

* Adds support for Rc/Arc/Mutex<T>

* Fixes codegen

* Fixes lint

* Fix clippy

---------

Co-authored-by: LongYinan <lynweklm@gmail.com>
This commit is contained in:
Maël Nison 2023-04-25 05:14:06 +02:00 committed by GitHub
parent 5a1f229dba
commit 2f00e79873
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 194 additions and 2 deletions

View file

@ -205,7 +205,10 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, (&'static str, bool, bool)>> = La
("unknown", ("unknown", false, false)), ("unknown", ("unknown", false, false)),
("Unknown", ("unknown", false, false)), ("Unknown", ("unknown", false, false)),
("JsUnknown", ("unknown", false, false)), ("JsUnknown", ("unknown", false, false)),
("This", ("this", false, false)) ("This", ("this", false, false)),
("Rc", ("{}", false, false)),
("Arc", ("{}", false, false)),
("Mutex", ("{}", false, false)),
]); ]);
map map

View file

@ -1,4 +1,8 @@
use std::ptr; use std::{
ptr,
rc::Rc,
sync::{Arc, Mutex},
};
use crate::{check_status, sys, Error, JsUnknown, NapiRaw, NapiValue, Result, Status, ValueType}; use crate::{check_status, sys, Error, JsUnknown, NapiRaw, NapiValue, Result, Status, ValueType};
@ -245,3 +249,188 @@ where
} }
} }
} }
impl<T: TypeName> TypeName for Rc<T> {
fn type_name() -> &'static str {
T::type_name()
}
fn value_type() -> ValueType {
T::value_type()
}
}
impl<T: ValidateNapiValue> ValidateNapiValue for Rc<T> {
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
let mut result = -1;
check_status!(
unsafe { sys::napi_typeof(env, napi_val, &mut result) },
"Failed to detect napi value type",
)?;
let received_type = ValueType::from(result);
if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
Ok(validate_ret)
} else {
Err(Error::new(
Status::InvalidArg,
format!(
"Expect value to be Rc<{}>, but received {}",
T::value_type(),
received_type
),
))
}
}
}
impl<T> FromNapiValue for Rc<T>
where
T: FromNapiValue,
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
let mut val_type = 0;
check_status!(
unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
"Failed to convert napi value into rust type `Rc<T>`",
)?;
Ok(Rc::new(unsafe { T::from_napi_value(env, napi_val)? }))
}
}
impl<T> ToNapiValue for Rc<T>
where
T: ToNapiValue + Clone,
{
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
unsafe { T::to_napi_value(env, (*val).clone()) }
}
}
impl<T: TypeName> TypeName for Arc<T> {
fn type_name() -> &'static str {
T::type_name()
}
fn value_type() -> ValueType {
T::value_type()
}
}
impl<T: ValidateNapiValue> ValidateNapiValue for Arc<T> {
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
let mut result = -1;
check_status!(
unsafe { sys::napi_typeof(env, napi_val, &mut result) },
"Failed to detect napi value type",
)?;
let received_type = ValueType::from(result);
if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
Ok(validate_ret)
} else {
Err(Error::new(
Status::InvalidArg,
format!(
"Expect value to be Arc<{}>, but received {}",
T::value_type(),
received_type
),
))
}
}
}
impl<T> FromNapiValue for Arc<T>
where
T: FromNapiValue,
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
let mut val_type = 0;
check_status!(
unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
"Failed to convert napi value into rust type `Arc<T>`",
)?;
Ok(Arc::new(unsafe { T::from_napi_value(env, napi_val)? }))
}
}
impl<T> ToNapiValue for Arc<T>
where
T: ToNapiValue + Clone,
{
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
unsafe { T::to_napi_value(env, (*val).clone()) }
}
}
impl<T: TypeName> TypeName for Mutex<T> {
fn type_name() -> &'static str {
T::type_name()
}
fn value_type() -> ValueType {
T::value_type()
}
}
impl<T: ValidateNapiValue> ValidateNapiValue for Mutex<T> {
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
let mut result = -1;
check_status!(
unsafe { sys::napi_typeof(env, napi_val, &mut result) },
"Failed to detect napi value type",
)?;
let received_type = ValueType::from(result);
if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
Ok(validate_ret)
} else {
Err(Error::new(
Status::InvalidArg,
format!(
"Expect value to be Mutex<{}>, but received {}",
T::value_type(),
received_type
),
))
}
}
}
impl<T> FromNapiValue for Mutex<T>
where
T: FromNapiValue,
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
let mut val_type = 0;
check_status!(
unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
"Failed to convert napi value into rust type `Mutex<T>`",
)?;
Ok(Mutex::new(unsafe { T::from_napi_value(env, napi_val)? }))
}
}
impl<T> ToNapiValue for Mutex<T>
where
T: ToNapiValue + Clone,
{
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
unsafe {
match val.lock() {
Ok(inner) => T::to_napi_value(env, inner.clone()),
Err(_) => Err(Error::new(
Status::GenericFailure,
"Failed to acquire a lock",
)),
}
}
}
}