From 2f00e79873dbccb4f87261999aaddba59548acc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Tue, 25 Apr 2023 05:14:06 +0200 Subject: [PATCH] chore(napi): adds support for `Rc` / `Arc` / `Mutex` (#1573) * Adds support for Rc/Arc/Mutex * Fixes codegen * Fixes lint * Fix clippy --------- Co-authored-by: LongYinan --- crates/backend/src/typegen.rs | 5 +- crates/napi/src/bindgen_runtime/js_values.rs | 191 ++++++++++++++++++- 2 files changed, 194 insertions(+), 2 deletions(-) diff --git a/crates/backend/src/typegen.rs b/crates/backend/src/typegen.rs index a3474700..11c1d819 100644 --- a/crates/backend/src/typegen.rs +++ b/crates/backend/src/typegen.rs @@ -205,7 +205,10 @@ static KNOWN_TYPES: Lazy> = La ("unknown", ("unknown", false, false)), ("Unknown", ("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 diff --git a/crates/napi/src/bindgen_runtime/js_values.rs b/crates/napi/src/bindgen_runtime/js_values.rs index 7577b97a..173c3858 100644 --- a/crates/napi/src/bindgen_runtime/js_values.rs +++ b/crates/napi/src/bindgen_runtime/js_values.rs @@ -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}; @@ -245,3 +249,188 @@ where } } } + +impl TypeName for Rc { + fn type_name() -> &'static str { + T::type_name() + } + + fn value_type() -> ValueType { + T::value_type() + } +} + +impl ValidateNapiValue for Rc { + unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result { + 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 FromNapiValue for Rc +where + T: FromNapiValue, +{ + unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { + 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`", + )?; + + Ok(Rc::new(unsafe { T::from_napi_value(env, napi_val)? })) + } +} + +impl ToNapiValue for Rc +where + T: ToNapiValue + Clone, +{ + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { + unsafe { T::to_napi_value(env, (*val).clone()) } + } +} + +impl TypeName for Arc { + fn type_name() -> &'static str { + T::type_name() + } + + fn value_type() -> ValueType { + T::value_type() + } +} + +impl ValidateNapiValue for Arc { + unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result { + 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 FromNapiValue for Arc +where + T: FromNapiValue, +{ + unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { + 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`", + )?; + + Ok(Arc::new(unsafe { T::from_napi_value(env, napi_val)? })) + } +} + +impl ToNapiValue for Arc +where + T: ToNapiValue + Clone, +{ + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { + unsafe { T::to_napi_value(env, (*val).clone()) } + } +} + +impl TypeName for Mutex { + fn type_name() -> &'static str { + T::type_name() + } + + fn value_type() -> ValueType { + T::value_type() + } +} + +impl ValidateNapiValue for Mutex { + unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result { + 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 FromNapiValue for Mutex +where + T: FromNapiValue, +{ + unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result { + 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`", + )?; + + Ok(Mutex::new(unsafe { T::from_napi_value(env, napi_val)? })) + } +} + +impl ToNapiValue for Mutex +where + T: ToNapiValue + Clone, +{ + unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result { + unsafe { + match val.lock() { + Ok(inner) => T::to_napi_value(env, inner.clone()), + Err(_) => Err(Error::new( + Status::GenericFailure, + "Failed to acquire a lock", + )), + } + } + } +}