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