1use std::{
2 ptr,
3 rc::Rc,
4 sync::{Arc, Mutex},
5};
6
7use crate::{check_status, sys, Env, Error, JsValue, Result, Status, Value, ValueType};
8
9mod array;
10mod arraybuffer;
11#[cfg(feature = "napi6")]
12mod bigint;
13mod boolean;
14mod buffer;
15mod class;
16#[cfg(all(feature = "chrono_date", feature = "napi5"))]
17mod date;
18mod either;
19mod external;
20mod function;
21mod map;
22mod nil;
23mod number;
24mod object;
25#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
26mod promise;
27mod promise_raw;
28mod scope;
29#[cfg(feature = "serde-json")]
30mod serde;
31mod set;
32#[cfg(feature = "web_stream")]
33mod stream;
34mod string;
35mod symbol;
36mod task;
37mod value_ref;
38
39pub use crate::js_values::Unknown;
40#[cfg(feature = "napi5")]
41pub use crate::JsDate as Date;
42pub use array::*;
43pub use arraybuffer::*;
44#[cfg(feature = "napi6")]
45pub use bigint::*;
46pub use buffer::*;
47pub use class::*;
48pub use either::*;
49pub use external::*;
50pub use function::*;
51pub use nil::*;
52pub use object::*;
53#[cfg(all(feature = "tokio_rt", feature = "napi4"))]
54pub use promise::*;
55pub use promise_raw::*;
56pub use scope::*;
57#[cfg(feature = "web_stream")]
58pub use stream::*;
59pub use string::*;
60pub use symbol::*;
61pub use task::*;
62pub use value_ref::*;
63
64pub trait TypeName {
65 fn type_name() -> &'static str;
66
67 fn value_type() -> ValueType;
68}
69
70pub trait ToNapiValue: Sized {
71 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value>;
75
76 fn into_unknown(self, env: &Env) -> Result<Unknown> {
77 let napi_val = unsafe { Self::to_napi_value(env.0, self)? };
78 Ok(Unknown(
79 Value {
80 env: env.0,
81 value: napi_val,
82 value_type: ValueType::Unknown,
83 },
84 std::marker::PhantomData,
85 ))
86 }
87}
88
89impl ToNapiValue for sys::napi_value {
90 unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
91 Ok(val)
92 }
93}
94
95impl<'env, T: JsValue<'env>> ToNapiValue for T {
96 unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
97 Ok(val.raw())
98 }
99}
100
101pub trait FromNapiValue: Sized {
102 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self>;
106
107 fn from_unknown(value: Unknown) -> Result<Self> {
108 unsafe { Self::from_napi_value(value.0.env, value.0.value) }
109 }
110}
111
112pub trait FromNapiRef {
113 unsafe fn from_napi_ref(env: sys::napi_env, napi_val: sys::napi_value) -> Result<&'static Self>;
117}
118
119pub trait FromNapiMutRef {
120 unsafe fn from_napi_mut_ref(
124 env: sys::napi_env,
125 napi_val: sys::napi_value,
126 ) -> Result<&'static mut Self>;
127}
128
129pub trait ValidateNapiValue: TypeName {
130 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
137 let value_type = Self::value_type();
138
139 let mut result = -1;
140 check_status!(
141 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
142 "Failed to detect napi value type",
143 )?;
144
145 let received_type = ValueType::from(result);
146 if value_type == received_type {
147 Ok(ptr::null_mut())
148 } else {
149 Err(Error::new(
150 Status::InvalidArg,
151 format!(
152 "Expect value to be {}, but received {}",
153 value_type, received_type
154 ),
155 ))
156 }
157 }
158}
159
160impl<T: TypeName> TypeName for Option<T> {
161 fn type_name() -> &'static str {
162 T::type_name()
163 }
164
165 fn value_type() -> ValueType {
166 T::value_type()
167 }
168}
169
170impl<T: ValidateNapiValue> ValidateNapiValue for Option<T> {
171 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
172 let mut result = -1;
173 check_status!(
174 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
175 "Failed to detect napi value type",
176 )?;
177
178 let received_type = ValueType::from(result);
179 if received_type == ValueType::Null || received_type == ValueType::Undefined {
180 Ok(ptr::null_mut())
181 } else if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
182 Ok(validate_ret)
183 } else {
184 Err(Error::new(
185 Status::InvalidArg,
186 format!(
187 "Expect value to be Option<{}>, but received {}",
188 T::value_type(),
189 received_type
190 ),
191 ))
192 }
193 }
194}
195
196impl<T> FromNapiValue for Option<T>
197where
198 T: FromNapiValue,
199{
200 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
201 let mut val_type = 0;
202
203 check_status!(
204 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
205 "Failed to convert napi value into rust type `Option<T>`",
206 )?;
207
208 match val_type {
209 sys::ValueType::napi_undefined | sys::ValueType::napi_null => Ok(None),
210 _ => Ok(Some(unsafe { T::from_napi_value(env, napi_val)? })),
211 }
212 }
213}
214
215impl<T> ToNapiValue for Option<T>
216where
217 T: ToNapiValue,
218{
219 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
220 match val {
221 Some(val) => unsafe { T::to_napi_value(env, val) },
222 None => {
223 let mut ptr = ptr::null_mut();
224 check_status!(
225 unsafe { sys::napi_get_null(env, &mut ptr) },
226 "Failed to convert rust type `Option<T>` into napi value",
227 )?;
228 Ok(ptr)
229 }
230 }
231 }
232}
233
234impl<T> ToNapiValue for Result<T>
235where
236 T: ToNapiValue,
237{
238 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
239 match val {
240 Ok(v) => unsafe { T::to_napi_value(env, v) },
241 Err(e) => {
242 let error_code = unsafe { String::to_napi_value(env, format!("{:?}", e.status))? };
243 let reason = unsafe { String::to_napi_value(env, e.reason.clone())? };
244 let mut error = ptr::null_mut();
245 check_status!(
246 unsafe { sys::napi_create_error(env, error_code, reason, &mut error) },
247 "Failed to create napi error"
248 )?;
249
250 Ok(error)
251 }
252 }
253 }
254}
255
256impl<T: TypeName> TypeName for Rc<T> {
257 fn type_name() -> &'static str {
258 T::type_name()
259 }
260
261 fn value_type() -> ValueType {
262 T::value_type()
263 }
264}
265
266impl<T: ValidateNapiValue> ValidateNapiValue for Rc<T> {
267 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
268 let mut result = -1;
269 check_status!(
270 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
271 "Failed to detect napi value type",
272 )?;
273
274 let received_type = ValueType::from(result);
275 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
276 Ok(validate_ret)
277 } else {
278 Err(Error::new(
279 Status::InvalidArg,
280 format!(
281 "Expect value to be Rc<{}>, but received {}",
282 T::value_type(),
283 received_type
284 ),
285 ))
286 }
287 }
288}
289
290impl<T> FromNapiValue for Rc<T>
291where
292 T: FromNapiValue,
293{
294 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
295 let mut val_type = 0;
296
297 check_status!(
298 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
299 "Failed to convert napi value into rust type `Rc<T>`",
300 )?;
301
302 Ok(Rc::new(unsafe { T::from_napi_value(env, napi_val)? }))
303 }
304}
305
306impl<T> ToNapiValue for Rc<T>
307where
308 T: ToNapiValue + Clone,
309{
310 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
311 unsafe { T::to_napi_value(env, (*val).clone()) }
312 }
313}
314
315impl<T> ToNapiValue for &Rc<T>
316where
317 T: ToNapiValue + Clone,
318{
319 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
320 unsafe { T::to_napi_value(env, (**val).clone()) }
321 }
322}
323
324impl<T> ToNapiValue for &mut Rc<T>
325where
326 T: ToNapiValue + Clone,
327{
328 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
329 unsafe { T::to_napi_value(env, (**val).clone()) }
330 }
331}
332
333impl<T: TypeName> TypeName for Arc<T> {
334 fn type_name() -> &'static str {
335 T::type_name()
336 }
337
338 fn value_type() -> ValueType {
339 T::value_type()
340 }
341}
342
343impl<T: ValidateNapiValue> ValidateNapiValue for Arc<T> {
344 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
345 let mut result = -1;
346 check_status!(
347 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
348 "Failed to detect napi value type",
349 )?;
350
351 let received_type = ValueType::from(result);
352 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
353 Ok(validate_ret)
354 } else {
355 Err(Error::new(
356 Status::InvalidArg,
357 format!(
358 "Expect value to be Arc<{}>, but received {}",
359 T::value_type(),
360 received_type
361 ),
362 ))
363 }
364 }
365}
366
367impl<T> FromNapiValue for Arc<T>
368where
369 T: FromNapiValue,
370{
371 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
372 let mut val_type = 0;
373
374 check_status!(
375 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
376 "Failed to convert napi value into rust type `Arc<T>`",
377 )?;
378
379 Ok(Arc::new(unsafe { T::from_napi_value(env, napi_val)? }))
380 }
381}
382
383impl<T> ToNapiValue for Arc<T>
384where
385 T: ToNapiValue + Clone,
386{
387 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
388 unsafe { T::to_napi_value(env, (*val).clone()) }
389 }
390}
391
392impl<T> ToNapiValue for &Arc<T>
393where
394 T: ToNapiValue + Clone,
395{
396 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
397 unsafe { T::to_napi_value(env, (**val).clone()) }
398 }
399}
400
401impl<T> ToNapiValue for &mut Arc<T>
402where
403 T: ToNapiValue + Clone,
404{
405 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
406 unsafe { T::to_napi_value(env, (**val).clone()) }
407 }
408}
409
410impl<T: TypeName> TypeName for Mutex<T> {
411 fn type_name() -> &'static str {
412 T::type_name()
413 }
414
415 fn value_type() -> ValueType {
416 T::value_type()
417 }
418}
419
420impl<T: ValidateNapiValue> ValidateNapiValue for Mutex<T> {
421 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
422 let mut result = -1;
423 check_status!(
424 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
425 "Failed to detect napi value type",
426 )?;
427
428 let received_type = ValueType::from(result);
429 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
430 Ok(validate_ret)
431 } else {
432 Err(Error::new(
433 Status::InvalidArg,
434 format!(
435 "Expect value to be Mutex<{}>, but received {}",
436 T::value_type(),
437 received_type
438 ),
439 ))
440 }
441 }
442}
443
444impl<T> FromNapiValue for Mutex<T>
445where
446 T: FromNapiValue,
447{
448 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
449 let mut val_type = 0;
450
451 check_status!(
452 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
453 "Failed to convert napi value into rust type `Mutex<T>`",
454 )?;
455
456 Ok(Mutex::new(unsafe { T::from_napi_value(env, napi_val)? }))
457 }
458}
459
460impl<T> ToNapiValue for Mutex<T>
461where
462 T: ToNapiValue + Clone,
463{
464 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
465 unsafe {
466 match val.lock() {
467 Ok(inner) => T::to_napi_value(env, inner.clone()),
468 Err(_) => Err(Error::new(
469 Status::GenericFailure,
470 "Failed to acquire a lock",
471 )),
472 }
473 }
474 }
475}
476
477impl<T> ToNapiValue for &Mutex<T>
478where
479 T: ToNapiValue + Clone,
480{
481 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
482 unsafe {
483 match val.lock() {
484 Ok(inner) => T::to_napi_value(env, inner.clone()),
485 Err(_) => Err(Error::new(
486 Status::GenericFailure,
487 "Failed to acquire a lock",
488 )),
489 }
490 }
491 }
492}
493
494impl<T> ToNapiValue for &mut Mutex<T>
495where
496 T: ToNapiValue + Clone,
497{
498 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
499 ToNapiValue::to_napi_value(env, &*val)
500 }
501}