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(
|
unsafe fn validate(
|
||||||
env: napi::bindgen_prelude::sys::napi_env,
|
env: napi::bindgen_prelude::sys::napi_env,
|
||||||
napi_val: napi::bindgen_prelude::sys::napi_value
|
napi_val: napi::bindgen_prelude::sys::napi_value
|
||||||
) -> napi::bindgen_prelude::Result<()> {
|
) -> napi::bindgen_prelude::Result<napi::sys::napi_value> {
|
||||||
napi::bindgen_prelude::assert_type_of!(env, napi_val, napi::bindgen_prelude::ValueType::Number)
|
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 {
|
let type_check = if self.strict {
|
||||||
quote! {
|
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 {
|
} else {
|
||||||
quote! {}
|
quote! {}
|
||||||
|
|
|
@ -114,10 +114,13 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
||||||
/// # 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
|
||||||
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();
|
let available_types = Self::type_of();
|
||||||
if available_types.is_empty() {
|
if available_types.is_empty() {
|
||||||
return Ok(());
|
return Ok(ptr::null_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = -1;
|
let mut result = -1;
|
||||||
|
@ -128,7 +131,7 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
||||||
|
|
||||||
let received_type = ValueType::from(result);
|
let received_type = ValueType::from(result);
|
||||||
if available_types.contains(&received_type) {
|
if available_types.contains(&received_type) {
|
||||||
Ok(())
|
Ok(ptr::null_mut())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::new(
|
Err(Error::new(
|
||||||
Status::InvalidArg,
|
Status::InvalidArg,
|
||||||
|
|
|
@ -257,7 +257,21 @@ impl<T> ValidateNapiValue for Vec<T>
|
||||||
where
|
where
|
||||||
T: FromNapiValue,
|
T: FromNapiValue,
|
||||||
{
|
{
|
||||||
fn type_of() -> Vec<ValueType> {
|
unsafe fn validate(
|
||||||
vec![ValueType::Object]
|
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;
|
pub use crate::js_values::TypedArrayType;
|
||||||
use crate::{check_status, sys, Error, Result, Status};
|
use crate::{check_status, sys, Error, Result, Status};
|
||||||
|
|
||||||
use super::{FromNapiValue, ToNapiValue, TypeName};
|
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||||
|
|
||||||
macro_rules! impl_typed_array {
|
macro_rules! impl_typed_array {
|
||||||
($name:ident, $rust_type:ident, $typed_array_type:expr) => {
|
($name:ident, $rust_type:ident, $typed_array_type:expr) => {
|
||||||
|
@ -98,7 +98,7 @@ macro_rules! impl_typed_array {
|
||||||
|
|
||||||
impl TypeName for $name {
|
impl TypeName for $name {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"TypedArray"
|
concat!("TypedArray<", stringify!($rust_type), ">")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn value_type() -> crate::ValueType {
|
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 {
|
impl FromNapiValue for $name {
|
||||||
unsafe fn from_napi_value(
|
unsafe fn from_napi_value(
|
||||||
env: napi_sys::napi_env,
|
env: napi_sys::napi_env,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use std::ptr;
|
||||||
|
|
||||||
use crate::{check_status, sys};
|
use crate::{check_status, sys};
|
||||||
|
|
||||||
use super::{FromNapiValue, ToNapiValue, TypeName};
|
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||||
|
|
||||||
/// i64 is converted to `Number`
|
/// i64 is converted to `Number`
|
||||||
#[repr(transparent)]
|
#[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 {
|
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> {
|
||||||
let mut word_count = 0usize;
|
let mut word_count = 0usize;
|
||||||
|
|
|
@ -140,7 +140,18 @@ impl ToNapiValue for Buffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateNapiValue for Buffer {
|
impl ValidateNapiValue for Buffer {
|
||||||
fn type_of() -> Vec<ValueType> {
|
unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
|
||||||
vec![ValueType::Object]
|
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 chrono::{DateTime, NaiveDateTime, Utc};
|
||||||
|
|
||||||
|
use crate::{bindgen_prelude::*, check_status, sys, ValueType};
|
||||||
|
|
||||||
impl TypeName for DateTime<Utc> {
|
impl TypeName for DateTime<Utc> {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"DateTime"
|
"DateTime"
|
||||||
|
@ -12,8 +15,20 @@ impl TypeName for DateTime<Utc> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateNapiValue for DateTime<Utc> {
|
impl ValidateNapiValue for DateTime<Utc> {
|
||||||
fn type_of() -> Vec<ValueType> {
|
unsafe fn validate(
|
||||||
vec![ValueType::Object]
|
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 crate::{check_status, Error, Status, TaggedObject};
|
||||||
|
|
||||||
use super::{FromNapiValue, ToNapiValue};
|
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||||
|
|
||||||
pub struct External<T: 'static> {
|
pub struct External<T: 'static> {
|
||||||
obj: *mut TaggedObject<T>,
|
obj: *mut TaggedObject<T>,
|
||||||
|
@ -13,6 +13,22 @@ pub struct External<T: 'static> {
|
||||||
pub adjusted_size: i64,
|
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> {
|
impl<T: 'static> External<T> {
|
||||||
pub fn new(value: T) -> Self {
|
pub fn new(value: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -1 +1,9 @@
|
||||||
|
use super::ValidateNapiValue;
|
||||||
|
|
||||||
pub use crate::JsFunction;
|
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>
|
impl<K, V, S> ToNapiValue for HashMap<K, V, S>
|
||||||
where
|
where
|
||||||
K: AsRef<str>,
|
K: AsRef<str>,
|
||||||
|
|
|
@ -88,3 +88,9 @@ impl TypeName for Object {
|
||||||
ValueType::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 crate::{check_status, Error, Result, Status};
|
||||||
|
|
||||||
use super::FromNapiValue;
|
use super::{FromNapiValue, TypeName, ValidateNapiValue};
|
||||||
|
|
||||||
pub struct Promise<T: FromNapiValue> {
|
pub struct Promise<T: FromNapiValue> {
|
||||||
value: Pin<Box<Receiver<*mut Result<T>>>>,
|
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> {}
|
unsafe impl<T: FromNapiValue> Send for Promise<T> {}
|
||||||
|
|
||||||
impl<T: FromNapiValue> FromNapiValue 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 {
|
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> {
|
||||||
let mut ptr = ptr::null_mut();
|
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 {
|
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> {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
|
@ -134,6 +146,12 @@ impl ToNapiValue for &str {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Utf16String(String);
|
pub struct Utf16String(String);
|
||||||
|
|
||||||
|
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 {
|
||||||
Utf16String(s)
|
Utf16String(s)
|
||||||
|
@ -227,6 +245,12 @@ pub mod latin1_string {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Latin1String(String);
|
pub struct Latin1String(String);
|
||||||
|
|
||||||
|
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 {
|
||||||
Latin1String(s)
|
Latin1String(s)
|
||||||
|
|
|
@ -2,12 +2,28 @@ use std::{ffi::CString, ptr};
|
||||||
|
|
||||||
use crate::check_status;
|
use crate::check_status;
|
||||||
|
|
||||||
use super::ToNapiValue;
|
use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue};
|
||||||
|
|
||||||
pub struct Symbol {
|
pub struct Symbol {
|
||||||
desc: Option<String>,
|
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 {
|
impl Symbol {
|
||||||
pub fn new(desc: String) -> Self {
|
pub fn new(desc: String) -> Self {
|
||||||
Self { desc: Some(desc) }
|
Self { desc: Some(desc) }
|
||||||
|
@ -48,3 +64,12 @@ impl ToNapiValue for Symbol {
|
||||||
Ok(symbol_value)
|
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 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);
|
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 {
|
impl JsDate {
|
||||||
pub fn value_of(&self) -> Result<f64> {
|
pub fn value_of(&self) -> Result<f64> {
|
||||||
let mut timestamp: f64 = 0.0;
|
let mut timestamp: f64 = 0.0;
|
||||||
|
|
|
@ -3,7 +3,8 @@ use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use crate::{
|
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")]
|
#[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);
|
pub struct JsExternal(pub(crate) Value);
|
||||||
|
|
||||||
impl TypeName for JsExternal {
|
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 createExternalString(content: string): ExternalObject<string>␊
|
||||||
export function getExternal(external: ExternalObject<number>): number␊
|
export function getExternal(external: ExternalObject<number>): number␊
|
||||||
export function mutateExternal(external: ExternalObject<number>, newVal: number): void␊
|
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 tsRename(a: { foo: number }): string[]␊
|
||||||
export function xxh64Alias(input: Buffer): bigint␊
|
export function xxh64Alias(input: Buffer): bigint␊
|
||||||
export function getMapping(): Record<string, number>␊
|
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 createExternalString(content: string): ExternalObject<string>
|
||||||
export function getExternal(external: ExternalObject<number>): number
|
export function getExternal(external: ExternalObject<number>): number
|
||||||
export function mutateExternal(external: ExternalObject<number>, newVal: number): void
|
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 tsRename(a: { foo: number }): string[]
|
||||||
export function xxh64Alias(input: Buffer): bigint
|
export function xxh64Alias(input: Buffer): bigint
|
||||||
export function getMapping(): Record<string, number>
|
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 r#enum;
|
||||||
mod error;
|
mod error;
|
||||||
mod external;
|
mod external;
|
||||||
|
mod fn_strict;
|
||||||
mod fn_ts_override;
|
mod fn_ts_override;
|
||||||
mod js_mod;
|
mod js_mod;
|
||||||
mod map;
|
mod map;
|
||||||
|
|
Loading…
Reference in a new issue