From a5c19ce1da4c16e986dab3e267b43ee1f1fe03d6 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Thu, 12 May 2022 15:11:47 +0800 Subject: [PATCH] fix(napi): type constraint for either types --- .../src/bindgen_runtime/js_values/either.rs | 137 ++++++------------ examples/napi/__test__/typegen.spec.ts.md | 2 + examples/napi/__test__/typegen.spec.ts.snap | Bin 3114 -> 3133 bytes examples/napi/__test__/values.spec.ts | 11 ++ examples/napi/index.d.ts | 2 + examples/napi/src/either.rs | 14 ++ 6 files changed, 73 insertions(+), 93 deletions(-) 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 d3ff3d429dcc50e953f473a1a31edb899f7eea8e..6c9e20490804c8b59a9254b3eb1e1f186595e69d 100644 GIT binary patch literal 3133 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 XPSR}CcPk&KZtnaa`g#Gbe=7h0vGEDf literal 3114 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 { @@ -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() +}