Merge pull request #1200 from Hywan/feat-either-n-up-to-26

feat(napi) Implement `Either3` to `Either26`.
This commit is contained in:
LongYinan 2022-07-05 17:35:15 +08:00 committed by GitHub
commit dface0c6a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 267 additions and 354 deletions

View file

@ -14,6 +14,38 @@ static NAPI_IMPL_ID: AtomicU32 = AtomicU32::new(0);
// Generate trait implementations for given Struct. // Generate trait implementations for given Struct.
fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> TokenStream { fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> TokenStream {
let name_str = name.to_string(); 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! { quote! {
impl napi::bindgen_prelude::TypeName for #name { impl napi::bindgen_prelude::TypeName for #name {
fn type_name() -> &'static str { 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 { impl napi::NapiRaw for &#name {
unsafe fn raw(&self) -> napi::sys::napi_value { unsafe fn raw(&self) -> napi::sys::napi_value {
unreachable!() unreachable!()
@ -523,6 +563,8 @@ impl NapiStruct {
Ok(val) Ok(val)
} }
} }
impl napi::bindgen_prelude::ValidateNapiValue for #name {}
} }
} }

View file

@ -180,6 +180,27 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
("Either3", "{} | {} | {}"), ("Either3", "{} | {} | {}"),
("Either4", "{} | {} | {} | {}"), ("Either4", "{} | {} | {} | {}"),
("Either5", "{} | {} | {} | {} | {}"), ("Either5", "{} | {} | {} | {} | {}"),
("Either6", "{} | {} | {} | {} | {} | {}"),
("Either7", "{} | {} | {} | {} | {} | {} | {}"),
("Either8", "{} | {} | {} | {} | {} | {} | {} | {}"),
("Either9", "{} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either10", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either11", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either12", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either13", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either14", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either15", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either16", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either17", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either18", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either19", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either20", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either21", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either22", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either23", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either24", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either25", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Either26", "{} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {} | {}"),
("Null", "null"), ("Null", "null"),
("JsNull", "null"), ("JsNull", "null"),
("null", "null"), ("null", "null"),

View file

@ -38,7 +38,6 @@ pub use buffer::*;
pub use class::*; pub use class::*;
pub use either::*; pub use either::*;
pub use external::*; pub use external::*;
#[cfg(feature = "napi4")]
pub use function::*; pub use function::*;
pub use nil::*; pub use nil::*;
pub use object::*; pub use object::*;
@ -116,16 +115,15 @@ pub trait FromNapiMutRef {
} }
pub trait ValidateNapiValue: FromNapiValue + TypeName { pub trait ValidateNapiValue: FromNapiValue + TypeName {
fn type_of() -> Vec<ValueType> {
vec![]
}
/// # Safety /// # Safety
/// ///
/// this function called to validate whether napi value passed to rust is valid type /// 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> { unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
let available_types = Self::type_of(); let value_type = Self::value_type();
if available_types.is_empty() { if value_type == ValueType::Unknown {
return Ok(ptr::null_mut()); return Ok(ptr::null_mut());
} }
@ -136,22 +134,15 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
)?; )?;
let received_type = ValueType::from(result); let received_type = ValueType::from(result);
if available_types.contains(&received_type) { if value_type == received_type {
Ok(ptr::null_mut()) Ok(ptr::null_mut())
} else { } else {
Err(Error::new( Err(Error::new(
Status::InvalidArg, Status::InvalidArg,
if available_types.len() > 1 {
format!(
"Expect value to be one of {:?}, but received {}",
available_types, received_type
)
} else {
format!( format!(
"Expect value to be {}, but received {}", "Expect value to be {}, but received {}",
available_types[0], received_type value_type, received_type
) ),
},
)) ))
} }
} }

View file

