diff --git a/crates/napi/src/bindgen_runtime/js_values/either.rs b/crates/napi/src/bindgen_runtime/js_values/either.rs index a8bfe3f8..aab142b6 100644 --- a/crates/napi/src/bindgen_runtime/js_values/either.rs +++ b/crates/napi/src/bindgen_runtime/js_values/either.rs @@ -1,22 +1,18 @@ use super::{FromNapiValue, ToNapiValue, TypeName}; -use crate::{sys, type_of, JsNull, JsUndefined, NapiRaw, Status, ValueType}; +use crate::{ + bindgen_runtime::{Null, Undefined}, + sys, type_of, JsUndefined, NapiRaw, Status, ValueType, +}; const ERROR_MSG: &str = "The return value of typeof(T) should not be equal in Either"; #[derive(Debug, Clone, Copy)] -pub enum Either< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, -> { +pub enum Either { A(A), B(B), } -impl< - A: TypeName + FromNapiValue + ToNapiValue + NapiRaw, - B: TypeName + FromNapiValue + ToNapiValue + NapiRaw, - > Either -{ +impl Either { /// # Safety /// Backward compatible with `Either` in **v1** pub unsafe fn raw(&self) -> sys::napi_value { @@ -27,9 +23,7 @@ impl< } } -impl TypeName - for Either -{ +impl TypeName for Either { fn type_name() -> &'static str { "Either" } @@ -40,7 +34,7 @@ impl From> for Option { +impl From> for Option { fn from(value: Either) -> Option { match value { Either::A(v) => Some(v), @@ -49,8 +43,17 @@ impl From> for } } -impl From> for Option { - fn from(value: Either) -> Option { +impl From> for Either { + fn from(value: Option) -> Self { + match value { + Some(v) => Either::A(v), + None => Either::B(()), + } + } +} + +impl From> for Option { + fn from(value: Either) -> Option { match value { Either::A(v) => Some(v), Either::B(_) => None, @@ -58,9 +61,7 @@ impl From> for Opti } } -impl - FromNapiValue for Either -{ +impl FromNapiValue for Either { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { debug_assert!(A::value_type() != B::value_type(), "{}", ERROR_MSG); let js_type = type_of!(env, napi_val)?; @@ -82,9 +83,7 @@ impl - ToNapiValue for Either -{ +impl ToNapiValue for Either { unsafe fn to_napi_value( env: sys::napi_env, value: Self, @@ -97,22 +96,13 @@ impl { +pub enum Either3 { A(A), B(B), C(C), } -impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - > TypeName for Either3 -{ +impl TypeName for Either3 { fn type_name() -> &'static str { "Either3" } @@ -122,11 +112,8 @@ impl< } } -impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - > FromNapiValue for Either3 +impl + FromNapiValue for Either3 { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { debug_assert!( @@ -160,12 +147,7 @@ impl< } } -impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - > ToNapiValue for Either3 -{ +impl ToNapiValue for Either3 { unsafe fn to_napi_value( env: sys::napi_env, value: Self, @@ -179,25 +161,14 @@ impl< } #[derive(Debug, Clone, Copy)] -pub enum Either4< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - D: TypeName + FromNapiValue + ToNapiValue, -> { +pub enum Either4 { 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 -{ +impl TypeName for Either4 { fn type_name() -> &'static str { "Either4" } @@ -208,10 +179,10 @@ impl< } impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - D: TypeName + FromNapiValue + ToNapiValue, + A: TypeName + FromNapiValue, + B: TypeName + FromNapiValue, + C: TypeName + FromNapiValue, + D: TypeName + FromNapiValue, > FromNapiValue for Either4 { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { @@ -254,12 +225,8 @@ impl< } } -impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - D: TypeName + FromNapiValue + ToNapiValue, - > ToNapiValue for Either4 +impl ToNapiValue + for Either4 { unsafe fn to_napi_value( env: sys::napi_env, @@ -275,13 +242,7 @@ impl< } #[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, -> { +pub enum Either5 { A(A), B(B), C(C), @@ -289,13 +250,8 @@ pub enum Either5< 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 +impl TypeName + for Either5 { fn type_name() -> &'static str { "Either5" @@ -307,11 +263,11 @@ impl< } impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - D: TypeName + FromNapiValue + ToNapiValue, - E: TypeName + FromNapiValue + ToNapiValue, + A: TypeName + FromNapiValue, + B: TypeName + FromNapiValue, + C: TypeName + FromNapiValue, + D: TypeName + FromNapiValue, + E: TypeName + FromNapiValue, > FromNapiValue for Either5 { unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result { @@ -358,13 +314,8 @@ impl< } } -impl< - A: TypeName + FromNapiValue + ToNapiValue, - B: TypeName + FromNapiValue + ToNapiValue, - C: TypeName + FromNapiValue + ToNapiValue, - D: TypeName + FromNapiValue + ToNapiValue, - E: TypeName + FromNapiValue + ToNapiValue, - > ToNapiValue for Either5 +impl ToNapiValue + for Either5 { unsafe fn to_napi_value( env: sys::napi_env, diff --git a/examples/napi/__test__/typegen.spec.ts.md b/examples/napi/__test__/typegen.spec.ts.md index 700fd349..d22d65b1 100644 --- a/examples/napi/__test__/typegen.spec.ts.md +++ b/examples/napi/__test__/typegen.spec.ts.md @@ -57,6 +57,8 @@ Generated by [AVA](https://avajs.dev). export function either4(input: string | number | boolean | Obj): number␊ export function receiveClassOrNumber(either: number | JsClassForEither): number␊ export function receiveMutClassOrNumber(either: number | JsClassForEither): number␊ + export function returnEitherClass(input: number): number | JsClassForEither␊ + export function eitherFromOption(): JsClassForEither | undefined␊ /** default enum values are continuos i32s start from 0 */␊ export const enum Kind {␊ /** Barks */␊ diff --git a/examples/napi/__test__/typegen.spec.ts.snap b/examples/napi/__test__/typegen.spec.ts.snap index d3ff3d42..6c9e2049 100644 Binary files a/examples/napi/__test__/typegen.spec.ts.snap and b/examples/napi/__test__/typegen.spec.ts.snap differ diff --git a/examples/napi/__test__/values.spec.ts b/examples/napi/__test__/values.spec.ts index e421c980..f1ad6054 100644 --- a/examples/napi/__test__/values.spec.ts +++ b/examples/napi/__test__/values.spec.ts @@ -93,6 +93,8 @@ import { CssStyleSheet, asyncReduceBuffer, callbackReturnPromise, + returnEitherClass, + eitherFromOption, } from '../' test('export const', (t) => { @@ -467,6 +469,15 @@ test('receive class reference in either', (t) => { t.is(receiveMutClassOrNumber(c), 100) }) +test('return either class', (t) => { + t.is(returnEitherClass(1), 1) + t.true(returnEitherClass(-1) instanceof JsClassForEither) +}) + +test('either from option', (t) => { + t.true(eitherFromOption() instanceof JsClassForEither) +}) + test('either3', (t) => { t.is(either3(2), 2) t.is(either3('hello'), 'hello'.length) diff --git a/examples/napi/index.d.ts b/examples/napi/index.d.ts index b50df571..d3adb048 100644 --- a/examples/napi/index.d.ts +++ b/examples/napi/index.d.ts @@ -47,6 +47,8 @@ export interface Obj { export function either4(input: string | number | boolean | Obj): number export function receiveClassOrNumber(either: number | JsClassForEither): number export function receiveMutClassOrNumber(either: number | JsClassForEither): number +export function returnEitherClass(input: number): number | JsClassForEither +export function eitherFromOption(): JsClassForEither | undefined /** default enum values are continuos i32s start from 0 */ export const enum Kind { /** Barks */ diff --git a/examples/napi/src/either.rs b/examples/napi/src/either.rs index 175de708..0f5fa8cd 100644 --- a/examples/napi/src/either.rs +++ b/examples/napi/src/either.rs @@ -82,3 +82,17 @@ fn receive_mut_class_or_number(either: Either) -> u3 Either::B(_) => 100, } } + +#[napi] +fn return_either_class(input: i32) -> Either { + if input > 0 { + Either::A(input as u32) + } else { + Either::B(JsClassForEither {}) + } +} + +#[napi] +fn either_from_option() -> Either { + Some(JsClassForEither {}).into() +}