napi-rs/crates/napi/src/bindgen_runtime/js_values/either.rs

333 lines
8.5 KiB
Rust
Raw Normal View History

2021-11-02 01:34:19 +09:00
use super::{FromNapiValue, ToNapiValue, TypeName};
use crate::{
bindgen_runtime::{Null, Undefined},
sys, type_of, JsUndefined, NapiRaw, Status, ValueType,
};
2021-11-02 01:34:19 +09:00
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> {
2021-11-02 01:34:19 +09:00
A(A),
B(B),
}
impl<A: NapiRaw, B: NapiRaw> Either<A, B> {
2021-11-23 15:49:24 +09:00
/// # Safety
/// Backward compatible with `Either` in **v1**
pub unsafe fn raw(&self) -> sys::napi_value {
match &self {
2022-01-13 12:15:02 +09:00
Self::A(a) => unsafe { a.raw() },
Self::B(b) => unsafe { b.raw() },
}
}
}
impl<A: TypeName, B: TypeName> TypeName for Either<A, B> {
2021-11-02 01:34:19 +09:00
fn type_name() -> &'static str {
"Either"
}
fn value_type() -> ValueType {
ValueType::Unknown
}
}
// Backwards compatibility with v1
impl<T> From<Either<T, JsUndefined>> for Option<T> {
fn from(value: Either<T, JsUndefined>) -> Option<T> {
match value {
Either::A(v) => Some(v),
Either::B(_) => None,
}
}
}
impl<T> From<Option<T>> for Either<T, Undefined> {
fn from(value: Option<T>) -> Self {
match value {
Some(v) => Either::A(v),
None => Either::B(()),
}
}
}
impl<T> From<Either<T, Null>> for Option<T> {
fn from(value: Either<T, Null>) -> Option<T> {
match value {
Either::A(v) => Some(v),
Either::B(_) => None,
}
}
}
impl<A: TypeName + FromNapiValue, B: TypeName + FromNapiValue> FromNapiValue for Either<A, B> {
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
2021-11-02 01:34:19 +09:00
debug_assert!(A::value_type() != B::value_type(), "{}", ERROR_MSG);
let js_type = type_of!(env, napi_val)?;
if js_type == A::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
2021-11-02 01:34:19 +09:00
} else if js_type == B::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
2021-11-02 01:34:19 +09:00
} else {
Err(crate::Error::new(
Status::InvalidArg,
format!(
"Expect type {} or {}, but got {}",
A::value_type(),
B::value_type(),
js_type
),
))
}
}
}
impl<A: ToNapiValue, B: ToNapiValue> ToNapiValue for Either<A, B> {
2021-11-02 01:34:19 +09:00
unsafe fn to_napi_value(
env: sys::napi_env,
2021-11-02 01:34:19 +09:00
value: Self,
) -> crate::Result<crate::sys::napi_value> {
match value {
2022-01-13 12:15:02 +09:00
Self::A(a) => unsafe { A::to_napi_value(env, a) },
Self::B(b) => unsafe { B::to_napi_value(env, b) },
2021-11-02 01:34:19 +09:00
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Either3<A, B, C> {
2021-11-02 01:34:19 +09:00
A(A),
B(B),
C(C),
}
impl<A: TypeName, B: TypeName, C: TypeName> TypeName for Either3<A, B, C> {
2021-11-02 01:34:19 +09:00
fn type_name() -> &'static str {
"Either3"
}
fn value_type() -> ValueType {
ValueType::Unknown
}
}
impl<A: TypeName + FromNapiValue, B: TypeName + FromNapiValue, C: TypeName + FromNapiValue>
FromNapiValue for Either3<A, B, C>
2021-11-02 01:34:19 +09:00
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
2021-11-02 01:34:19 +09:00
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() {
2022-01-13 12:15:02 +09:00
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
2021-11-02 01:34:19 +09:00
} else if js_type == B::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
2021-11-02 01:34:19 +09:00
} else if js_type == C::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { C::from_napi_value(env, napi_val).map(Self::C) }
2021-11-02 01:34:19 +09:00
} 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: ToNapiValue, B: ToNapiValue, C: ToNapiValue> ToNapiValue for Either3<A, B, C> {
2021-11-02 01:34:19 +09:00
unsafe fn to_napi_value(
env: sys::napi_env,
2021-11-02 01:34:19 +09:00
value: Self,
) -> crate::Result<crate::sys::napi_value> {
match value {
2022-01-13 12:15:02 +09:00
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) },
2021-11-02 01:34:19 +09:00
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Either4<A, B, C, D> {
2021-11-02 01:34:19 +09:00
A(A),
B(B),
C(C),
D(D),
}
impl<A: TypeName, B: TypeName, C: TypeName, D: TypeName> TypeName for Either4<A, B, C, D> {
2021-11-02 01:34:19 +09:00
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,
2021-11-02 01:34:19 +09:00
> FromNapiValue for Either4<A, B, C, D>
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> {
2021-11-02 01:34:19 +09:00
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() {
2022-01-13 12:15:02 +09:00
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
2021-11-02 01:34:19 +09:00
} else if js_type == B::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
2021-11-02 01:34:19 +09:00
} else if js_type == C::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { C::from_napi_value(env, napi_val).map(Self::C) }
2021-11-02 01:34:19 +09:00
} else if js_type == D::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { D::from_napi_value(env, napi_val).map(Self::D) }
2021-11-02 01:34:19 +09:00
} 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>
2021-11-02 01:34:19 +09:00
{
unsafe fn to_napi_value(
env: sys::napi_env,
2021-11-02 01:34:19 +09:00
value: Self,
) -> crate::Result<crate::sys::napi_value> {
match value {
2022-01-13 12:15:02 +09:00
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) },
2021-11-02 01:34:19 +09:00
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum Either5<A, B, C, D, E> {
2021-11-02 01:34:19 +09:00
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>
2021-11-02 01:34:19 +09:00
{
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,
2021-11-02 01:34:19 +09:00
> 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> {
2021-11-02 01:34:19 +09:00
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() {
2022-01-13 12:15:02 +09:00
unsafe { A::from_napi_value(env, napi_val).map(Self::A) }
2021-11-02 01:34:19 +09:00
} else if js_type == B::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { B::from_napi_value(env, napi_val).map(Self::B) }
2021-11-02 01:34:19 +09:00
} else if js_type == C::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { C::from_napi_value(env, napi_val).map(Self::C) }
2021-11-02 01:34:19 +09:00
} else if js_type == D::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { D::from_napi_value(env, napi_val).map(Self::D) }
2021-11-02 01:34:19 +09:00
} else if js_type == E::value_type() {
2022-01-13 12:15:02 +09:00
unsafe { E::from_napi_value(env, napi_val).map(Self::E) }
2021-11-02 01:34:19 +09:00
} 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>
2021-11-02 01:34:19 +09:00
{
unsafe fn to_napi_value(
env: sys::napi_env,
2021-11-02 01:34:19 +09:00
value: Self,
) -> crate::Result<crate::sys::napi_value> {
match value {
2022-01-13 12:15:02 +09:00
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) },
2021-11-02 01:34:19 +09:00
}
}
}