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 | } |
155 | |
156 | either_n!(Either, A, B); |
157 | either_n!(Either3, A, B, C); |
158 | either_n!(Either4, A, B, C, D); |
159 | either_n!(Either5, A, B, C, D, E); |
160 | either_n!(Either6, A, B, C, D, E, F); |
161 | either_n!(Either7, A, B, C, D, E, F, G); |
162 | either_n!(Either8, A, B, C, D, E, F, G, H); |
163 | either_n!(Either9, A, B, C, D, E, F, G, H, I); |
164 | either_n!(Either10, A, B, C, D, E, F, G, H, I, J); |
165 | either_n!(Either11, A, B, C, D, E, F, G, H, I, J, K); |
166 | either_n!(Either12, A, B, C, D, E, F, G, H, I, J, K, L); |
167 | either_n!(Either13, A, B, C, D, E, F, G, H, I, J, K, L, M); |
168 | either_n!(Either14, A, B, C, D, E, F, G, H, I, J, K, L, M, N); |
169 | either_n!(Either15, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); |
170 | either_n!(Either16, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); |
171 | either_n!(Either17, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q); |
172 | either_n!(Either18, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R); |
173 | either_n!(Either19, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S); |
174 | either_n!(Either20, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T); |
175 | either_n!(Either21, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U); |
176 | 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); |
177 | 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); |
178 | 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); |
179 | 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); |
180 | 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); |
181 | |
182 | fn silence_rejected_promise(env: sys::napi_env, promise: sys::napi_value) -> crate::Result<()> { |
183 | let mut catch_method = std::ptr::null_mut(); |
184 | check_status!(unsafe { |
185 | sys::napi_get_named_property(env, promise, "catch \0" .as_ptr().cast(), &mut catch_method) |
186 | })?; |
187 | let mut catch_noop_callback = std::ptr::null_mut(); |
188 | check_status!(unsafe { |
189 | sys::napi_create_function( |
190 | env, |
191 | "catch \0" .as_ptr().cast(), |
192 | 5, |
193 | Some(noop), |
194 | std::ptr::null_mut(), |
195 | &mut catch_noop_callback, |
196 | ) |
197 | })?; |
198 | check_status!(unsafe { |
199 | sys::napi_call_function( |
200 | env, |
201 | promise, |
202 | catch_method, |
203 | 1, |
204 | vec![catch_noop_callback].as_ptr().cast(), |
205 | std::ptr::null_mut(), |
206 | ) |
207 | })?; |
208 | Ok(()) |
209 | } |
210 | |
211 | unsafe extern "C" fn noop(_env: sys::napi_env, _info: sys::napi_callback_info) -> sys::napi_value { |
212 | std::ptr::null_mut() |
213 | } |
214 | |