@ -165,11 +165,7 @@ impl Array {
} }
} }
impl ValidateNapiValue for Array { impl ValidateNapiValue for Array {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::Object]
}
}
impl<T> TypeName for Vec<T> { impl<T> TypeName for Vec<T> {
fn type_name() -> &'static str { fn type_name() -> &'static str {

View file

@ -38,11 +38,7 @@ impl TypeName for BigInt {
} }
} }
impl ValidateNapiValue for BigInt { impl ValidateNapiValue for BigInt {}
fn type_of() -> Vec<crate::ValueType> {
vec![crate::ValueType::BigInt]
}
}
impl FromNapiValue for BigInt { impl FromNapiValue for BigInt {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {

View file

@ -10,11 +10,7 @@ impl TypeName for bool {
} }
} }
impl ValidateNapiValue for bool { impl ValidateNapiValue for bool {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::Boolean]
}
}
impl ToNapiValue for bool { impl ToNapiValue for bool {
unsafe fn to_napi_value(env: sys::napi_env, val: bool) -> Result<sys::napi_value> { unsafe fn to_napi_value(env: sys::napi_env, val: bool) -> Result<sys::napi_value> {

View file

@ -1,11 +1,9 @@
use super::{FromNapiValue, ToNapiValue, TypeName}; use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
use crate::{ use crate::{
bindgen_runtime::{Null, Undefined}, 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)] #[derive(Debug, Clone, Copy)]
pub enum Either<A, B> { pub enum Either<A, B> {
A(A), 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> { 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); if unsafe { A::validate(env, napi_val) }.is_ok() {
let js_type = type_of!(env, napi_val)?; unsafe { A::from_napi_value(env, napi_val) }.map(Either::A)
if js_type == A::value_type() { } else if unsafe { B::validate(env, napi_val) }.is_ok() {
unsafe { A::from_napi_value(env, napi_val).map(Self::A) } unsafe { B::from_napi_value(env, napi_val).map(Either::B) }
} else if js_type == B::value_type() {
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
} else { } else {
Err(crate::Error::new( Err(Error::new(
Status::InvalidArg, Status::InvalidArg,
format!( format!(
"Expect type {} or {}, but got {}", "Value is not either {} or {}",
A::value_type(), A::type_name(),
B::value_type(), B::type_name()
js_type
), ),
)) ))
} }
@ -95,16 +94,18 @@ impl<A: ToNapiValue, B: ToNapiValue> ToNapiValue for Either<A, B> {
} }
} }
macro_rules! either_n {
( $either_name:ident, $( $parameter:ident ),+ $( , )* ) => {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Either3<A, B, C> { pub enum $either_name< $( $parameter ),+ > {
A(A), $( $parameter ( $parameter ) ),+
B(B),
C(C),
} }
impl<A: TypeName, B: TypeName, C: TypeName> TypeName for Either3<A, B, C> { impl< $( $parameter ),+ > TypeName for $either_name < $( $parameter ),+ >
where $( $parameter: TypeName ),+
{
fn type_name() -> &'static str { fn type_name() -> &'static str {
"Either3" stringify!( $either_name )
} }
fn value_type() -> ValueType { fn value_type() -> ValueType {
@ -112,221 +113,63 @@ impl<A: TypeName, B: TypeName, C: TypeName> TypeName for Either3<A, B, C> {
} }
} }
impl<A: TypeName + FromNapiValue, B: TypeName + FromNapiValue, C: TypeName + FromNapiValue> impl< $( $parameter ),+ > FromNapiValue for $either_name < $( $parameter ),+ >
FromNapiValue for Either3<A, B, C> where $( $parameter: TypeName + FromNapiValue + ValidateNapiValue ),+
{ {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
debug_assert!( $(
if unsafe { $parameter::validate(env, napi_val).is_ok() } {
unsafe { $parameter ::from_napi_value(env, napi_val).map(Self:: $parameter ) }
} else
)+
{ {
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( Err(crate::Error::new(
Status::InvalidArg, Status::InvalidArg,
format!( format!(
"Expect type {} or {} or {}, but got {}", concat!("Value is non of these types ", $( "`{", stringify!( $parameter ), "}`, " ),+ ),
A::value_type(), $( $parameter = $parameter::value_type(), )+
B::value_type(),
C::value_type(),
js_type
), ),
)) ))
} }
} }
} }
impl<A: ToNapiValue, B: ToNapiValue, C: ToNapiValue> ToNapiValue for Either3<A, B, C> { impl< $( $parameter ),+ > ToNapiValue for $either_name < $( $parameter ),+ >
unsafe fn to_napi_value( where $( $parameter: ToNapiValue ),+
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) },
}
}
}
#[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<A: ToNapiValue, B: ToNapiValue, C: ToNapiValue, D: ToNapiValue> ToNapiValue
for Either4<A, B, C, D>
{ {
unsafe fn to_napi_value( unsafe fn to_napi_value(
env: sys::napi_env, env: sys::napi_env,
value: Self, value: Self
) -> crate::Result<crate::sys::napi_value> { ) -> crate::Result<crate::sys::napi_value> {
match value { match value {
Self::A(a) => unsafe { A::to_napi_value(env, a) }, $( Self:: $parameter (v) => unsafe { $parameter ::to_napi_value(env, v) } ),+
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) },
} }
} }
} }
};
}
#[derive(Debug, Clone, Copy)] either_n!(Either3, A, B, C);
pub enum Either5<A, B, C, D, E> { either_n!(Either4, A, B, C, D);
A(A), either_n!(Either5, A, B, C, D, E);
B(B), either_n!(Either6, A, B, C, D, E, F);
C(C), either_n!(Either7, A, B, C, D, E, F, G);
D(D), either_n!(Either8, A, B, C, D, E, F, G, H);
E(E), 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);
impl<A: TypeName, B: TypeName, C: TypeName, D: TypeName, E: TypeName> TypeName either_n!(Either12, A, B, C, D, E, F, G, H, I, J, K, L);
for Either5<A, B, C, D, E> 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);
fn type_name() -> &'static str { either_n!(Either15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
"Either5" 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);
fn value_type() -> ValueType { either_n!(Either19, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
ValueType::Unknown 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);
impl< 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);
A: TypeName + FromNapiValue, 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);
B: TypeName + FromNapiValue, 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);
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) },
}
}
}

