Merge pull request #1200 from Hywan/feat-either-n-up-to-26
feat(napi) Implement `Either3` to `Either26`.
This commit is contained in:
commit
dface0c6a7
29 changed files with 267 additions and 354 deletions
|
@ -14,6 +14,38 @@ static NAPI_IMPL_ID: AtomicU32 = AtomicU32::new(0);
|
|||
// Generate trait implementations for given Struct.
|
||||
fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> TokenStream {
|
||||
let name_str = name.to_string();
|
||||
let js_name_str = format!("{}\0", name_str);
|
||||
let validate = quote! {
|
||||
unsafe fn validate(env: napi::sys::napi_env, napi_val: napi::sys::napi_value) -> napi::Result<napi::sys::napi_value> {
|
||||
if let Some(ctor_ref) = napi::bindgen_prelude::get_class_constructor(#js_name_str) {
|
||||
let mut ctor = std::ptr::null_mut();
|
||||
napi::check_status!(
|
||||
napi::sys::napi_get_reference_value(env, ctor_ref, &mut ctor),
|
||||
"Failed to get constructor reference of class `{}`",
|
||||
#name_str
|
||||
)?;
|
||||
let mut is_instance_of = false;
|
||||
napi::check_status!(
|
||||
napi::sys::napi_instanceof(env, napi_val, ctor, &mut is_instance_of),
|
||||
"Failed to get external value of class `{}`",
|
||||
#name_str
|
||||
)?;
|
||||
if is_instance_of {
|
||||
Ok(std::ptr::null_mut())
|
||||
} else {
|
||||
Err(napi::Error::new(
|
||||
napi::Status::InvalidArg,
|
||||
format!("Value is not instanceof class `{}`", #name_str)
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Err(napi::Error::new(
|
||||
napi::Status::InvalidArg,
|
||||
format!("Failed to get constructor of class `{}`", #name_str)
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
quote! {
|
||||
impl napi::bindgen_prelude::TypeName for #name {
|
||||
fn type_name() -> &'static str {
|
||||
|
@ -99,6 +131,14 @@ fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> Token
|
|||
}
|
||||
}
|
||||
|
||||
impl napi::bindgen_prelude::ValidateNapiValue for &#name {
|
||||
#validate
|
||||
}
|
||||
|
||||
impl napi::bindgen_prelude::ValidateNapiValue for &mut #name {
|
||||
#validate
|
||||
}
|
||||
|
||||
impl napi::NapiRaw for &#name {
|
||||
unsafe fn raw(&self) -> napi::sys::napi_value {
|
||||
unreachable!()
|
||||
|
@ -523,6 +563,8 @@ impl NapiStruct {
|
|||
Ok(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl napi::bindgen_prelude::ValidateNapiValue for #name {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,6 +180,27 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
|
|||
("Either3", "{} | {} | {}"),
|
||||
("Either4", "{} | {} | {} | {}"),
|
||||
("Either5", "{} | {} | {} | {} | {}"),
|
||||
("Either6", "{} | {} | {} | {} | {} | {}"),
|
||||
("Either7", "{} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either8", "{} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either9", "{} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either10", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either11", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either12", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either13", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either14", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either15", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either16", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either17", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either18", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either19", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either20", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either21", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either22", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either23", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either24", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either25", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Either26", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
|
||||
("Null", "null"),
|
||||
("JsNull", "null"),
|
||||
("null", "null"),
|
||||
|
|
|
@ -38,7 +38,6 @@ pub use buffer::*;
|
|||
pub use class::*;
|
||||
pub use either::*;
|
||||
pub use external::*;
|
||||
#[cfg(feature = "napi4")]
|
||||
pub use function::*;
|
||||
pub use nil::*;
|
||||
pub use object::*;
|
||||
|
@ -116,16 +115,15 @@ pub trait FromNapiMutRef {
|
|||
}
|
||||
|
||||
pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// this function called to validate whether napi value passed to rust is valid type
|
||||
/// The reason why this function return `napi_value` is that if a `Promise<T>` passed in
|
||||
/// we need to return `Promise.reject(T)`, not the `T`.
|
||||
/// So we need to create `Promise.reject(T)` in this function.
|
||||
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
|
||||
let available_types = Self::type_of();
|
||||
if available_types.is_empty() {
|
||||
let value_type = Self::value_type();
|
||||
if value_type == ValueType::Unknown {
|
||||
return Ok(ptr::null_mut());
|
||||
}
|
||||
|
||||
|
@ -136,22 +134,15 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
|||
)?;
|
||||
|
||||
let received_type = ValueType::from(result);
|
||||
if available_types.contains(&received_type) {
|
||||
if value_type == received_type {
|
||||
Ok(ptr::null_mut())
|
||||
} else {
|
||||
Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
if available_types.len() > 1 {
|
||||
format!(
|
||||
"Expect value to be one of {:?}, but received {}",
|
||||
available_types, received_type
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"Expect value to be {}, but received {}",
|
||||
available_types[0], received_type
|
||||
)
|
||||
},
|
||||
format!(
|
||||
"Expect value to be {}, but received {}",
|
||||
value_type, received_type
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,11 +165,7 @@ impl Array {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Array {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Object]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for Array {}
|
||||
|
||||
impl<T> TypeName for Vec<T> {
|
||||
fn type_name() -> &'static str {
|
||||
|
|
|
@ -38,11 +38,7 @@ impl TypeName for BigInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for BigInt {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::BigInt]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for BigInt {}
|
||||
|
||||
impl FromNapiValue for BigInt {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
|
|
|
@ -10,11 +10,7 @@ impl TypeName for bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for bool {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Boolean]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for bool {}
|
||||
|
||||
impl ToNapiValue for bool {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: bool) -> Result<sys::napi_value> {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
use super::{FromNapiValue, ToNapiValue, TypeName};
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||
use crate::{
|
||||
bindgen_runtime::{Null, Undefined},
|
||||
sys, type_of, JsUndefined, NapiRaw, Status, ValueType,
|
||||
sys, Error, JsUndefined, NapiRaw, Status, ValueType,
|
||||
};
|
||||
|
||||
const ERROR_MSG: &str = "The return value of typeof(T) should not be equal in Either";
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Either<A, B> {
|
||||
A(A),
|
||||
|
@ -61,22 +59,23 @@ impl<T> From<Either<T, Null>> for Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<A: TypeName + FromNapiValue, B: TypeName + FromNapiValue> FromNapiValue for Either<A, B> {
|
||||
impl<
|
||||
A: TypeName + FromNapiValue + ValidateNapiValue,
|
||||
B: TypeName + FromNapiValue + ValidateNapiValue,
|
||||
> FromNapiValue for Either<A, B>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
debug_assert!(A::value_type() != B::value_type(), "{}", ERROR_MSG);
|
||||
let js_type = type_of!(env, napi_val)?;
|
||||
if js_type == A::value_type() {
|
||||
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
|
||||
} else if js_type == B::value_type() {
|
||||
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
|
||||
if unsafe { A::validate(env, napi_val) }.is_ok() {
|
||||
unsafe { A::from_napi_value(env, napi_val) }.map(Either::A)
|
||||
} else if unsafe { B::validate(env, napi_val) }.is_ok() {
|
||||
unsafe { B::from_napi_value(env, napi_val).map(Either::B) }
|
||||
} else {
|
||||
Err(crate::Error::new(
|
||||
Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
format!(
|
||||
"Expect type {} or {}, but got {}",
|
||||
A::value_type(),
|
||||
B::value_type(),
|
||||
js_type
|
||||
"Value is not either {} or {}",
|
||||
A::type_name(),
|
||||
B::type_name()
|
||||
),
|
||||
))
|
||||
}
|
||||
|
@ -95,238 +94,82 @@ impl<A: ToNapiValue, B: ToNapiValue> ToNapiValue for Either<A, B> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Either3<A, B, C> {
|
||||
A(A),
|
||||
B(B),
|
||||
C(C),
|
||||
}
|
||||
|
||||
impl<A: TypeName, B: TypeName, C: TypeName> TypeName for Either3<A, B, C> {
|
||||
fn type_name() -> &'static str {
|
||||
"Either3"
|
||||
}
|
||||
|
||||
fn value_type() -> ValueType {
|
||||
ValueType::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: TypeName + FromNapiValue, B: TypeName + FromNapiValue, C: TypeName + FromNapiValue>
|
||||
FromNapiValue for Either3<A, B, C>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
debug_assert!(
|
||||
{
|
||||
let mut types = vec![A::value_type(), B::value_type(), C::value_type()];
|
||||
types.dedup();
|
||||
types.len() == 3
|
||||
},
|
||||
"{}",
|
||||
ERROR_MSG
|
||||
);
|
||||
let js_type = type_of!(env, napi_val)?;
|
||||
if js_type == A::value_type() {
|
||||
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
|
||||
} else if js_type == B::value_type() {
|
||||
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
|
||||
} else if js_type == C::value_type() {
|
||||
unsafe { C::from_napi_value(env, napi_val).map(Self::C) }
|
||||
} else {
|
||||
Err(crate::Error::new(
|
||||
Status::InvalidArg,
|
||||
format!(
|
||||
"Expect type {} or {} or {}, but got {}",
|
||||
A::value_type(),
|
||||
B::value_type(),
|
||||
C::value_type(),
|
||||
js_type
|
||||
),
|
||||
))
|
||||
macro_rules! either_n {
|
||||
( $either_name:ident, $( $parameter:ident ),+ $( , )* ) => {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum $either_name< $( $parameter ),+ > {
|
||||
$( $parameter ( $parameter ) ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: ToNapiValue, B: ToNapiValue, C: ToNapiValue> ToNapiValue for Either3<A, B, C> {
|
||||
unsafe fn to_napi_value(
|
||||
env: sys::napi_env,
|
||||
value: Self,
|
||||
) -> crate::Result<crate::sys::napi_value> {
|
||||
match value {
|
||||
Self::A(a) => unsafe { A::to_napi_value(env, a) },
|
||||
Self::B(b) => unsafe { B::to_napi_value(env, b) },
|
||||
Self::C(c) => unsafe { C::to_napi_value(env, c) },
|
||||
impl< $( $parameter ),+ > TypeName for $either_name < $( $parameter ),+ >
|
||||
where $( $parameter: TypeName ),+
|
||||
{
|
||||
fn type_name() -> &'static str {
|
||||
stringify!( $either_name )
|
||||
}
|
||||
|
||||
fn value_type() -> ValueType {
|
||||
ValueType::Unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Either4<A, B, C, D> {
|
||||
A(A),
|
||||
B(B),
|
||||
C(C),
|
||||
D(D),
|
||||
}
|
||||
|
||||
impl<A: TypeName, B: TypeName, C: TypeName, D: TypeName> TypeName for Either4<A, B, C, D> {
|
||||
fn type_name() -> &'static str {
|
||||
"Either4"
|
||||
}
|
||||
|
||||
fn value_type() -> ValueType {
|
||||
ValueType::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
A: TypeName + FromNapiValue,
|
||||
B: TypeName + FromNapiValue,
|
||||
C: TypeName + FromNapiValue,
|
||||
D: TypeName + FromNapiValue,
|
||||
> FromNapiValue for Either4<A, B, C, D>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
debug_assert!(
|
||||
{
|
||||
let mut types = vec![
|
||||
A::value_type(),
|
||||
B::value_type(),
|
||||
C::value_type(),
|
||||
D::value_type(),
|
||||
];
|
||||
types.dedup();
|
||||
types.len() == 4
|
||||
},
|
||||
"{}",
|
||||
ERROR_MSG
|
||||
);
|
||||
let js_type = type_of!(env, napi_val)?;
|
||||
if js_type == A::value_type() {
|
||||
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
|
||||
} else if js_type == B::value_type() {
|
||||
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
|
||||
} else if js_type == C::value_type() {
|
||||
unsafe { C::from_napi_value(env, napi_val).map(Self::C) }
|
||||
} else if js_type == D::value_type() {
|
||||
unsafe { D::from_napi_value(env, napi_val).map(Self::D) }
|
||||
} else {
|
||||
Err(crate::Error::new(
|
||||
Status::InvalidArg,
|
||||
format!(
|
||||
"Expect type {} or {} or {} or {}, but got {}",
|
||||
A::value_type(),
|
||||
B::value_type(),
|
||||
C::value_type(),
|
||||
D::value_type(),
|
||||
js_type
|
||||
),
|
||||
))
|
||||
impl< $( $parameter ),+ > FromNapiValue for $either_name < $( $parameter ),+ >
|
||||
where $( $parameter: TypeName + FromNapiValue + ValidateNapiValue ),+
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
$(
|
||||
if unsafe { $parameter::validate(env, napi_val).is_ok() } {
|
||||
unsafe { $parameter ::from_napi_value(env, napi_val).map(Self:: $parameter ) }
|
||||
} else
|
||||
)+
|
||||
{
|
||||
Err(crate::Error::new(
|
||||
Status::InvalidArg,
|
||||
format!(
|
||||
concat!("Value is non of these types ", $( "`{", stringify!( $parameter ), "}`, " ),+ ),
|
||||
$( $parameter = $parameter::value_type(), )+
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: ToNapiValue, B: ToNapiValue, C: ToNapiValue, D: ToNapiValue> ToNapiValue
|
||||
for Either4<A, B, C, D>
|
||||
{
|
||||
unsafe fn to_napi_value(
|
||||
env: sys::napi_env,
|
||||
value: Self,
|
||||
) -> crate::Result<crate::sys::napi_value> {
|
||||
match value {
|
||||
Self::A(a) => unsafe { A::to_napi_value(env, a) },
|
||||
Self::B(b) => unsafe { B::to_napi_value(env, b) },
|
||||
Self::C(c) => unsafe { C::to_napi_value(env, c) },
|
||||
Self::D(d) => unsafe { D::to_napi_value(env, d) },
|
||||
impl< $( $parameter ),+ > ToNapiValue for $either_name < $( $parameter ),+ >
|
||||
where $( $parameter: ToNapiValue ),+
|
||||
{
|
||||
unsafe fn to_napi_value(
|
||||
env: sys::napi_env,
|
||||
value: Self
|
||||
) -> crate::Result<crate::sys::napi_value> {
|
||||
match value {
|
||||
$( Self:: $parameter (v) => unsafe { $parameter ::to_napi_value(env, v) } ),+
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Either5<A, B, C, D, E> {
|
||||
A(A),
|
||||
B(B),
|
||||
C(C),
|
||||
D(D),
|
||||
E(E),
|
||||
}
|
||||
|
||||
impl<A: TypeName, B: TypeName, C: TypeName, D: TypeName, E: TypeName> TypeName
|
||||
for Either5<A, B, C, D, E>
|
||||
{
|
||||
fn type_name() -> &'static str {
|
||||
"Either5"
|
||||
}
|
||||
|
||||
fn value_type() -> ValueType {
|
||||
ValueType::Unknown
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
A: TypeName + FromNapiValue,
|
||||
B: TypeName + FromNapiValue,
|
||||
C: TypeName + FromNapiValue,
|
||||
D: TypeName + FromNapiValue,
|
||||
E: TypeName + FromNapiValue,
|
||||
> FromNapiValue for Either5<A, B, C, D, E>
|
||||
{
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
debug_assert!(
|
||||
{
|
||||
let mut types = vec![
|
||||
A::value_type(),
|
||||
B::value_type(),
|
||||
C::value_type(),
|
||||
D::value_type(),
|
||||
E::value_type(),
|
||||
];
|
||||
types.dedup();
|
||||
types.len() == 5
|
||||
},
|
||||
"{}",
|
||||
ERROR_MSG
|
||||
);
|
||||
let js_type = type_of!(env, napi_val)?;
|
||||
if js_type == A::value_type() {
|
||||
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
|
||||
} else if js_type == B::value_type() {
|
||||
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
|
||||
} else if js_type == C::value_type() {
|
||||
unsafe { C::from_napi_value(env, napi_val).map(Self::C) }
|
||||
} else if js_type == D::value_type() {
|
||||
unsafe { D::from_napi_value(env, napi_val).map(Self::D) }
|
||||
} else if js_type == E::value_type() {
|
||||
unsafe { E::from_napi_value(env, napi_val).map(Self::E) }
|
||||
} else {
|
||||
Err(crate::Error::new(
|
||||
Status::InvalidArg,
|
||||
format!(
|
||||
"Expect type {} or {} or {} or {} or {}, but got {}",
|
||||
A::value_type(),
|
||||
B::value_type(),
|
||||
C::value_type(),
|
||||
D::value_type(),
|
||||
E::value_type(),
|
||||
js_type
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: ToNapiValue, B: ToNapiValue, C: ToNapiValue, D: ToNapiValue, E: ToNapiValue> ToNapiValue
|
||||
for Either5<A, B, C, D, E>
|
||||
{
|
||||
unsafe fn to_napi_value(
|
||||
env: sys::napi_env,
|
||||
value: Self,
|
||||
) -> crate::Result<crate::sys::napi_value> {
|
||||
match value {
|
||||
Self::A(a) => unsafe { A::to_napi_value(env, a) },
|
||||
Self::B(b) => unsafe { B::to_napi_value(env, b) },
|
||||
Self::C(c) => unsafe { C::to_napi_value(env, c) },
|
||||
Self::D(d) => unsafe { D::to_napi_value(env, d) },
|
||||
Self::E(e) => unsafe { E::to_napi_value(env, e) },
|
||||
}
|
||||
}
|
||||
}
|
||||
either_n!(Either3, A, B, C);
|
||||
either_n!(Either4, A, B, C, D);
|
||||
either_n!(Either5, A, B, C, D, E);
|
||||
either_n!(Either6, A, B, C, D, E, F);
|
||||
either_n!(Either7, A, B, C, D, E, F, G);
|
||||
either_n!(Either8, A, B, C, D, E, F, G, H);
|
||||
either_n!(Either9, A, B, C, D, E, F, G, H, I);
|
||||
either_n!(Either10, A, B, C, D, E, F, G, H, I, J);
|
||||
either_n!(Either11, A, B, C, D, E, F, G, H, I, J, K);
|
||||
either_n!(Either12, A, B, C, D, E, F, G, H, I, J, K, L);
|
||||
either_n!(Either13, A, B, C, D, E, F, G, H, I, J, K, L, M);
|
||||
either_n!(Either14, A, B, C, D, E, F, G, H, I, J, K, L, M, N);
|
||||
either_n!(Either15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
|
||||
either_n!(Either16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
|
||||
either_n!(Either17, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
|
||||
either_n!(Either18, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
|
||||
either_n!(Either19, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
|
||||
either_n!(Either20, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
|
||||
either_n!(Either21, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
|
||||
either_n!(Either22, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
|
||||
either_n!(Either23, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W);
|
||||
either_n!(Either24, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X);
|
||||
either_n!(Either25, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y);
|
||||
either_n!(Either26, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
|
||||
|
|
|
@ -23,11 +23,7 @@ impl<T: 'static> TypeName for External<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ValidateNapiValue for External<T> {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::External]
|
||||
}
|
||||
}
|
||||
impl<T: 'static> ValidateNapiValue for External<T> {}
|
||||
|
||||
impl<T: 'static> External<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
|
|
|
@ -2,8 +2,4 @@ use super::ValidateNapiValue;
|
|||
|
||||
pub use crate::JsFunction;
|
||||
|
||||
impl ValidateNapiValue for JsFunction {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::Function]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for JsFunction {}
|
||||
|
|
|
@ -13,11 +13,7 @@ impl<K, V, S> TypeName for HashMap<K, V, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<K: From<String> + Eq + Hash, V: FromNapiValue> ValidateNapiValue for HashMap<K, V> {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::Object]
|
||||
}
|
||||
}
|
||||
impl<K: From<String> + Eq + Hash, V: FromNapiValue> ValidateNapiValue for HashMap<K, V> {}
|
||||
|
||||
impl<K, V, S> ToNapiValue for HashMap<K, V, S>
|
||||
where
|
||||
|
|
|
@ -15,11 +15,7 @@ impl TypeName for Null {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Null {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Null]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for Null {}
|
||||
|
||||
impl FromNapiValue for Null {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
|
||||
|
@ -56,11 +52,7 @@ impl TypeName for Undefined {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Undefined {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Undefined]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for Undefined {}
|
||||
|
||||
impl FromNapiValue for Undefined {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
|
||||
|
|
|
@ -15,12 +15,7 @@ macro_rules! impl_number_conversions {
|
|||
}
|
||||
}
|
||||
|
||||
impl $crate::bindgen_prelude::ValidateNapiValue for $t {
|
||||
#[inline(always)]
|
||||
fn type_of() -> Vec<$crate::ValueType> {
|
||||
vec![$crate::ValueType::Number]
|
||||
}
|
||||
}
|
||||
impl $crate::bindgen_prelude::ValidateNapiValue for $t { }
|
||||
|
||||
impl $crate::bindgen_prelude::ToNapiValue for $t {
|
||||
#[inline(always)]
|
||||
|
|
|
@ -88,9 +88,3 @@ impl TypeName for Object {
|
|||
ValueType::Object
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Object {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Object]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,6 @@ impl<T: FromNapiValue> TypeName for Promise<T> {
|
|||
}
|
||||
|
||||
impl<T: FromNapiValue> ValidateNapiValue for Promise<T> {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::Object]
|
||||
}
|
||||
|
||||
unsafe fn validate(
|
||||
env: crate::sys::napi_env,
|
||||
napi_val: crate::sys::napi_value,
|
||||
|
|
|
@ -16,11 +16,7 @@ impl TypeName for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for String {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for String {}
|
||||
|
||||
impl ToNapiValue for String {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||
|
@ -81,11 +77,7 @@ impl TypeName for &str {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for &str {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for &str {}
|
||||
|
||||
impl FromNapiValue for &str {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
|
||||
|
@ -146,11 +138,7 @@ impl ToNapiValue for &str {
|
|||
#[derive(Debug)]
|
||||
pub struct Utf16String(String);
|
||||
|
||||
impl ValidateNapiValue for Utf16String {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for Utf16String {}
|
||||
|
||||
impl From<String> for Utf16String {
|
||||
fn from(s: String) -> Self {
|
||||
|
@ -245,11 +233,7 @@ pub mod latin1_string {
|
|||
#[derive(Debug)]
|
||||
pub struct Latin1String(String);
|
||||
|
||||
impl ValidateNapiValue for Latin1String {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for Latin1String {}
|
||||
|
||||
impl From<String> for Latin1String {
|
||||
fn from(s: String) -> Self {
|
||||
|
|
|
@ -14,15 +14,11 @@ impl TypeName for Symbol {
|
|||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
crate::ValueType::Object
|
||||
crate::ValueType::Symbol
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Symbol {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::Symbol]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for Symbol {}
|
||||
|
||||
impl Symbol {
|
||||
pub fn new(desc: String) -> Self {
|
||||
|
|
|
@ -3,8 +3,10 @@ use std::os::raw::c_void;
|
|||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use crate::bindgen_runtime::TypeName;
|
||||
use crate::{check_status, sys, JsUnknown, NapiValue, Ref, Result, Value, ValueType};
|
||||
use crate::bindgen_runtime::{TypeName, ValidateNapiValue};
|
||||
use crate::{
|
||||
check_status, sys, Error, JsUnknown, NapiValue, Ref, Result, Status, Value, ValueType,
|
||||
};
|
||||
|
||||
pub struct JsArrayBuffer(pub(crate) Value);
|
||||
|
||||
|
@ -18,6 +20,20 @@ impl TypeName for JsArrayBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsArrayBuffer {
|
||||
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
|
||||
let mut is_array_buffer = false;
|
||||
check_status!(unsafe { sys::napi_is_arraybuffer(env, napi_val, &mut is_array_buffer) })?;
|
||||
if !is_array_buffer {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Value is not an array buffer".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct JsArrayBufferValue {
|
||||
pub(crate) value: JsArrayBuffer,
|
||||
len: usize,
|
||||
|
|
|
@ -20,6 +20,8 @@ impl TypeName for JsBigInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsBigInt {}
|
||||
|
||||
impl JsBigInt {
|
||||
pub(crate) fn from_raw_unchecked(
|
||||
env: sys::napi_env,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use super::Value;
|
||||
use crate::bindgen_runtime::TypeName;
|
||||
use crate::bindgen_runtime::{TypeName, ValidateNapiValue};
|
||||
use crate::{check_status, ValueType};
|
||||
use crate::{sys, Error, Result};
|
||||
|
||||
|
@ -18,6 +18,8 @@ impl TypeName for JsBoolean {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsBoolean {}
|
||||
|
||||
impl JsBoolean {
|
||||
pub fn get_value(&self) -> Result<bool> {
|
||||
let mut result = false;
|
||||
|
|
|
@ -3,7 +3,10 @@ use std::ops::{Deref, DerefMut};
|
|||
use std::ptr;
|
||||
|
||||
use super::{Value, ValueType};
|
||||
use crate::{bindgen_runtime::TypeName, check_status, sys, JsUnknown, NapiValue, Ref, Result};
|
||||
use crate::bindgen_runtime::ValidateNapiValue;
|
||||
use crate::{
|
||||
bindgen_runtime::TypeName, check_status, sys, Error, JsUnknown, NapiValue, Ref, Result, Status,
|
||||
};
|
||||
|
||||
pub struct JsBuffer(pub(crate) Value);
|
||||
|
||||
|
@ -17,6 +20,20 @@ impl TypeName for JsBuffer {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsBuffer {
|
||||
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
|
||||
let mut is_buffer = false;
|
||||
check_status!(unsafe { sys::napi_is_buffer(env, napi_val, &mut is_buffer) })?;
|
||||
if !is_buffer {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Value is not a buffer".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct JsBufferValue {
|
||||
pub(crate) value: JsBuffer,
|
||||
data: mem::ManuallyDrop<Vec<u8>>,
|
||||
|
|
|
@ -73,6 +73,8 @@ impl TypeName for JsNull {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsNull {}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct JsSymbol(pub(crate) Value);
|
||||
|
||||
|
@ -86,11 +88,7 @@ impl TypeName for JsSymbol {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsSymbol {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Symbol]
|
||||
}
|
||||
}
|
||||
impl ValidateNapiValue for JsSymbol {}
|
||||
|
||||
pub struct JsExternal(pub(crate) Value);
|
||||
|
||||
|
@ -104,6 +102,8 @@ impl TypeName for JsExternal {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsExternal {}
|
||||
|
||||
macro_rules! impl_napi_value_trait {
|
||||
($js_value:ident, $value_type:ident) => {
|
||||
impl NapiValue for $js_value {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::convert::TryFrom;
|
||||
|
||||
use super::Value;
|
||||
use crate::bindgen_runtime::TypeName;
|
||||
use crate::bindgen_runtime::{TypeName, ValidateNapiValue};
|
||||
use crate::{check_status, ValueType};
|
||||
use crate::{sys, Error, Result};
|
||||
|
||||
|
@ -18,6 +18,8 @@ impl TypeName for JsNumber {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsNumber {}
|
||||
|
||||
impl JsNumber {
|
||||
pub fn get_uint32(&self) -> Result<u32> {
|
||||
let mut result = 0;
|
||||
|
|
|
@ -2,6 +2,7 @@ use std::mem;
|
|||
use std::ptr;
|
||||
|
||||
use crate::bindgen_runtime::TypeName;
|
||||
use crate::bindgen_runtime::ValidateNapiValue;
|
||||
use crate::ValueType;
|
||||
use crate::{check_status, sys, Result, Value};
|
||||
|
||||
|
@ -26,6 +27,8 @@ impl TypeName for JsString {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsString {}
|
||||
|
||||
impl JsString {
|
||||
pub fn utf8_len(&self) -> Result<usize> {
|
||||
let mut length = 0;
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use crate::{bindgen_runtime::TypeName, ValueType};
|
||||
use crate::{
|
||||
bindgen_runtime::{TypeName, ValidateNapiValue},
|
||||
ValueType,
|
||||
};
|
||||
|
||||
use super::Value;
|
||||
|
||||
|
@ -14,3 +17,5 @@ impl TypeName for JsUndefined {
|
|||
ValueType::Undefined
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsUndefined {}
|
||||
|
|
|
@ -62,6 +62,7 @@ Generated by [AVA](https://avajs.dev).
|
|||
export function either4(input: string | number | boolean | Obj): number␊
|
||||
export function receiveClassOrNumber(either: number | JsClassForEither): number␊
|
||||
export function receiveMutClassOrNumber(either: number | JsClassForEither): number␊
|
||||
export function receiveDifferentClass(either: JsClassForEither | AnotherClassForEither): number␊
|
||||
export function returnEitherClass(input: number): number | JsClassForEither␊
|
||||
export function eitherFromOption(): JsClassForEither | undefined␊
|
||||
/** default enum values are continuos i32s start from 0 */␊
|
||||
|
@ -276,6 +277,9 @@ Generated by [AVA](https://avajs.dev).
|
|||
export class JsClassForEither {␊
|
||||
constructor()␊
|
||||
}␊
|
||||
export class AnotherClassForEither {␊
|
||||
constructor()␊
|
||||
}␊
|
||||
export class Fib {␊
|
||||
[Symbol.iterator](): Iterator<number, void, number>␊
|
||||
constructor()␊
|
||||
|
|
Binary file not shown.
|
@ -99,6 +99,8 @@ import {
|
|||
overrideIndividualArgOnFunctionWithCbArg,
|
||||
createObjectWithClassField,
|
||||
receiveObjectWithClassField,
|
||||
AnotherClassForEither,
|
||||
receiveDifferentClass,
|
||||
} from '../'
|
||||
|
||||
test('export const', (t) => {
|
||||
|
@ -500,6 +502,13 @@ test('receive class reference in either', (t) => {
|
|||
t.is(receiveMutClassOrNumber(c), 100)
|
||||
})
|
||||
|
||||
test('receive different class', (t) => {
|
||||
const a = new JsClassForEither()
|
||||
const b = new AnotherClassForEither()
|
||||
t.is(receiveDifferentClass(a), 42)
|
||||
t.is(receiveDifferentClass(b), 100)
|
||||
})
|
||||
|
||||
test('return either class', (t) => {
|
||||
t.is(returnEitherClass(1), 1)
|
||||
t.true(returnEitherClass(-1) instanceof JsClassForEither)
|
||||
|
|
4
examples/napi/index.d.ts
vendored
4
examples/napi/index.d.ts
vendored
|
@ -52,6 +52,7 @@ export interface Obj {
|
|||
export function either4(input: string | number | boolean | Obj): number
|
||||
export function receiveClassOrNumber(either: number | JsClassForEither): number
|
||||
export function receiveMutClassOrNumber(either: number | JsClassForEither): number
|
||||
export function receiveDifferentClass(either: JsClassForEither | AnotherClassForEither): number
|
||||
export function returnEitherClass(input: number): number | JsClassForEither
|
||||
export function eitherFromOption(): JsClassForEither | undefined
|
||||
/** default enum values are continuos i32s start from 0 */
|
||||
|
@ -266,6 +267,9 @@ export class ClassWithFactory {
|
|||
export class JsClassForEither {
|
||||
constructor()
|
||||
}
|
||||
export class AnotherClassForEither {
|
||||
constructor()
|
||||
}
|
||||
export class Fib {
|
||||
[Symbol.iterator](): Iterator<number, void, number>
|
||||
constructor()
|
||||
|
|
|
@ -67,6 +67,17 @@ impl JsClassForEither {
|
|||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
struct AnotherClassForEither {}
|
||||
|
||||
#[napi]
|
||||
impl AnotherClassForEither {
|
||||
#[napi(constructor)]
|
||||
pub fn new() -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn receive_class_or_number(either: Either<u32, &JsClassForEither>) -> u32 {
|
||||
match either {
|
||||
|
@ -83,6 +94,14 @@ fn receive_mut_class_or_number(either: Either<u32, &mut JsClassForEither>) -> u3
|
|||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn receive_different_class(either: Either<&JsClassForEither, &AnotherClassForEither>) -> u32 {
|
||||
match either {
|
||||
Either::A(_) => 42,
|
||||
Either::B(_) => 100,
|
||||
}
|
||||
}
|
||||
|
||||
#[napi]
|
||||
fn return_either_class(input: i32) -> Either<u32, JsClassForEither> {
|
||||
if input > 0 {
|
||||
|
|
Loading…
Reference in a new issue