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;
25mod os_string;
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::*;
53pub use promise::*;
54pub use promise_raw::*;
55pub use scope::*;
56#[cfg(feature = "web_stream")]
57pub use stream::*;
58pub use string::*;
59pub use symbol::*;
60pub use task::*;
61pub use value_ref::*;
62
63pub trait TypeName {
64 fn type_name() -> &'static str;
65
66 fn value_type() -> ValueType;
67}
68
69pub trait ToNapiValue: Sized {
70 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>;
111
112 fn from_unknown(value: Unknown) -> Result<Self> {
113 unsafe { Self::from_napi_value(value.0.env, value.0.value) }
114 }
115}
116
117pub trait FromNapiRef {
118 unsafe fn from_napi_ref(env: sys::napi_env, napi_val: sys::napi_value) -> Result<&'static Self>;
127}
128
129pub trait FromNapiMutRef {
130 unsafe fn from_napi_mut_ref(
139 env: sys::napi_env,
140 napi_val: sys::napi_value,
141 ) -> Result<&'static mut Self>;
142}
143
144impl<T: FromNapiRef + 'static> FromNapiValue for &T {
145 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
146 unsafe { T::from_napi_ref(env, napi_val) }
147 }
148}
149
150impl<T: FromNapiMutRef + 'static> FromNapiValue for &mut T {
151 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
152 unsafe { T::from_napi_mut_ref(env, napi_val) }
153 }
154}
155
156pub trait ValidateNapiValue: TypeName {
157 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
169 let value_type = Self::value_type();
170
171 let mut result = -1;
172 check_status!(
173 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
174 "Failed to detect napi value type",
175 )?;
176
177 let received_type = ValueType::from(result);
178 if value_type == received_type {
179 Ok(ptr::null_mut())
180 } else {
181 Err(Error::new(
182 Status::InvalidArg,
183 format!("Expect value to be {value_type}, but received {received_type}"),
184 ))
185 }
186 }
187}
188
189impl<T: TypeName> TypeName for Option<T> {
190 fn type_name() -> &'static str {
191 T::type_name()
192 }
193
194 fn value_type() -> ValueType {
195 T::value_type()
196 }
197}
198
199impl<T: ValidateNapiValue> ValidateNapiValue for Option<T> {
200 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
201 let mut result = -1;
202 check_status!(
203 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
204 "Failed to detect napi value type",
205 )?;
206
207 let received_type = ValueType::from(result);
208 if received_type == ValueType::Null || received_type == ValueType::Undefined {
209 Ok(ptr::null_mut())
210 } else if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
211 Ok(validate_ret)
212 } else {
213 Err(Error::new(
214 Status::InvalidArg,
215 format!(
216 "Expect value to be Option<{}>, but received {}",
217 T::value_type(),
218 received_type
219 ),
220 ))
221 }
222 }
223}
224
225impl<T> FromNapiValue for Option<T>
226where
227 T: FromNapiValue,
228{
229 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
230 let mut val_type = 0;
231
232 check_status!(
233 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
234 "Failed to convert napi value into rust type `Option<T>`",
235 )?;
236
237 match val_type {
238 sys::ValueType::napi_undefined | sys::ValueType::napi_null => Ok(None),
239 _ => Ok(Some(unsafe { T::from_napi_value(env, napi_val)? })),
240 }
241 }
242}
243
244impl<T> ToNapiValue for Option<T>
245where
246 T: ToNapiValue,
247{
248 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
249 match val {
250 Some(val) => unsafe { T::to_napi_value(env, val) },
251 None => {
252 let mut ptr = ptr::null_mut();
253 check_status!(
254 unsafe { sys::napi_get_null(env, &mut ptr) },
255 "Failed to convert rust type `Option<T>` into napi value",
256 )?;
257 Ok(ptr)
258 }
259 }
260 }
261}
262
263impl<T> ToNapiValue for Result<T>
264where
265 T: ToNapiValue,
266{
267 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
268 match val {
269 Ok(v) => unsafe { T::to_napi_value(env, v) },
270 Err(e) => {
271 let error_code = unsafe { String::to_napi_value(env, format!("{:?}", e.status))? };
272 let reason = unsafe { String::to_napi_value(env, e.reason.clone())? };
273 let mut error = ptr::null_mut();
274 check_status!(
275 unsafe { sys::napi_create_error(env, error_code, reason, &mut error) },
276 "Failed to create napi error"
277 )?;
278
279 Ok(error)
280 }
281 }
282 }
283}
284
285impl<T: TypeName> TypeName for Rc<T> {
286 fn type_name() -> &'static str {
287 T::type_name()
288 }
289
290 fn value_type() -> ValueType {
291 T::value_type()
292 }
293}
294
295impl<T: ValidateNapiValue> ValidateNapiValue for Rc<T> {
296 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
297 let mut result = -1;
298 check_status!(
299 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
300 "Failed to detect napi value type",
301 )?;
302
303 let received_type = ValueType::from(result);
304 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
305 Ok(validate_ret)
306 } else {
307 Err(Error::new(
308 Status::InvalidArg,
309 format!(
310 "Expect value to be Rc<{}>, but received {}",
311 T::value_type(),
312 received_type
313 ),
314 ))
315 }
316 }
317}
318
319impl<T> FromNapiValue for Rc<T>
320where
321 T: FromNapiValue,
322{
323 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
324 Ok(Rc::new(unsafe { T::from_napi_value(env, napi_val)? }))
325 }
326}
327
328impl<T> ToNapiValue for Rc<T>
329where
330 T: ToNapiValue + Clone,
331{
332 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
333 unsafe { T::to_napi_value(env, (*val).clone()) }
334 }
335}
336
337impl<T> ToNapiValue for &Rc<T>
338where
339 T: ToNapiValue + Clone,
340{
341 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
342 unsafe { T::to_napi_value(env, (**val).clone()) }
343 }
344}
345
346impl<T> ToNapiValue for &mut Rc<T>
347where
348 T: ToNapiValue + Clone,
349{
350 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
351 unsafe { T::to_napi_value(env, (**val).clone()) }
352 }
353}
354
355impl<T: TypeName> TypeName for Arc<T> {
356 fn type_name() -> &'static str {
357 T::type_name()
358 }
359
360 fn value_type() -> ValueType {
361 T::value_type()
362 }
363}
364
365impl<T: ValidateNapiValue> ValidateNapiValue for Arc<T> {
366 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
367 let mut result = -1;
368 check_status!(
369 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
370 "Failed to detect napi value type",
371 )?;
372
373 let received_type = ValueType::from(result);
374 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
375 Ok(validate_ret)
376 } else {
377 Err(Error::new(
378 Status::InvalidArg,
379 format!(
380 "Expect value to be Arc<{}>, but received {}",
381 T::value_type(),
382 received_type
383 ),
384 ))
385 }
386 }
387}
388
389impl<T> FromNapiValue for Arc<T>
390where
391 T: FromNapiValue,
392{
393 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
394 Ok(Arc::new(unsafe { T::from_napi_value(env, napi_val)? }))
395 }
396}
397
398impl<T> ToNapiValue for Arc<T>
399where
400 T: ToNapiValue + Clone,
401{
402 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
403 unsafe { T::to_napi_value(env, (*val).clone()) }
404 }
405}
406
407impl<T> ToNapiValue for &Arc<T>
408where
409 T: ToNapiValue + Clone,
410{
411 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
412 unsafe { T::to_napi_value(env, (**val).clone()) }
413 }
414}
415
416impl<T> ToNapiValue for &mut Arc<T>
417where
418 T: ToNapiValue + Clone,
419{
420 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
421 unsafe { T::to_napi_value(env, (**val).clone()) }
422 }
423}
424
425impl<T: TypeName> TypeName for Mutex<T> {
426 fn type_name() -> &'static str {
427 T::type_name()
428 }
429
430 fn value_type() -> ValueType {
431 T::value_type()
432 }
433}
434
435impl<T: ValidateNapiValue> ValidateNapiValue for Mutex<T> {
436 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
437 let mut result = -1;
438 check_status!(
439 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
440 "Failed to detect napi value type",
441 )?;
442
443 let received_type = ValueType::from(result);
444 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
445 Ok(validate_ret)
446 } else {
447 Err(Error::new(
448 Status::InvalidArg,
449 format!(
450 "Expect value to be Mutex<{}>, but received {}",
451 T::value_type(),
452 received_type
453 ),
454 ))
455 }
456 }
457}
458
459impl<T> FromNapiValue for Mutex<T>
460where
461 T: FromNapiValue,
462{
463 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
464 Ok(Mutex::new(unsafe { T::from_napi_value(env, napi_val)? }))
465 }
466}
467
468impl<T> ToNapiValue for Mutex<T>
469where
470 T: ToNapiValue + Clone,
471{
472 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
473 unsafe {
474 match val.lock() {
475 Ok(inner) => T::to_napi_value(env, inner.clone()),
476 Err(_) => Err(Error::new(
477 Status::GenericFailure,
478 "Failed to acquire a lock",
479 )),
480 }
481 }
482 }
483}
484
485impl<T> ToNapiValue for &Mutex<T>
486where
487 T: ToNapiValue + Clone,
488{
489 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
490 unsafe {
491 match val.lock() {
492 Ok(inner) => T::to_napi_value(env, inner.clone()),
493 Err(_) => Err(Error::new(
494 Status::GenericFailure,
495 "Failed to acquire a lock",
496 )),
497 }
498 }
499 }
500}
501
502impl<T> ToNapiValue for &mut Mutex<T>
503where
504 T: ToNapiValue + Clone,
505{
506 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
507 ToNapiValue::to_napi_value(env, &*val)
508 }
509}