View file

@ -23,11 +23,7 @@ impl<T: 'static> TypeName for External<T> {
} }
} }
impl<T: 'static> ValidateNapiValue for External<T> { impl<T: 'static> ValidateNapiValue for External<T> {}
fn type_of() -> Vec<crate::ValueType> {
vec![crate::ValueType::External]
}
}
impl<T: 'static> External<T> { impl<T: 'static> External<T> {
pub fn new(value: T) -> Self { pub fn new(value: T) -> Self {

View file

@ -2,8 +2,4 @@ use super::ValidateNapiValue;
pub use crate::JsFunction; pub use crate::JsFunction;
impl ValidateNapiValue for JsFunction { impl ValidateNapiValue for JsFunction {}
fn type_of() -> Vec<crate::ValueType> {
vec![crate::ValueType::Function]
}
}

View file

@ -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> { 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, V, S> ToNapiValue for HashMap<K, V, S> impl<K, V, S> ToNapiValue for HashMap<K, V, S>
where where

View file

@ -15,11 +15,7 @@ impl TypeName for Null {
} }
} }
impl ValidateNapiValue for Null { impl ValidateNapiValue for Null {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::Null]
}
}
impl FromNapiValue for Null { impl FromNapiValue for Null {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> { 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 { impl ValidateNapiValue for Undefined {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::Undefined]
}
}
impl FromNapiValue for Undefined { impl FromNapiValue for Undefined {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {

View file

@ -15,12 +15,7 @@ macro_rules! impl_number_conversions {
} }
} }
impl $crate::bindgen_prelude::ValidateNapiValue for $t { impl $crate::bindgen_prelude::ValidateNapiValue for $t { }
#[inline(always)]
fn type_of() -> Vec<$crate::ValueType> {
vec![$crate::ValueType::Number]
}
}
impl $crate::bindgen_prelude::ToNapiValue for $t { impl $crate::bindgen_prelude::ToNapiValue for $t {
#[inline(always)] #[inline(always)]

View file

@ -88,9 +88,3 @@ impl TypeName for Object {
ValueType::Object ValueType::Object
} }
} }
impl ValidateNapiValue for Object {
fn type_of() -> Vec<ValueType> {
vec![ValueType::Object]
}
}

View file

@ -25,10 +25,6 @@ impl<T: FromNapiValue> TypeName for Promise<T> {
} }
impl<T: FromNapiValue> ValidateNapiValue for Promise<T> { impl<T: FromNapiValue> ValidateNapiValue for Promise<T> {
fn type_of() -> Vec<crate::ValueType> {
vec![crate::ValueType::Object]
}
unsafe fn validate( unsafe fn validate(
env: crate::sys::napi_env, env: crate::sys::napi_env,
napi_val: crate::sys::napi_value, napi_val: crate::sys::napi_value,

View file

@ -16,11 +16,7 @@ impl TypeName for String {
} }
} }
impl ValidateNapiValue for String { impl ValidateNapiValue for String {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::String]
}
}
impl ToNapiValue for String { impl ToNapiValue for String {
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> { 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 { impl ValidateNapiValue for &str {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::String]
}
}
impl FromNapiValue for &str { impl FromNapiValue for &str {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> { 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)] #[derive(Debug)]
pub struct Utf16String(String); pub struct Utf16String(String);
impl ValidateNapiValue for Utf16String { impl ValidateNapiValue for Utf16String {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::String]
}
}
impl From<String> for Utf16String { impl From<String> for Utf16String {
fn from(s: String) -> Self { fn from(s: String) -> Self {
@ -245,11 +233,7 @@ pub mod latin1_string {
#[derive(Debug)] #[derive(Debug)]
pub struct Latin1String(String); pub struct Latin1String(String);
impl ValidateNapiValue for Latin1String { impl ValidateNapiValue for Latin1String {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::String]
}
}
impl From<String> for Latin1String { impl From<String> for Latin1String {
fn from(s: String) -> Self { fn from(s: String) -> Self {

View file

@ -14,15 +14,11 @@ impl TypeName for Symbol {
} }
fn value_type() -> crate::ValueType { fn value_type() -> crate::ValueType {
crate::ValueType::Object crate::ValueType::Symbol
} }
} }
impl ValidateNapiValue for Symbol { impl ValidateNapiValue for Symbol {}
fn type_of() -> Vec<crate::ValueType> {
vec![crate::ValueType::Symbol]
}
}
impl Symbol { impl Symbol {
pub fn new(desc: String) -> Self { pub fn new(desc: String) -> Self {

View file

@ -3,8 +3,10 @@ use std::os::raw::c_void;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use crate::bindgen_runtime::TypeName; use crate::bindgen_runtime::{TypeName, ValidateNapiValue};
use crate::{check_status, sys, JsUnknown, NapiValue, Ref, Result, Value, ValueType}; use crate::{
check_status, sys, Error, JsUnknown, NapiValue, Ref, Result, Status, Value, ValueType,
};
pub struct JsArrayBuffer(pub(crate) Value); 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 struct JsArrayBufferValue {
pub(crate) value: JsArrayBuffer, pub(crate) value: JsArrayBuffer,
len: usize, len: usize,

View file

@ -20,6 +20,8 @@ impl TypeName for JsBigInt {
} }
} }
impl ValidateNapiValue for JsBigInt {}
impl JsBigInt { impl JsBigInt {
pub(crate) fn from_raw_unchecked( pub(crate) fn from_raw_unchecked(
env: sys::napi_env, env: sys::napi_env,

View file

@ -1,7 +1,7 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use super::Value; use super::Value;
use crate::bindgen_runtime::TypeName; use crate::bindgen_runtime::{TypeName, ValidateNapiValue};
use crate::{check_status, ValueType}; use crate::{check_status, ValueType};
use crate::{sys, Error, Result}; use crate::{sys, Error, Result};
@ -18,6 +18,8 @@ impl TypeName for JsBoolean {
} }
} }
impl ValidateNapiValue for JsBoolean {}
impl JsBoolean { impl JsBoolean {
pub fn get_value(&self) -> Result<bool> { pub fn get_value(&self) -> Result<bool> {
let mut result = false; let mut result = false;

View file

@ -3,7 +3,10 @@ use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use super::{Value, ValueType}; 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); 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 struct JsBufferValue {
pub(crate) value: JsBuffer, pub(crate) value: JsBuffer,
data: mem::ManuallyDrop<Vec<u8>>, data: mem::ManuallyDrop<Vec<u8>>,

View file

@ -73,6 +73,8 @@ impl TypeName for JsNull {
} }
} }
impl ValidateNapiValue for JsNull {}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct JsSymbol(pub(crate) Value); pub struct JsSymbol(pub(crate) Value);
@ -86,11 +88,7 @@ impl TypeName for JsSymbol {
} }
} }
impl ValidateNapiValue for JsSymbol { impl ValidateNapiValue for JsSymbol {}
fn type_of() -> Vec<ValueType> {
vec![ValueType::Symbol]
}
}
pub struct JsExternal(pub(crate) Value); pub struct JsExternal(pub(crate) Value);
@ -104,6 +102,8 @@ impl TypeName for JsExternal {
} }
} }
impl ValidateNapiValue for JsExternal {}
macro_rules! impl_napi_value_trait { macro_rules! impl_napi_value_trait {
($js_value:ident, $value_type:ident) => { ($js_value:ident, $value_type:ident) => {
impl NapiValue for $js_value { impl NapiValue for $js_value {

View file

@ -1,7 +1,7 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use super::Value; use super::Value;
use crate::bindgen_runtime::TypeName; use crate::bindgen_runtime::{TypeName, ValidateNapiValue};
use crate::{check_status, ValueType}; use crate::{check_status, ValueType};
use crate::{sys, Error, Result}; use crate::{sys, Error, Result};
@ -18,6 +18,8 @@ impl TypeName for JsNumber {
} }
} }
impl ValidateNapiValue for JsNumber {}
impl JsNumber { impl JsNumber {
pub fn get_uint32(&self) -> Result<u32> { pub fn get_uint32(&self) -> Result<u32> {
let mut result = 0; let mut result = 0;

View file

@ -2,6 +2,7 @@ use std::mem;
use std::ptr; use std::ptr;
use crate::bindgen_runtime::TypeName; use crate::bindgen_runtime::TypeName;
use crate::bindgen_runtime::ValidateNapiValue;
use crate::ValueType; use crate::ValueType;
use crate::{check_status, sys, Result, Value}; use crate::{check_status, sys, Result, Value};
@ -26,6 +27,8 @@ impl TypeName for JsString {
} }
} }
impl ValidateNapiValue for JsString {}
impl JsString { impl JsString {
pub fn utf8_len(&self) -> Result<usize> { pub fn utf8_len(&self) -> Result<usize> {
let mut length = 0; let mut length = 0;

View file

@ -1,4 +1,7 @@
use crate::{bindgen_runtime::TypeName, ValueType}; use crate::{
bindgen_runtime::{TypeName, ValidateNapiValue},
ValueType,
};
use super::Value; use super::Value;
@ -14,3 +17,5 @@ impl TypeName for JsUndefined {
ValueType::Undefined ValueType::Undefined
} }
} }
impl ValidateNapiValue for JsUndefined {}

View file

@ -62,6 +62,7 @@ Generated by [AVA](https://avajs.dev).
export function either4(input: string | number | boolean | Obj): number␊ export function either4(input: string | number | boolean | Obj): number␊
export function receiveClassOrNumber(either: number | JsClassForEither): number␊ export function receiveClassOrNumber(either: number | JsClassForEither): number␊
export function receiveMutClassOrNumber(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 returnEitherClass(input: number): number | JsClassForEither␊
export function eitherFromOption(): JsClassForEither | undefined␊ export function eitherFromOption(): JsClassForEither | undefined␊
/** default enum values are continuos i32s start from 0 */␊ /** default enum values are continuos i32s start from 0 */␊
@ -276,6 +277,9 @@ Generated by [AVA](https://avajs.dev).
export class JsClassForEither {␊ export class JsClassForEither {␊
constructor()␊ constructor()␊
}␊ }␊
export class AnotherClassForEither {␊
constructor()␊
}␊
export class Fib {␊ export class Fib {␊
[Symbol.iterator](): Iterator<number, void, number> [Symbol.iterator](): Iterator<number, void, number>
constructor()␊ constructor()␊

View file

@ -99,6 +99,8 @@ import {
overrideIndividualArgOnFunctionWithCbArg, overrideIndividualArgOnFunctionWithCbArg,
createObjectWithClassField, createObjectWithClassField,
receiveObjectWithClassField, receiveObjectWithClassField,
AnotherClassForEither,
receiveDifferentClass,
} from '../' } from '../'
test('export const', (t) => { test('export const', (t) => {
@ -500,6 +502,13 @@ test('receive class reference in either', (t) => {
t.is(receiveMutClassOrNumber(c), 100) 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) => { test('return either class', (t) => {
t.is(returnEitherClass(1), 1) t.is(returnEitherClass(1), 1)
t.true(returnEitherClass(-1) instanceof JsClassForEither) t.true(returnEitherClass(-1) instanceof JsClassForEither)

View file

@ -52,6 +52,7 @@ export interface Obj {
export function either4(input: string | number | boolean | Obj): number export function either4(input: string | number | boolean | Obj): number
export function receiveClassOrNumber(either: number | JsClassForEither): number export function receiveClassOrNumber(either: number | JsClassForEither): number
export function receiveMutClassOrNumber(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 returnEitherClass(input: number): number | JsClassForEither
export function eitherFromOption(): JsClassForEither | undefined export function eitherFromOption(): JsClassForEither | undefined
/** default enum values are continuos i32s start from 0 */ /** default enum values are continuos i32s start from 0 */
@ -266,6 +267,9 @@ export class ClassWithFactory {
export class JsClassForEither { export class JsClassForEither {
constructor() constructor()
} }
export class AnotherClassForEither {
constructor()
}
export class Fib { export class Fib {
[Symbol.iterator](): Iterator<number, void, number> [Symbol.iterator](): Iterator<number, void, number>
constructor() constructor()

View file

@ -67,6 +67,17 @@ impl JsClassForEither {
} }
} }
#[napi]
struct AnotherClassForEither {}
#[napi]
impl AnotherClassForEither {
#[napi(constructor)]
pub fn new() -> Self {
Self {}
}
}
#[napi] #[napi]
fn receive_class_or_number(either: Either<u32, &JsClassForEither>) -> u32 { fn receive_class_or_number(either: Either<u32, &JsClassForEither>) -> u32 {
match either { 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] #[napi]
fn return_either_class(input: i32) -> Either<u32, JsClassForEither> { fn return_either_class(input: i32) -> Either<u32, JsClassForEither> {
if input > 0 { if input > 0 {