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
129impl<T: FromNapiRef + 'static> FromNapiValue for &T {
130 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
131 unsafe { T::from_napi_ref(env, napi_val) }
132 }
133}
134
135impl<T: FromNapiMutRef + 'static> FromNapiValue for &mut T {
136 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
137 unsafe { T::from_napi_mut_ref(env, napi_val) }
138 }
139}
140
141pub trait ValidateNapiValue: TypeName {
142 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
149 let value_type = Self::value_type();
150
151 let mut result = -1;
152 check_status!(
153 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
154 "Failed to detect napi value type",
155 )?;
156
157 let received_type = ValueType::from(result);
158 if value_type == received_type {
159 Ok(ptr::null_mut())
160 } else {
161 Err(Error::new(
162 Status::InvalidArg,
163 format!("Expect value to be {value_type}, but received {received_type}"),
164 ))
165 }
166 }
167}
168
169impl<T: TypeName> TypeName for Option<T> {
170 fn type_name() -> &'static str {
171 T::type_name()
172 }
173
174 fn value_type() -> ValueType {
175 T::value_type()
176 }
177}
178
179impl<T: ValidateNapiValue> ValidateNapiValue for Option<T> {
180 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
181 let mut result = -1;
182 check_status!(
183 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
184 "Failed to detect napi value type",
185 )?;
186
187 let received_type = ValueType::from(result);
188 if received_type == ValueType::Null || received_type == ValueType::Undefined {
189 Ok(ptr::null_mut())
190 } else if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
191 Ok(validate_ret)
192 } else {
193 Err(Error::new(
194 Status::InvalidArg,
195 format!(
196 "Expect value to be Option<{}>, but received {}",
197 T::value_type(),
198 received_type
199 ),
200 ))
201 }
202 }
203}
204
205impl<T> FromNapiValue for Option<T>
206where
207 T: FromNapiValue,
208{
209 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
210 let mut val_type = 0;
211
212 check_status!(
213 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
214 "Failed to convert napi value into rust type `Option<T>`",
215 )?;
216
217 match val_type {
218 sys::ValueType::napi_undefined | sys::ValueType::napi_null => Ok(None),
219 _ => Ok(Some(unsafe { T::from_napi_value(env, napi_val)? })),
220 }
221 }
222}
223
224impl<T> ToNapiValue for Option<T>
225where
226 T: ToNapiValue,
227{
228 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
229 match val {
230 Some(val) => unsafe { T::to_napi_value(env, val) },
231 None => {
232 let mut ptr = ptr::null_mut();
233 check_status!(
234 unsafe { sys::napi_get_null(env, &mut ptr) },
235 "Failed to convert rust type `Option<T>` into napi value",
236 )?;
237 Ok(ptr)
238 }
239 }
240 }
241}
242
243impl<T> ToNapiValue for Result<T>
244where
245 T: ToNapiValue,
246{
247 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
248 match val {
249 Ok(v) => unsafe { T::to_napi_value(env, v) },
250 Err(e) => {
251 let error_code = unsafe { String::to_napi_value(env, format!("{:?}", e.status))? };
252 let reason = unsafe { String::to_napi_value(env, e.reason.clone())? };
253 let mut error = ptr::null_mut();
254 check_status!(
255 unsafe { sys::napi_create_error(env, error_code, reason, &mut error) },
256 "Failed to create napi error"
257 )?;
258
259 Ok(error)
260 }
261 }
262 }
263}
264
265impl<T: TypeName> TypeName for Rc<T> {
266 fn type_name() -> &'static str {
267 T::type_name()
268 }
269
270 fn value_type() -> ValueType {
271 T::value_type()
272 }
273}
274
275impl<T: ValidateNapiValue> ValidateNapiValue for Rc<T> {
276 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
277 let mut result = -1;
278 check_status!(
279 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
280 "Failed to detect napi value type",
281 )?;
282
283 let received_type = ValueType::from(result);
284 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
285 Ok(validate_ret)
286 } else {
287 Err(Error::new(
288 Status::InvalidArg,
289 format!(
290 "Expect value to be Rc<{}>, but received {}",
291 T::value_type(),
292 received_type
293 ),
294 ))
295 }
296 }
297}
298
299impl<T> FromNapiValue for Rc<T>
300where
301 T: FromNapiValue,
302{
303 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
304 let mut val_type = 0;
305
306 check_status!(
307 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
308 "Failed to convert napi value into rust type `Rc<T>`",
309 )?;
310
311 Ok(Rc::new(unsafe { T::from_napi_value(env, napi_val)? }))
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 &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> ToNapiValue for &mut Rc<T>
334where
335 T: ToNapiValue + Clone,
336{
337 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
338 unsafe { T::to_napi_value(env, (**val).clone()) }
339 }
340}
341
342impl<T: TypeName> TypeName for Arc<T> {
343 fn type_name() -> &'static str {
344 T::type_name()
345 }
346
347 fn value_type() -> ValueType {
348 T::value_type()
349 }
350}
351
352impl<T: ValidateNapiValue> ValidateNapiValue for Arc<T> {
353 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
354 let mut result = -1;
355 check_status!(
356 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
357 "Failed to detect napi value type",
358 )?;
359
360 let received_type = ValueType::from(result);
361 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
362 Ok(validate_ret)
363 } else {
364 Err(Error::new(
365 Status::InvalidArg,
366 format!(
367 "Expect value to be Arc<{}>, but received {}",
368 T::value_type(),
369 received_type
370 ),
371 ))
372 }
373 }
374}
375
376impl<T> FromNapiValue for Arc<T>
377where
378 T: FromNapiValue,
379{
380 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
381 let mut val_type = 0;
382
383 check_status!(
384 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
385 "Failed to convert napi value into rust type `Arc<T>`",
386 )?;
387
388 Ok(Arc::new(unsafe { T::from_napi_value(env, napi_val)? }))
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 &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> ToNapiValue for &mut Arc<T>
411where
412 T: ToNapiValue + Clone,
413{
414 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
415 unsafe { T::to_napi_value(env, (**val).clone()) }
416 }
417}
418
419impl<T: TypeName> TypeName for Mutex<T> {
420 fn type_name() -> &'static str {
421 T::type_name()
422 }
423
424 fn value_type() -> ValueType {
425 T::value_type()
426 }
427}
428
429impl<T: ValidateNapiValue> ValidateNapiValue for Mutex<T> {
430 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
431 let mut result = -1;
432 check_status!(
433 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
434 "Failed to detect napi value type",
435 )?;
436
437 let received_type = ValueType::from(result);
438 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
439 Ok(validate_ret)
440 } else {
441 Err(Error::new(
442 Status::InvalidArg,
443 format!(
444 "Expect value to be Mutex<{}>, but received {}",
445 T::value_type(),
446 received_type
447 ),
448 ))
449 }
450 }
451}
452
453impl<T> FromNapiValue for Mutex<T>
454where
455 T: FromNapiValue,
456{
457 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
458 let mut val_type = 0;
459
460 check_status!(
461 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
462 "Failed to convert napi value into rust type `Mutex<T>`",
463 )?;
464
465 Ok(Mutex::new(unsafe { T::from_napi_value(env, napi_val)? }))
466 }
467}
468
469impl<T> ToNapiValue for Mutex<T>
470where
471 T: ToNapiValue + Clone,
472{
473 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
474 unsafe {
475 match val.lock() {
476 Ok(inner) => T::to_napi_value(env, inner.clone()),
477 Err(_) => Err(Error::new(
478 Status::GenericFailure,
479 "Failed to acquire a lock",
480 )),
481 }
482 }
483 }
484}
485
486impl<T> ToNapiValue for &Mutex<T>
487where
488 T: ToNapiValue + Clone,
489{
490 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
491 unsafe {
492 match val.lock() {
493 Ok(inner) => T::to_napi_value(env, inner.clone()),
494 Err(_) => Err(Error::new(
495 Status::GenericFailure,
496 "Failed to acquire a lock",
497 )),
498 }
499 }
500 }
501}
502
503impl<T> ToNapiValue for &mut Mutex<T>
504where
505 T: ToNapiValue + Clone,
506{
507 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
508 ToNapiValue::to_napi_value(env, &*val)
509 }
510}