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