fix(napi): missing ValidateNapiValue trait for types
This commit is contained in:
parent
b48a757837
commit
18afd86a2e
23 changed files with 563 additions and 21 deletions
|
@ -51,8 +51,9 @@ impl NapiEnum {
|
|||
unsafe fn validate(
|
||||
env: napi::bindgen_prelude::sys::napi_env,
|
||||
napi_val: napi::bindgen_prelude::sys::napi_value
|
||||
) -> napi::bindgen_prelude::Result<()> {
|
||||
napi::bindgen_prelude::assert_type_of!(env, napi_val, napi::bindgen_prelude::ValueType::Number)
|
||||
) -> napi::bindgen_prelude::Result<napi::sys::napi_value> {
|
||||
napi::bindgen_prelude::assert_type_of!(env, napi_val, napi::bindgen_prelude::ValueType::Number)?;
|
||||
Ok(std::ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -159,7 +159,10 @@ impl NapiFn {
|
|||
_ => {
|
||||
let type_check = if self.strict {
|
||||
quote! {
|
||||
<#ty as napi::bindgen_prelude::ValidateNapiValue>::validate(env, cb.get_arg(#index))?;
|
||||
let maybe_promise = <#ty as napi::bindgen_prelude::ValidateNapiValue>::validate(env, cb.get_arg(#index))?;
|
||||
if !maybe_promise.is_null() {
|
||||
return Ok(maybe_promise);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {}
|
||||
|
|
|
@ -114,10 +114,13 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
|||
/// # Safety
|
||||
///
|
||||
/// this function called to validate whether napi value passed to rust is valid type
|
||||
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<()> {
|
||||
unsafe fn validate(
|
||||
env: sys::napi_env,
|
||||
napi_val: sys::napi_value,
|
||||
) -> Result<napi_sys::napi_value> {
|
||||
let available_types = Self::type_of();
|
||||
if available_types.is_empty() {
|
||||
return Ok(());
|
||||
return Ok(ptr::null_mut());
|
||||
}
|
||||
|
||||
let mut result = -1;
|
||||
|
@ -128,7 +131,7 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
|||
|
||||
let received_type = ValueType::from(result);
|
||||
if available_types.contains(&received_type) {
|
||||
Ok(())
|
||||
Ok(ptr::null_mut())
|
||||
} else {
|
||||
Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
|
|
|
@ -257,7 +257,21 @@ impl<T> ValidateNapiValue for Vec<T>
|
|||
where
|
||||
T: FromNapiValue,
|
||||
{
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Object]
|
||||
unsafe fn validate(
|
||||
env: sys::napi_env,
|
||||
napi_val: sys::napi_value,
|
||||
) -> Result<napi_sys::napi_value> {
|
||||
let mut is_array = false;
|
||||
check_status!(
|
||||
unsafe { sys::napi_is_array(env, napi_val, &mut is_array) },
|
||||
"Failed to check given napi value is array"
|
||||
)?;
|
||||
if !is_array {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Expected an array".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::ptr;
|
|||
pub use crate::js_values::TypedArrayType;
|
||||
use crate::{check_status, sys, Error, Result, Status};
|
||||
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName};
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||
|
||||
macro_rules! impl_typed_array {
|
||||
($name:ident, $rust_type:ident, $typed_array_type:expr) => {
|
||||
|
@ -98,7 +98,7 @@ macro_rules! impl_typed_array {
|
|||
|
||||
impl TypeName for $name {
|
||||
fn type_name() -> &'static str {
|
||||
"TypedArray"
|
||||
concat!("TypedArray<", stringify!($rust_type), ">")
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
|
@ -106,6 +106,26 @@ macro_rules! impl_typed_array {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for $name {
|
||||
unsafe fn validate(
|
||||
env: sys::napi_env,
|
||||
napi_val: sys::napi_value,
|
||||
) -> Result<$crate::sys::napi_value> {
|
||||
let mut is_typed_array = false;
|
||||
check_status!(
|
||||
unsafe { sys::napi_is_typedarray(env, napi_val, &mut is_typed_array) },
|
||||
"Failed to check if value is typed array"
|
||||
)?;
|
||||
if !is_typed_array {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Expected a TypedArray value".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromNapiValue for $name {
|
||||
unsafe fn from_napi_value(
|
||||
env: napi_sys::napi_env,
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::ptr;
|
|||
|
||||
use crate::{check_status, sys};
|
||||
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName};
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||
|
||||
/// i64 is converted to `Number`
|
||||
#[repr(transparent)]
|
||||
|
@ -38,6 +38,12 @@ impl TypeName for BigInt {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for BigInt {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::BigInt]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromNapiValue for BigInt {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
|
||||
let mut word_count = 0usize;
|
||||
|
|
|
@ -140,7 +140,18 @@ impl ToNapiValue for Buffer {
|
|||
}
|
||||
|
||||
impl ValidateNapiValue for Buffer {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Object]
|
||||
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) },
|
||||
"Failed to validate napi buffer"
|
||||
)?;
|
||||
if !is_buffer {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Expected a Buffer value".to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
use crate::{bindgen_prelude::*, check_status, sys, ValueType};
|
||||
use std::ptr;
|
||||
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
|
||||
use crate::{bindgen_prelude::*, check_status, sys, ValueType};
|
||||
|
||||
impl TypeName for DateTime<Utc> {
|
||||
fn type_name() -> &'static str {
|
||||
"DateTime"
|
||||
|
@ -12,8 +15,20 @@ impl TypeName for DateTime<Utc> {
|
|||
}
|
||||
|
||||
impl ValidateNapiValue for DateTime<Utc> {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Object]
|
||||
unsafe fn validate(
|
||||
env: sys::napi_env,
|
||||
napi_val: sys::napi_value,
|
||||
) -> Result<napi_sys::napi_value> {
|
||||
let mut is_date = false;
|
||||
check_status!(unsafe { napi_sys::napi_is_date(env, napi_val, &mut is_date) })?;
|
||||
if !is_date {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Expected a Date object".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use crate::{check_status, Error, Status, TaggedObject};
|
||||
|
||||
use super::{FromNapiValue, ToNapiValue};
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||
|
||||
pub struct External<T: 'static> {
|
||||
obj: *mut TaggedObject<T>,
|
||||
|
@ -13,6 +13,22 @@ pub struct External<T: 'static> {
|
|||
pub adjusted_size: i64,
|
||||
}
|
||||
|
||||
impl<T: 'static> TypeName for External<T> {
|
||||
fn type_name() -> &'static str {
|
||||
"External"
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
crate::ValueType::External
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ValidateNapiValue for External<T> {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::External]
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> External<T> {
|
||||
pub fn new(value: T) -> Self {
|
||||
Self {
|
||||
|
|
|
@ -1 +1,9 @@
|
|||
use super::ValidateNapiValue;
|
||||
|
||||
pub use crate::JsFunction;
|
||||
|
||||
impl ValidateNapiValue for JsFunction {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::Function]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ 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, V, S> ToNapiValue for HashMap<K, V, S>
|
||||
where
|
||||
K: AsRef<str>,
|
||||
|
|
|
@ -88,3 +88,9 @@ impl TypeName for Object {
|
|||
ValueType::Object
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Object {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Object]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,79 @@ use tokio::sync::oneshot::{channel, Receiver, Sender};
|
|||
|
||||
use crate::{check_status, Error, Result, Status};
|
||||
|
||||
use super::FromNapiValue;
|
||||
use super::{FromNapiValue, TypeName, ValidateNapiValue};
|
||||
|
||||
pub struct Promise<T: FromNapiValue> {
|
||||
value: Pin<Box<Receiver<*mut Result<T>>>>,
|
||||
}
|
||||
|
||||
impl<T: FromNapiValue> TypeName for Promise<T> {
|
||||
fn type_name() -> &'static str {
|
||||
"Promise"
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
crate::ValueType::Object
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
) -> Result<napi_sys::napi_value> {
|
||||
let mut is_promise = false;
|
||||
check_status!(
|
||||
unsafe { crate::sys::napi_is_promise(env, napi_val, &mut is_promise) },
|
||||
"Failed to check if value is promise"
|
||||
)?;
|
||||
if !is_promise {
|
||||
let mut deferred = ptr::null_mut();
|
||||
let mut promise = ptr::null_mut();
|
||||
check_status!(
|
||||
unsafe { crate::sys::napi_create_promise(env, &mut deferred, &mut promise) },
|
||||
"Failed to create promise"
|
||||
)?;
|
||||
let mut err = ptr::null_mut();
|
||||
let mut code = ptr::null_mut();
|
||||
let mut message = ptr::null_mut();
|
||||
check_status!(
|
||||
unsafe {
|
||||
crate::sys::napi_create_string_utf8(
|
||||
env,
|
||||
CStr::from_bytes_with_nul_unchecked(b"InvalidArg\0").as_ptr(),
|
||||
10,
|
||||
&mut code,
|
||||
)
|
||||
},
|
||||
"Failed to create error message"
|
||||
)?;
|
||||
check_status!(
|
||||
unsafe {
|
||||
crate::sys::napi_create_string_utf8(
|
||||
env,
|
||||
CStr::from_bytes_with_nul_unchecked(b"Expected Promise object\0").as_ptr(),
|
||||
23,
|
||||
&mut message,
|
||||
)
|
||||
},
|
||||
"Failed to create error message"
|
||||
)?;
|
||||
check_status!(
|
||||
unsafe { crate::sys::napi_create_error(env, code, message, &mut err) },
|
||||
"Failed to create rejected error"
|
||||
)?;
|
||||
check_status!(unsafe { crate::sys::napi_reject_deferred(env, deferred, err) })?;
|
||||
return Ok(promise);
|
||||
}
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: FromNapiValue> Send for Promise<T> {}
|
||||
|
||||
impl<T: FromNapiValue> FromNapiValue for Promise<T> {
|
||||
|
|
|
@ -16,6 +16,12 @@ impl TypeName for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for String {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
|
||||
impl ToNapiValue for String {
|
||||
unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
|
||||
let mut ptr = ptr::null_mut();
|
||||
|
@ -75,6 +81,12 @@ impl TypeName for &str {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for &str {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
|
||||
impl FromNapiValue for &str {
|
||||
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
|
||||
let mut len = 0;
|
||||
|
@ -134,6 +146,12 @@ impl ToNapiValue for &str {
|
|||
#[derive(Debug)]
|
||||
pub struct Utf16String(String);
|
||||
|
||||
impl ValidateNapiValue for Utf16String {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Utf16String {
|
||||
fn from(s: String) -> Self {
|
||||
Utf16String(s)
|
||||
|
@ -227,6 +245,12 @@ pub mod latin1_string {
|
|||
#[derive(Debug)]
|
||||
pub struct Latin1String(String);
|
||||
|
||||
impl ValidateNapiValue for Latin1String {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::String]
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Latin1String {
|
||||
fn from(s: String) -> Self {
|
||||
Latin1String(s)
|
||||
|
|
|
@ -2,12 +2,28 @@ use std::{ffi::CString, ptr};
|
|||
|
||||
use crate::check_status;
|
||||
|
||||
use super::ToNapiValue;
|
||||
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||
|
||||
pub struct Symbol {
|
||||
desc: Option<String>,
|
||||
}
|
||||
|
||||
impl TypeName for Symbol {
|
||||
fn type_name() -> &'static str {
|
||||
"Symbol"
|
||||
}
|
||||
|
||||
fn value_type() -> crate::ValueType {
|
||||
crate::ValueType::Object
|
||||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for Symbol {
|
||||
fn type_of() -> Vec<crate::ValueType> {
|
||||
vec![crate::ValueType::Symbol]
|
||||
}
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
pub fn new(desc: String) -> Self {
|
||||
Self { desc: Some(desc) }
|
||||
|
@ -48,3 +64,12 @@ impl ToNapiValue for Symbol {
|
|||
Ok(symbol_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromNapiValue for Symbol {
|
||||
unsafe fn from_napi_value(
|
||||
_env: napi_sys::napi_env,
|
||||
_napi_val: napi_sys::napi_value,
|
||||
) -> crate::Result<Self> {
|
||||
Ok(Self { desc: None })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
use std::ptr;
|
||||
|
||||
use super::check_status;
|
||||
use crate::{bindgen_runtime::TypeName, sys, Result, Value, ValueType};
|
||||
use crate::{
|
||||
bindgen_runtime::{TypeName, ValidateNapiValue},
|
||||
sys, Error, Result, Status, Value, ValueType,
|
||||
};
|
||||
|
||||
pub struct JsDate(pub(crate) Value);
|
||||
|
||||
|
@ -13,6 +18,21 @@ impl TypeName for JsDate {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsDate {
|
||||
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
|
||||
let mut is_date = false;
|
||||
check_status!(unsafe { napi_sys::napi_is_date(env, napi_val, &mut is_date) })?;
|
||||
if !is_date {
|
||||
return Err(Error::new(
|
||||
Status::InvalidArg,
|
||||
"Expected a Date object".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ptr::null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl JsDate {
|
||||
pub fn value_of(&self) -> Result<f64> {
|
||||
let mut timestamp: f64 = 0.0;
|
||||
|
|
|
@ -3,7 +3,8 @@ use std::ffi::CString;
|
|||
use std::ptr;
|
||||
|
||||
use crate::{
|
||||
bindgen_runtime::TypeName, check_status, sys, type_of, Callback, Error, Result, Status, ValueType,
|
||||
bindgen_runtime::{TypeName, ValidateNapiValue},
|
||||
check_status, sys, type_of, Callback, Error, Result, Status, ValueType,
|
||||
};
|
||||
|
||||
#[cfg(feature = "serde-json")]
|
||||
|
@ -85,6 +86,12 @@ impl TypeName for JsSymbol {
|
|||
}
|
||||
}
|
||||
|
||||
impl ValidateNapiValue for JsSymbol {
|
||||
fn type_of() -> Vec<ValueType> {
|
||||
vec![ValueType::Symbol]
|
||||
}
|
||||
}
|
||||
|
||||
pub struct JsExternal(pub(crate) Value);
|
||||
|
||||
impl TypeName for JsExternal {
|
||||
|
|
168
examples/napi/__test__/strict.spect.ts
Normal file
168
examples/napi/__test__/strict.spect.ts
Normal file
|
@ -0,0 +1,168 @@
|
|||
import test from 'ava'
|
||||
|
||||
import {
|
||||
validateArray,
|
||||
validateTypedArray,
|
||||
validateBigint,
|
||||
validateBuffer,
|
||||
validateBoolean,
|
||||
validateDate,
|
||||
validateDateTime,
|
||||
createExternal,
|
||||
validateExternal,
|
||||
validateFunction,
|
||||
validateHashMap,
|
||||
validatePromise,
|
||||
validateString,
|
||||
validateSymbol,
|
||||
validateNull,
|
||||
validateUndefined,
|
||||
} from '../index'
|
||||
|
||||
test('should validate array', (t) => {
|
||||
t.is(validateArray([1, 2, 3]), 3)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateArray(1), {
|
||||
message: 'Expected an array',
|
||||
code: 'InvalidArg',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate arraybuffer', (t) => {
|
||||
t.is(validateTypedArray(new Uint8Array([1, 2, 3])), 3)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateTypedArray(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expected a TypedArray value',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate BigInt', (t) => {
|
||||
if (typeof BigInt === 'undefined') {
|
||||
t.pass('BigInt is not supported')
|
||||
} else {
|
||||
const fx = BigInt(1024 * 1024 * 1024 * 1024)
|
||||
t.is(validateBigint(fx), fx)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateBigint(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be BigInt, but received Number',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
test('should validate buffer', (t) => {
|
||||
t.is(validateBuffer(Buffer.from('hello')), 5)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateBuffer(2), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expected a Buffer value',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate boolean value', (t) => {
|
||||
t.is(validateBoolean(true), false)
|
||||
t.is(validateBoolean(false), true)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateBoolean(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be Boolean, but received Number',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate date', (t) => {
|
||||
if (Number(process.versions.napi) >= 5) {
|
||||
return t.pass()
|
||||
}
|
||||
const fx = new Date('2016-12-24')
|
||||
t.is(validateDate(new Date()), fx.valueOf())
|
||||
t.is(validateDateTime(fx), 1)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateDate(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expected a Date value',
|
||||
})
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateDateTime(2), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expected a Date value',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate External', (t) => {
|
||||
const fx = createExternal(1)
|
||||
t.is(validateExternal(fx), 1)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateExternal(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be External, but received Number',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate function', (t) => {
|
||||
t.is(
|
||||
validateFunction(() => 1),
|
||||
4,
|
||||
)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateFunction(2), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be Function, but received Number',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate Map', (t) => {
|
||||
t.is(validateHashMap({ a: 1, b: 2 }), 2)
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateHashMap(), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be Object, but received Undefined',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate promise', async (t) => {
|
||||
t.is(await validatePromise(Promise.resolve(1)), 2)
|
||||
// @ts-expect-error
|
||||
await t.throwsAsync(() => validatePromise(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expected Promise object',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate string', (t) => {
|
||||
t.is(validateString('hello'), 'hello!')
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateString(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be String, but received Number',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate symbol', (t) => {
|
||||
t.notThrows(() => validateSymbol(Symbol()))
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateSymbol(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be Symbol, but received Number',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate null', (t) => {
|
||||
t.notThrows(() => validateNull(null))
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateNull(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be Null, but received Number',
|
||||
})
|
||||
})
|
||||
|
||||
test('should validate undefined', (t) => {
|
||||
t.notThrows(() => validateUndefined(void 0))
|
||||
// @ts-expect-error
|
||||
t.notThrows(() => validateUndefined())
|
||||
// @ts-expect-error
|
||||
t.throws(() => validateUndefined(1), {
|
||||
code: 'InvalidArg',
|
||||
message: 'Expect value to be Undefined, but received Number',
|
||||
})
|
||||
})
|
|
@ -82,6 +82,22 @@ Generated by [AVA](https://avajs.dev).
|
|||
export function createExternalString(content: string): ExternalObject<string>␊
|
||||
export function getExternal(external: ExternalObject<number>): number␊
|
||||
export function mutateExternal(external: ExternalObject<number>, newVal: number): void␊
|
||||
export function validateArray(arr: Array<number>): number␊
|
||||
export function validateBuffer(b: Buffer): number␊
|
||||
export function validateTypedArray(input: Uint8Array): number␊
|
||||
export function validateBigint(input: bigint): bigint␊
|
||||
export function validateBoolean(i: boolean): boolean␊
|
||||
export function validateDate(d: Date): number␊
|
||||
export function validateDateTime(d: Date): number␊
|
||||
export function validateExternal(e: ExternalObject<number>): number␊
|
||||
export function validateFunction(cb: () => number): number␊
|
||||
export function validateHashMap(input: Record<string, number>): number␊
|
||||
export function validateNull(i: null): boolean␊
|
||||
export function validateUndefined(i: undefined): boolean␊
|
||||
export function validateNumber(i: number): number␊
|
||||
export function validatePromise(p: Promise<number>): Promise<number>␊
|
||||
export function validateString(s: string): string␊
|
||||
export function validateSymbol(s: symbol): boolean␊
|
||||
export function tsRename(a: { foo: number }): string[]␊
|
||||
export function xxh64Alias(input: Buffer): bigint␊
|
||||
export function getMapping(): Record<string, number>␊
|
||||
|
|
Binary file not shown.
16
examples/napi/index.d.ts
vendored
16
examples/napi/index.d.ts
vendored
|
@ -72,6 +72,22 @@ export function createExternal(size: number): ExternalObject<number>
|
|||
export function createExternalString(content: string): ExternalObject<string>
|
||||
export function getExternal(external: ExternalObject<number>): number
|
||||
export function mutateExternal(external: ExternalObject<number>, newVal: number): void
|
||||
export function validateArray(arr: Array<number>): number
|
||||
export function validateBuffer(b: Buffer): number
|
||||
export function validateTypedArray(input: Uint8Array): number
|
||||
export function validateBigint(input: bigint): bigint
|
||||
export function validateBoolean(i: boolean): boolean
|
||||
export function validateDate(d: Date): number
|
||||
export function validateDateTime(d: Date): number
|
||||
export function validateExternal(e: ExternalObject<number>): number
|
||||
export function validateFunction(cb: () => number): number
|
||||
export function validateHashMap(input: Record<string, number>): number
|
||||
export function validateNull(i: null): boolean
|
||||
export function validateUndefined(i: undefined): boolean
|
||||
export function validateNumber(i: number): number
|
||||
export function validatePromise(p: Promise<number>): Promise<number>
|
||||
export function validateString(s: string): string
|
||||
export function validateSymbol(s: symbol): boolean
|
||||
export function tsRename(a: { foo: number }): string[]
|
||||
export function xxh64Alias(input: Buffer): bigint
|
||||
export function getMapping(): Record<string, number>
|
||||
|
|
89
examples/napi/src/fn_strict.rs
Normal file
89
examples/napi/src/fn_strict.rs
Normal file
|
@ -0,0 +1,89 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use napi::{bindgen_prelude::*, JsSymbol, JsUnknown};
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_array(arr: Vec<u32>) -> u32 {
|
||||
arr.len() as u32
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_buffer(b: Buffer) -> u32 {
|
||||
b.len() as u32
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_typed_array(input: Uint8Array) -> u32 {
|
||||
input.len() as u32
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_bigint(input: BigInt) -> i128 {
|
||||
input.get_i128().0
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_boolean(i: bool) -> bool {
|
||||
!i
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_date(d: Date) -> Result<f64> {
|
||||
d.value_of()
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_date_time(_d: DateTime<Utc>) -> i64 {
|
||||
1
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_external(e: External<u32>) -> u32 {
|
||||
*e
|
||||
}
|
||||
|
||||
#[napi(strict, ts_args_type = "cb: () => number")]
|
||||
fn validate_function(cb: JsFunction) -> Result<u32> {
|
||||
Ok(
|
||||
cb.call::<JsUnknown>(None, &[])?
|
||||
.coerce_to_number()?
|
||||
.get_uint32()?
|
||||
+ 3,
|
||||
)
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_hash_map(input: HashMap<String, u32>) -> u32 {
|
||||
input.len() as u32
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_null(_i: Null) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_undefined(_i: Undefined) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_number(i: f64) -> f64 {
|
||||
i + 1.0
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
async fn validate_promise(p: Promise<u32>) -> Result<u32> {
|
||||
Ok(p.await? + 1)
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_string(s: String) -> String {
|
||||
s + "!"
|
||||
}
|
||||
|
||||
#[napi(strict)]
|
||||
fn validate_symbol(_s: JsSymbol) -> bool {
|
||||
true
|
||||
}
|
|
@ -23,6 +23,7 @@ mod either;
|
|||
mod r#enum;
|
||||
mod error;
|
||||
mod external;
|
||||
mod fn_strict;
|
||||
mod fn_ts_override;
|
||||
mod js_mod;
|
||||
mod map;
|
||||
|
|
Loading…
Reference in a new issue