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.
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 {}
}
}

View file

@ -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"),

View file

@ -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
)
},
value_type, received_type
),
))
}
}

View file

@ -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 {

View file

@ -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> {

View file

@ -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> {

View file

@ -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,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)]
pub enum Either3<A, B, C> {
A(A),
B(B),
C(C),
pub enum $either_name< $( $parameter ),+ > {
$( $parameter ( $parameter ) ),+
}
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 {
"Either3"
stringify!( $either_name )
}
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>
FromNapiValue for Either3<A, B, C>
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> {
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(
Status::InvalidArg,
format!(
"Expect type {} or {} or {}, but got {}",
A::value_type(),
B::value_type(),
C::value_type(),
js_type
concat!("Value is non of these types ", $( "`{", stringify!( $parameter ), "}`, " ),+ ),
$( $parameter = $parameter::value_type(), )+
),
))
}
}
}
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) },
}
}
}
#[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>
impl< $( $parameter ),+ > ToNapiValue for $either_name < $( $parameter ),+ >
where $( $parameter: ToNapiValue ),+
{
unsafe fn to_napi_value(
env: sys::napi_env,
value: Self,
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:: $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);

View file

@ -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 {

View file

@ -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 {}

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> {
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

View file

@ -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> {

View file

@ -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)]

View file

@ -88,9 +88,3 @@ impl TypeName for 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> {
fn type_of() -> Vec<crate::ValueType> {
vec![crate::ValueType::Object]
}
unsafe fn validate(
env: crate::sys::napi_env,
napi_val: crate::sys::napi_value,

View file

@ -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 {

View file

@ -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 {

View file

@ -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,

View file

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

View file

@ -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;

View file

@ -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>>,

View file

@ -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 {

View file

@ -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;

View file

@ -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;

View file

@ -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 {}

View file

@ -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()␊

View file

@ -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)

View file

@ -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()

View file

@ -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 {