feat(napi): implement Either
type
This commit is contained in:
parent
ff593eac6a
commit
f26cd4aa7b
19 changed files with 538 additions and 1 deletions
|
@ -38,6 +38,10 @@ impl NapiEnum {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
#name_str
|
#name_str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> napi::ValueType {
|
||||||
|
napi::ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateNapiValue for #name {
|
impl ValidateNapiValue for #name {
|
||||||
|
|
|
@ -16,6 +16,10 @@ fn gen_napi_value_map_impl(name: &Ident, to_napi_val_impl: TokenStream) -> Token
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
#name_str
|
#name_str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> napi::ValueType {
|
||||||
|
napi::ValueType::Function
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#to_napi_val_impl
|
#to_napi_val_impl
|
||||||
|
@ -255,6 +259,10 @@ impl NapiStruct {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
#name_str
|
#name_str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> napi::ValueType {
|
||||||
|
napi::ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNapiValue for #name {
|
impl ToNapiValue for #name {
|
||||||
|
|
|
@ -59,6 +59,10 @@ static KNOWN_TYPES: Lazy<HashMap<&'static str, &'static str>> = Lazy::new(|| {
|
||||||
("Vec", "Array<{}>"),
|
("Vec", "Array<{}>"),
|
||||||
("Option", "{} | null"),
|
("Option", "{} | null"),
|
||||||
("Result", "Error | {}"),
|
("Result", "Error | {}"),
|
||||||
|
("Either", "{} | {}"),
|
||||||
|
("Either3", "{} | {} | {}"),
|
||||||
|
("Either4", "{} | {} | {} | {}"),
|
||||||
|
("Either5", "{} | {} | {} | {} | {}"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
map
|
map
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::ptr;
|
||||||
mod array;
|
mod array;
|
||||||
mod boolean;
|
mod boolean;
|
||||||
mod buffer;
|
mod buffer;
|
||||||
|
mod either;
|
||||||
mod map;
|
mod map;
|
||||||
mod nil;
|
mod nil;
|
||||||
mod number;
|
mod number;
|
||||||
|
@ -14,6 +15,7 @@ mod string;
|
||||||
|
|
||||||
pub use array::*;
|
pub use array::*;
|
||||||
pub use buffer::*;
|
pub use buffer::*;
|
||||||
|
pub use either::*;
|
||||||
pub use nil::*;
|
pub use nil::*;
|
||||||
pub use object::*;
|
pub use object::*;
|
||||||
pub use string::*;
|
pub use string::*;
|
||||||
|
@ -23,6 +25,8 @@ pub use string::latin1_string::*;
|
||||||
|
|
||||||
pub trait TypeName {
|
pub trait TypeName {
|
||||||
fn type_name() -> &'static str;
|
fn type_name() -> &'static str;
|
||||||
|
|
||||||
|
fn value_type() -> ValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ToNapiValue {
|
pub trait ToNapiValue {
|
||||||
|
@ -114,10 +118,14 @@ pub trait ValidateNapiValue: FromNapiValue + TypeName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TypeName for Option<T> {
|
impl<T: TypeName> TypeName for Option<T> {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"Option"
|
"Option"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
T::value_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> FromNapiValue for Option<T>
|
impl<T> FromNapiValue for Option<T>
|
||||||
|
|
|
@ -74,6 +74,10 @@ impl TypeName for Array {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"Array"
|
"Array"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNapiValue for Array {
|
impl ToNapiValue for Array {
|
||||||
|
@ -122,6 +126,10 @@ impl<T> TypeName for Vec<T> {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"Array<T>"
|
"Array<T>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ToNapiValue for Vec<T>
|
impl<T> ToNapiValue for Vec<T>
|
||||||
|
|
|
@ -4,6 +4,10 @@ impl TypeName for bool {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"bool"
|
"bool"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Boolean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateNapiValue for bool {
|
impl ValidateNapiValue for bool {
|
||||||
|
|
|
@ -52,6 +52,10 @@ impl TypeName for Buffer {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"Vec<u8>"
|
"Vec<u8>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromNapiValue for Buffer {
|
impl FromNapiValue for Buffer {
|
||||||
|
|
359
crates/napi/src/bindgen_runtime/js_values/either.rs
Normal file
359
crates/napi/src/bindgen_runtime/js_values/either.rs
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
use super::{FromNapiValue, ToNapiValue, TypeName};
|
||||||
|
use crate::{type_of, 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: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> {
|
||||||
|
A(A),
|
||||||
|
B(B),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: TypeName + FromNapiValue + ToNapiValue, B: TypeName + FromNapiValue + ToNapiValue> TypeName
|
||||||
|
for Either<A, B>
|
||||||
|
{
|
||||||
|
fn type_name() -> &'static str {
|
||||||
|
"Either"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: TypeName + FromNapiValue + ToNapiValue, B: TypeName + FromNapiValue + ToNapiValue>
|
||||||
|
FromNapiValue for Either<A, B>
|
||||||
|
{
|
||||||
|
unsafe fn from_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
napi_val: napi_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() {
|
||||||
|
A::from_napi_value(env, napi_val).map(Self::A)
|
||||||
|
} else if js_type == B::value_type() {
|
||||||
|
B::from_napi_value(env, napi_val).map(Self::B)
|
||||||
|
} else {
|
||||||
|
Err(crate::Error::new(
|
||||||
|
Status::InvalidArg,
|
||||||
|
format!(
|
||||||
|
"Expect type {} or {}, but got {}",
|
||||||
|
A::value_type(),
|
||||||
|
B::value_type(),
|
||||||
|
js_type
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: TypeName + FromNapiValue + ToNapiValue, B: TypeName + FromNapiValue + ToNapiValue>
|
||||||
|
ToNapiValue for Either<A, B>
|
||||||
|
{
|
||||||
|
unsafe fn to_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
value: Self,
|
||||||
|
) -> crate::Result<crate::sys::napi_value> {
|
||||||
|
match value {
|
||||||
|
Self::A(a) => A::to_napi_value(env, a),
|
||||||
|
Self::B(b) => B::to_napi_value(env, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Either3<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> {
|
||||||
|
A(A),
|
||||||
|
B(B),
|
||||||
|
C(C),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> TypeName for Either3<A, B, C>
|
||||||
|
{
|
||||||
|
fn type_name() -> &'static str {
|
||||||
|
"Either3"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> FromNapiValue for Either3<A, B, C>
|
||||||
|
{
|
||||||
|
unsafe fn from_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
napi_val: napi_sys::napi_value,
|
||||||
|
) -> crate::Result<Self> {
|
||||||
|
debug_assert!(
|
||||||
|
{
|
||||||
|
let mut types = vec![A::value_type(), B::value_type(), C::value_type()];
|
||||||
|
types.dedup();
|
||||||
|
types.len() == 3
|
||||||
|
},
|
||||||
|
"{}",
|
||||||
|
ERROR_MSG
|
||||||
|
);
|
||||||
|
let js_type = type_of!(env, napi_val)?;
|
||||||
|
if js_type == A::value_type() {
|
||||||
|
A::from_napi_value(env, napi_val).map(Self::A)
|
||||||
|
} else if js_type == B::value_type() {
|
||||||
|
B::from_napi_value(env, napi_val).map(Self::B)
|
||||||
|
} else if js_type == C::value_type() {
|
||||||
|
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
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> ToNapiValue for Either3<A, B, C>
|
||||||
|
{
|
||||||
|
unsafe fn to_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
value: Self,
|
||||||
|
) -> crate::Result<crate::sys::napi_value> {
|
||||||
|
match value {
|
||||||
|
Self::A(a) => A::to_napi_value(env, a),
|
||||||
|
Self::B(b) => B::to_napi_value(env, b),
|
||||||
|
Self::C(c) => C::to_napi_value(env, c),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Either4<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> {
|
||||||
|
A(A),
|
||||||
|
B(B),
|
||||||
|
C(C),
|
||||||
|
D(D),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> TypeName for Either4<A, B, C, D>
|
||||||
|
{
|
||||||
|
fn type_name() -> &'static str {
|
||||||
|
"Either4"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> FromNapiValue for Either4<A, B, C, D>
|
||||||
|
{
|
||||||
|
unsafe fn from_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
napi_val: napi_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() {
|
||||||
|
A::from_napi_value(env, napi_val).map(Self::A)
|
||||||
|
} else if js_type == B::value_type() {
|
||||||
|
B::from_napi_value(env, napi_val).map(Self::B)
|
||||||
|
} else if js_type == C::value_type() {
|
||||||
|
C::from_napi_value(env, napi_val).map(Self::C)
|
||||||
|
} else if js_type == D::value_type() {
|
||||||
|
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: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> ToNapiValue for Either4<A, B, C, D>
|
||||||
|
{
|
||||||
|
unsafe fn to_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
value: Self,
|
||||||
|
) -> crate::Result<crate::sys::napi_value> {
|
||||||
|
match value {
|
||||||
|
Self::A(a) => A::to_napi_value(env, a),
|
||||||
|
Self::B(b) => B::to_napi_value(env, b),
|
||||||
|
Self::C(c) => C::to_napi_value(env, c),
|
||||||
|
Self::D(d) => D::to_napi_value(env, d),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Either5<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
E: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> {
|
||||||
|
A(A),
|
||||||
|
B(B),
|
||||||
|
C(C),
|
||||||
|
D(D),
|
||||||
|
E(E),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
E: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> TypeName for Either5<A, B, C, D, E>
|
||||||
|
{
|
||||||
|
fn type_name() -> &'static str {
|
||||||
|
"Either5"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
A: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
E: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> FromNapiValue for Either5<A, B, C, D, E>
|
||||||
|
{
|
||||||
|
unsafe fn from_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
napi_val: napi_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() {
|
||||||
|
A::from_napi_value(env, napi_val).map(Self::A)
|
||||||
|
} else if js_type == B::value_type() {
|
||||||
|
B::from_napi_value(env, napi_val).map(Self::B)
|
||||||
|
} else if js_type == C::value_type() {
|
||||||
|
C::from_napi_value(env, napi_val).map(Self::C)
|
||||||
|
} else if js_type == D::value_type() {
|
||||||
|
D::from_napi_value(env, napi_val).map(Self::D)
|
||||||
|
} else if js_type == E::value_type() {
|
||||||
|
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: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
B: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
C: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
D: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
E: TypeName + FromNapiValue + ToNapiValue,
|
||||||
|
> ToNapiValue for Either5<A, B, C, D, E>
|
||||||
|
{
|
||||||
|
unsafe fn to_napi_value(
|
||||||
|
env: napi_sys::napi_env,
|
||||||
|
value: Self,
|
||||||
|
) -> crate::Result<crate::sys::napi_value> {
|
||||||
|
match value {
|
||||||
|
Self::A(a) => A::to_napi_value(env, a),
|
||||||
|
Self::B(b) => B::to_napi_value(env, b),
|
||||||
|
Self::C(c) => C::to_napi_value(env, c),
|
||||||
|
Self::D(d) => D::to_napi_value(env, d),
|
||||||
|
Self::E(e) => E::to_napi_value(env, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,10 @@ impl<K, V> TypeName for HashMap<K, V> {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"HashMap"
|
"HashMap"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K, V> ToNapiValue for HashMap<K, V>
|
impl<K, V> ToNapiValue for HashMap<K, V>
|
||||||
|
|
|
@ -9,6 +9,10 @@ impl TypeName for Null {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"null"
|
"null"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateNapiValue for Null {
|
impl ValidateNapiValue for Null {
|
||||||
|
@ -46,6 +50,10 @@ impl TypeName for Undefined {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"undefined"
|
"undefined"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ValidateNapiValue for Undefined {
|
impl ValidateNapiValue for Undefined {
|
||||||
|
|
|
@ -8,6 +8,10 @@ macro_rules! impl_number_conversions {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
$name
|
$name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> crate::ValueType {
|
||||||
|
crate::ValueType::Number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $crate::bindgen_prelude::ValidateNapiValue for $t {
|
impl $crate::bindgen_prelude::ValidateNapiValue for $t {
|
||||||
|
|
|
@ -81,6 +81,10 @@ impl TypeName for Object {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"Object"
|
"Object"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::Object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNapiValue for Object {
|
impl ToNapiValue for Object {
|
||||||
|
|
|
@ -11,6 +11,10 @@ impl TypeName for String {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"String"
|
"String"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNapiValue for String {
|
impl ToNapiValue for String {
|
||||||
|
@ -61,6 +65,10 @@ impl TypeName for &str {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"String"
|
"String"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToNapiValue for &str {
|
impl ToNapiValue for &str {
|
||||||
|
@ -96,6 +104,10 @@ impl TypeName for Utf16String {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"String(utf16)"
|
"String(utf16)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromNapiValue for Utf16String {
|
impl FromNapiValue for Utf16String {
|
||||||
|
@ -181,6 +193,10 @@ pub mod latin1_string {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"String(latin1)"
|
"String(latin1)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn value_type() -> ValueType {
|
||||||
|
ValueType::String
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "latin1")]
|
#[cfg(feature = "latin1")]
|
||||||
|
|
|
@ -14,6 +14,13 @@ Generated by [AVA](https://avajs.dev).
|
||||||
export function readFileAsync(path: string): Promise<Buffer>␊
|
export function readFileAsync(path: string): Promise<Buffer>␊
|
||||||
export function getCwd(callback: (arg0: string) => void): void␊
|
export function getCwd(callback: (arg0: string) => void): void␊
|
||||||
export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void␊
|
export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void␊
|
||||||
|
export function eitherStringOrNumber(input: string | number): number␊
|
||||||
|
export function returnEither(input: number): string | number␊
|
||||||
|
export function either3(input: string | number | boolean): number␊
|
||||||
|
interface Obj {␊
|
||||||
|
v: string | number␊
|
||||||
|
}␊
|
||||||
|
export function either4(input: string | number | boolean | Obj): number␊
|
||||||
export enum Kind { Dog = 0, Cat = 1, Duck = 2 }␊
|
export enum Kind { Dog = 0, Cat = 1, Duck = 2 }␊
|
||||||
export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }␊
|
export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }␊
|
||||||
export function enumToI32(e: CustomNumEnum): number␊
|
export function enumToI32(e: CustomNumEnum): number␊
|
||||||
|
|
Binary file not shown.
|
@ -26,6 +26,10 @@ import {
|
||||||
getPackageJsonName,
|
getPackageJsonName,
|
||||||
getBuffer,
|
getBuffer,
|
||||||
readFileAsync,
|
readFileAsync,
|
||||||
|
eitherStringOrNumber,
|
||||||
|
returnEither,
|
||||||
|
either3,
|
||||||
|
either4,
|
||||||
} from '../'
|
} from '../'
|
||||||
|
|
||||||
test('number', (t) => {
|
test('number', (t) => {
|
||||||
|
@ -130,3 +134,29 @@ test('async', async (t) => {
|
||||||
|
|
||||||
await t.throwsAsync(() => readFileAsync('some_nonexist_path.file'))
|
await t.throwsAsync(() => readFileAsync('some_nonexist_path.file'))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('either', (t) => {
|
||||||
|
t.is(eitherStringOrNumber(2), 2)
|
||||||
|
t.is(eitherStringOrNumber('hello'), 'hello'.length)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('return either', (t) => {
|
||||||
|
t.is(returnEither(2), 2)
|
||||||
|
t.is(returnEither(42), '42')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('either3', (t) => {
|
||||||
|
t.is(either3(2), 2)
|
||||||
|
t.is(either3('hello'), 'hello'.length)
|
||||||
|
t.is(either3(true), 1)
|
||||||
|
t.is(either3(false), 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('either4', (t) => {
|
||||||
|
t.is(either4(2), 2)
|
||||||
|
t.is(either4('hello'), 'hello'.length)
|
||||||
|
t.is(either4(true), 1)
|
||||||
|
t.is(either4(false), 0)
|
||||||
|
t.is(either4({ v: 1 }), 1)
|
||||||
|
t.is(either4({ v: 'world' }), 'world'.length)
|
||||||
|
})
|
||||||
|
|
7
examples/napi/index.d.ts
vendored
7
examples/napi/index.d.ts
vendored
|
@ -4,6 +4,13 @@ export function sumNums(nums: Array<number>): number
|
||||||
export function readFileAsync(path: string): Promise<Buffer>
|
export function readFileAsync(path: string): Promise<Buffer>
|
||||||
export function getCwd(callback: (arg0: string) => void): void
|
export function getCwd(callback: (arg0: string) => void): void
|
||||||
export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void
|
export function readFile(callback: (arg0: Error | undefined, arg1: string | null) => void): void
|
||||||
|
export function eitherStringOrNumber(input: string | number): number
|
||||||
|
export function returnEither(input: number): string | number
|
||||||
|
export function either3(input: string | number | boolean): number
|
||||||
|
interface Obj {
|
||||||
|
v: string | number
|
||||||
|
}
|
||||||
|
export function either4(input: string | number | boolean | Obj): number
|
||||||
export enum Kind { Dog = 0, Cat = 1, Duck = 2 }
|
export enum Kind { Dog = 0, Cat = 1, Duck = 2 }
|
||||||
export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }
|
export enum CustomNumEnum { One = 1, Two = 2, Three = 3, Four = 4, Six = 6, Eight = 8, Nine = 9, Ten = 10 }
|
||||||
export function enumToI32(e: CustomNumEnum): number
|
export function enumToI32(e: CustomNumEnum): number
|
||||||
|
|
57
examples/napi/src/either.rs
Normal file
57
examples/napi/src/either.rs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
use napi::bindgen_prelude::*;
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
fn either_string_or_number(input: Either<String, u32>) -> u32 {
|
||||||
|
match input {
|
||||||
|
Either::A(s) => s.len() as u32,
|
||||||
|
Either::B(n) => n,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
fn return_either(input: u32) -> Either<String, u32> {
|
||||||
|
if input > 10 {
|
||||||
|
Either::A(format!("{}", input))
|
||||||
|
} else {
|
||||||
|
Either::B(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
fn either3(input: Either3<String, u32, bool>) -> u32 {
|
||||||
|
match input {
|
||||||
|
Either3::A(s) => s.len() as u32,
|
||||||
|
Either3::B(n) => n,
|
||||||
|
Either3::C(b) => {
|
||||||
|
if b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi(object)]
|
||||||
|
struct Obj {
|
||||||
|
pub v: Either<String, u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[napi]
|
||||||
|
fn either4(input: Either4<String, u32, bool, Obj>) -> u32 {
|
||||||
|
match input {
|
||||||
|
Either4::A(s) => s.len() as u32,
|
||||||
|
Either4::B(n) => n,
|
||||||
|
Either4::C(b) => {
|
||||||
|
if b {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Either4::D(f) => match f.v {
|
||||||
|
Either::A(s) => s.len() as u32,
|
||||||
|
Either::B(n) => n,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ mod array;
|
||||||
mod r#async;
|
mod r#async;
|
||||||
mod callback;
|
mod callback;
|
||||||
mod class;
|
mod class;
|
||||||
|
mod either;
|
||||||
mod r#enum;
|
mod r#enum;
|
||||||
mod error;
|
mod error;
|
||||||
mod nullable;
|
mod nullable;
|
||||||
|
|
Loading…
Reference in a new issue