| 1 | use super::{FromNapiValue, ToNapiValue, TypeName, ValidateNapiValue}; |
| 2 | use crate::{ |
| 3 | bindgen_runtime::{Null, Undefined, Unknown}, |
| 4 | check_status, sys, Env, Error, JsUndefined, NapiRaw, NapiValue, Status, ValueType, |
| 5 | }; |
| 6 | |
| 7 | impl<A: NapiRaw, B: NapiRaw> Either<A, B> { |
| 8 | /// # Safety |
| 9 | /// Backward compatible with `Either` in **v1** |
| 10 | pub unsafe fn raw(&self) -> sys::napi_value { |
| 11 | match &self { |
| 12 | Self::A(a: &A) => unsafe { a.raw() }, |
| 13 | Self::B(b: &B) => unsafe { b.raw() }, |
| 14 | } |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | // Backwards compatibility with v1 |
| 19 | impl<T> From<Either<T, JsUndefined>> for Option<T> { |
| 20 | fn from(value: Either<T, JsUndefined>) -> Option<T> { |
| 21 | match value { |
| 22 | Either::A(v: T) => Some(v), |
| 23 | Either::B(_) => None, |
| 24 | } |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | impl<T> From<Option<T>> for Either<T, Undefined> { |
| 29 | fn from(value: Option<T>) -> Self { |
| 30 | match value { |
| 31 | Some(v: T) => Either::A(v), |
| 32 | None => Either::B(()), |
| 33 | } |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | impl<T> From<Either<T, Null>> for Option<T> { |
| 38 | fn from(value: Either<T, Null>) -> Option<T> { |
| 39 | match value { |
| 40 | Either::A(v: T) => Some(v), |
| 41 | Either::B(_) => None, |
| 42 | } |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | macro_rules! either_n { |
| 47 | ( $either_name:ident, $( $parameter:ident ),+ $( , )* ) => { |
| 48 | #[derive(Debug, Clone, Copy)] |
| 49 | pub enum $either_name< $( $parameter ),+ > { |
| 50 | $( $parameter ( $parameter ) ),+ |
| 51 | } |
| 52 | |
| 53 | impl< $( $parameter ),+ > TypeName for $either_name < $( $parameter ),+ > |
| 54 | where $( $parameter: TypeName ),+ |
| 55 | { |
| 56 | fn type_name() -> &'static str { |
| 57 | stringify!( $either_name ) |
| 58 | } |
| 59 | |
| 60 | fn value_type() -> ValueType { |
| 61 | ValueType::Unknown |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | impl< $( $parameter ),+ > FromNapiValue for $either_name < $( $parameter ),+ > |
| 66 | where $( $parameter: TypeName + FromNapiValue + ValidateNapiValue ),+ |
| 67 | { |
| 68 | unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> crate::Result<Self> { |
| 69 | let mut ret = Err(Error::new(Status::InvalidArg, "Invalid value" .to_owned())); |
| 70 | $( |
| 71 | if unsafe { |
| 72 | match $parameter::validate(env, napi_val) { |
| 73 | Ok(maybe_rejected_promise) => { |
| 74 | if maybe_rejected_promise.is_null() { |
| 75 | true |
| 76 | } else { |
| 77 | silence_rejected_promise(env, maybe_rejected_promise)?; |
| 78 | false |
| 79 | } |
| 80 | }, |
| 81 | Err(_) => false |
| 82 | } |
| 83 | } && unsafe { { ret = $parameter ::from_napi_value(env, napi_val).map(Self:: $parameter ); ret.is_ok() } } { |
| 84 | ret |
| 85 | } else |
| 86 | )+ |
| 87 | { |
| 88 | Err(crate::Error::new( |
| 89 | Status::InvalidArg, |
| 90 | format!( |
| 91 | concat!("Value is non of these types " , $( "`{" , stringify!( $parameter ), "}`, " ),+ ), |
| 92 | $( $parameter = $parameter::type_name(), )+ |
| 93 | ), |
| 94 | )) |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | impl< $( $parameter ),+ > ToNapiValue for $either_name < $( $parameter ),+ > |
| 100 | where $( $parameter: ToNapiValue ),+ |
| 101 | { |
| 102 | unsafe fn to_napi_value( |
| 103 | env: sys::napi_env, |
| 104 | value: Self |
| 105 | ) -> crate::Result<crate::sys::napi_value> { |
| 106 | match value { |
| 107 | $( Self:: $parameter (v) => unsafe { $parameter ::to_napi_value(env, v) } ),+ |
| 108 | } |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | impl< $( $parameter ),+ > ValidateNapiValue for $either_name < $( $parameter ),+ > |
| 113 | where $( $parameter: ValidateNapiValue ),+ |
| 114 | { |
| 115 | unsafe fn validate( |
| 116 | env: sys::napi_env, |
| 117 | napi_val: sys::napi_value, |
| 118 | ) -> crate::Result<sys::napi_value> { |
| 119 | let mut ret: crate::Result<sys::napi_value>; |
| 120 | $( |
| 121 | if unsafe { |
| 122 | ret = $parameter::validate(env, napi_val); |
| 123 | ret.is_ok() |
| 124 | } { |
| 125 | ret |
| 126 | } else |
| 127 | )+ |
| 128 | { |
| 129 | ret |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | impl<Data, $( $parameter: AsRef<Data> ),+ > AsRef<Data> for $either_name < $( $parameter ),+ > |
| 135 | where Data: ?Sized, |
| 136 | { |
| 137 | fn as_ref(&self) -> &Data { |
| 138 | match &self { |
| 139 | $( Self:: $parameter (v) => v.as_ref() ),+ |
| 140 | } |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | impl< $( $parameter ),+ > $either_name < $( $parameter ),+ > |
| 145 | where $( $parameter: NapiRaw ),+ |
| 146 | { |
| 147 | pub fn as_unknown(&self, env: Env) -> Unknown { |
| 148 | match &self { |
| 149 | $( Self:: $parameter (v) => unsafe { Unknown::from_raw_unchecked(env.raw(), v.raw()) } ),+ |
| 150 | } |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | #[cfg(feature = "serde-json" )] |
| 155 | impl< $( $parameter: serde::Serialize ),+ > serde::Serialize for $either_name< $( $parameter ),+ > { |
| 156 | fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> |
| 157 | where |
| 158 | Ser: serde::Serializer |
| 159 | { |
| 160 | match &self { |
| 161 | $( Self:: $parameter (v) => serializer.serialize_some(v) ),+ |
| 162 | } |
| 163 | } |
| 164 | } |
| 165 | }; |
| 166 | } |
| 167 | |
| 168 | either_n!(Either, A, B); |
| 169 | either_n!(Either3, A, B, C); |
| 170 | either_n!(Either4, A, B, C, D); |
| 171 | either_n!(Either5, A, B, C, D, E); |
| 172 | either_n!(Either6, A, B, C, D, E, F); |
| 173 | either_n!(Either7, A, B, C, D, E, F, G); |
| 174 | either_n!(Either8, A, B, C, D, E, F, G, H); |
| 175 | either_n!(Either9, A, B, C, D, E, F, G, H, I); |
| 176 | either_n!(Either10, A, B, C, D, E, F, G, H, I, J); |
| 177 | either_n!(Either11, A, B, C, D, E, F, G, H, I, J, K); |
| 178 | either_n!(Either12, A, B, C, D, E, F, G, H, I, J, K, L); |
| 179 | either_n!(Either13, A, B, C, D, E, F, G, H, I, J, K, L, M); |
| 180 | either_n!(Either14, A, B, C, D, E, F, G, H, I, J, K, L, M, N); |
| 181 | either_n!(Either15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); |
| 182 | either_n!(Either16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); |
| 183 | either_n!(Either17, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q); |
| 184 | either_n!(Either18, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R); |
| 185 | either_n!(Either19, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S); |
| 186 | either_n!(Either20, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T); |
| 187 | either_n!(Either21, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U); |
| 188 | either_n!(Either22, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V); |
| 189 | either_n!(Either23, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W); |
| 190 | either_n!(Either24, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X); |
| 191 | either_n!(Either25, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y); |
| 192 | either_n!(Either26, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z); |
| 193 | |
| 194 | fn silence_rejected_promise(env: sys::napi_env, promise: sys::napi_value) -> crate::Result<()> { |
| 195 | let mut catch_method = std::ptr::null_mut(); |
| 196 | check_status!(unsafe { |
| 197 | sys::napi_get_named_property(env, promise, "catch \0" .as_ptr().cast(), &mut catch_method) |
| 198 | })?; |
| 199 | let mut catch_noop_callback = std::ptr::null_mut(); |
| 200 | check_status!(unsafe { |
| 201 | sys::napi_create_function( |
| 202 | env, |
| 203 | "catch \0" .as_ptr().cast(), |
| 204 | 5, |
| 205 | Some(noop), |
| 206 | std::ptr::null_mut(), |
| 207 | &mut catch_noop_callback, |
| 208 | ) |
| 209 | })?; |
| 210 | check_status!(unsafe { |
| 211 | sys::napi_call_function( |
| 212 | env, |
| 213 | promise, |
| 214 | catch_method, |
| 215 | 1, |
| 216 | vec![catch_noop_callback].as_ptr().cast(), |
| 217 | std::ptr::null_mut(), |
| 218 | ) |
| 219 | })?; |
| 220 | Ok(()) |
| 221 | } |
| 222 | |
| 223 | unsafe extern "C" fn noop(_env: sys::napi_env, _info: sys::napi_callback_info) -> sys::napi_value { |
| 224 | std::ptr::null_mut() |
| 225 | } |
| 226 | |