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>;
74
75 fn into_unknown(self, env: &Env) -> Result<Unknown<'_>> {
76 let napi_val = unsafe { Self::to_napi_value(env.0, self)? };
77 Ok(Unknown(
78 Value {
79 env: env.0,
80 value: napi_val,
81 value_type: ValueType::Unknown,
82 },
83 std::marker::PhantomData,
84 ))
85 }
86}
87
88impl ToNapiValue for sys::napi_value {
89 unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
90 Ok(val)
91 }
92}
93
94impl<'env, T: JsValue<'env>> ToNapiValue for T {
95 unsafe fn to_napi_value(_env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
96 Ok(val.raw())
97 }
98}
99
100pub trait FromNapiValue: Sized {
101 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self>;
110
111 fn from_unknown(value: Unknown) -> Result<Self> {
112 unsafe { Self::from_napi_value(value.0.env, value.0.value) }
113 }
114}
115
116pub trait FromNapiRef {
117 unsafe fn from_napi_ref(env: sys::napi_env, napi_val: sys::napi_value) -> Result<&'static Self>;
126}
127
128pub trait FromNapiMutRef {
129 unsafe fn from_napi_mut_ref(
138 env: sys::napi_env,
139 napi_val: sys::napi_value,
140 ) -> Result<&'static mut Self>;
141}
142
143impl<T: FromNapiRef + 'static> FromNapiValue for &T {
144 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
145 unsafe { T::from_napi_ref(env, napi_val) }
146 }
147}
148
149impl<T: FromNapiMutRef + 'static> FromNapiValue for &mut T {
150 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
151 unsafe { T::from_napi_mut_ref(env, napi_val) }
152 }
153}
154
155pub trait ValidateNapiValue: TypeName {
156 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
168 let value_type = Self::value_type();
169
170 let mut result = -1;
171 check_status!(
172 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
173 "Failed to detect napi value type",
174 )?;
175
176 let received_type = ValueType::from(result);
177 if value_type == received_type {
178 Ok(ptr::null_mut())
179 } else {
180 Err(Error::new(
181 Status::InvalidArg,
182 format!("Expect value to be {value_type}, but received {received_type}"),
183 ))
184 }
185 }
186}
187
188impl<T: TypeName> TypeName for Option<T> {
189 fn type_name() -> &'static str {
190 T::type_name()
191 }
192
193 fn value_type() -> ValueType {
194 T::value_type()
195 }
196}
197
198impl<T: ValidateNapiValue> ValidateNapiValue for Option<T> {
199 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
200 let mut result = -1;
201 check_status!(
202 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
203 "Failed to detect napi value type",
204 )?;
205
206 let received_type = ValueType::from(result);
207 if received_type == ValueType::Null || received_type == ValueType::Undefined {
208 Ok(ptr::null_mut())
209 } else if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
210 Ok(validate_ret)
211 } else {
212 Err(Error::new(
213 Status::InvalidArg,
214 format!(
215 "Expect value to be Option<{}>, but received {}",
216 T::value_type(),
217 received_type
218 ),
219 ))
220 }
221 }
222}
223
224impl<T> FromNapiValue for Option<T>
225where
226 T: FromNapiValue,
227{
228 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
229 let mut val_type = 0;
230
231 check_status!(
232 unsafe { sys::napi_typeof(env, napi_val, &mut val_type) },
233 "Failed to convert napi value into rust type `Option<T>`",
234 )?;
235
236 match val_type {
237 sys::ValueType::napi_undefined | sys::ValueType::napi_null => Ok(None),
238 _ => Ok(Some(unsafe { T::from_napi_value(env, napi_val)? })),
239 }
240 }
241}
242
243impl<T> ToNapiValue for Option<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 Some(val) => unsafe { T::to_napi_value(env, val) },
250 None => {
251 let mut ptr = ptr::null_mut();
252 check_status!(
253 unsafe { sys::napi_get_null(env, &mut ptr) },
254 "Failed to convert rust type `Option<T>` into napi value",
255 )?;
256 Ok(ptr)
257 }
258 }
259 }
260}
261
262impl<T> ToNapiValue for Result<T>
263where
264 T: ToNapiValue,
265{
266 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
267 match val {
268 Ok(v) => unsafe { T::to_napi_value(env, v) },
269 Err(e) => {
270 let error_code = unsafe { String::to_napi_value(env, format!("{:?}", e.status))? };
271 let reason = unsafe { String::to_napi_value(env, e.reason.clone())? };
272 let mut error = ptr::null_mut();
273 check_status!(
274 unsafe { sys::napi_create_error(env, error_code, reason, &mut error) },
275 "Failed to create napi error"
276 )?;
277
278 Ok(error)
279 }
280 }
281 }
282}
283
284impl<T: TypeName> TypeName for Rc<T> {
285 fn type_name() -> &'static str {
286 T::type_name()
287 }
288
289 fn value_type() -> ValueType {
290 T::value_type()
291 }
292}
293
294impl<T: ValidateNapiValue> ValidateNapiValue for Rc<T> {
295 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
296 let mut result = -1;
297 check_status!(
298 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
299 "Failed to detect napi value type",
300 )?;
301
302 let received_type = ValueType::from(result);
303 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
304 Ok(validate_ret)
305 } else {
306 Err(Error::new(
307 Status::InvalidArg,
308 format!(
309 "Expect value to be Rc<{}>, but received {}",
310 T::value_type(),
311 received_type
312 ),
313 ))
314 }
315 }
316}
317
318impl<T> FromNapiValue for Rc<T>
319where
320 T: FromNapiValue,
321{
322 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
323 Ok(Rc::new(unsafe { T::from_napi_value(env, napi_val)? }))
324 }
325}
326
327impl<T> ToNapiValue for Rc<T>
328where
329 T: ToNapiValue + Clone,
330{
331 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
332 unsafe { T::to_napi_value(env, (*val).clone()) }
333 }
334}
335
336impl<T> ToNapiValue for &Rc<T>
337where
338 T: ToNapiValue + Clone,
339{
340 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
341 unsafe { T::to_napi_value(env, (**val).clone()) }
342 }
343}
344
345impl<T> ToNapiValue for &mut Rc<T>
346where
347 T: ToNapiValue + Clone,
348{
349 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
350 unsafe { T::to_napi_value(env, (**val).clone()) }
351 }
352}
353
354impl<T: TypeName> TypeName for Arc<T> {
355 fn type_name() -> &'static str {
356 T::type_name()
357 }
358
359 fn value_type() -> ValueType {
360 T::value_type()
361 }
362}
363
364impl<T: ValidateNapiValue> ValidateNapiValue for Arc<T> {
365 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
366 let mut result = -1;
367 check_status!(
368 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
369 "Failed to detect napi value type",
370 )?;
371
372 let received_type = ValueType::from(result);
373 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
374 Ok(validate_ret)
375 } else {
376 Err(Error::new(
377 Status::InvalidArg,
378 format!(
379 "Expect value to be Arc<{}>, but received {}",
380 T::value_type(),
381 received_type
382 ),
383 ))
384 }
385 }
386}
387
388impl<T> FromNapiValue for Arc<T>
389where
390 T: FromNapiValue,
391{
392 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
393 Ok(Arc::new(unsafe { T::from_napi_value(env, napi_val)? }))
394 }
395}
396
397impl<T> ToNapiValue for Arc<T>
398where
399 T: ToNapiValue + Clone,
400{
401 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
402 unsafe { T::to_napi_value(env, (*val).clone()) }
403 }
404}
405
406impl<T> ToNapiValue for &Arc<T>
407where
408 T: ToNapiValue + Clone,
409{
410 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
411 unsafe { T::to_napi_value(env, (**val).clone()) }
412 }
413}
414
415impl<T> ToNapiValue for &mut Arc<T>
416where
417 T: ToNapiValue + Clone,
418{
419 unsafe fn to_napi_value(env: sys::napi_env, val: Self) -> Result<sys::napi_value> {
420 unsafe { T::to_napi_value(env, (**val).clone()) }
421 }
422}
423
424impl<T: TypeName> TypeName for Mutex<T> {
425 fn type_name() -> &'static str {
426 T::type_name()
427 }
428
429 fn value_type() -> ValueType {
430 T::value_type()
431 }
432}
433
434impl<T: ValidateNapiValue> ValidateNapiValue for Mutex<T> {
435 unsafe fn validate(env: sys::napi_env, napi_val: sys::napi_value) -> Result<sys::napi_value> {
436 let mut result = -1;
437 check_status!(
438 unsafe { sys::napi_typeof(env, napi_val, &mut result) },
439 "Failed to detect napi value type",
440 )?;
441
442 let received_type = ValueType::from(result);
443 if let Ok(validate_ret) = unsafe { T::validate(env, napi_val) } {
444 Ok(validate_ret)
445 } else {
446 Err(Error::new(
447 Status::InvalidArg,
448 format!(
449 "Expect value to be Mutex<{}>, but received {}",
450 T::value_type(),
451 received_type
452 ),
453 ))
454 }
455 }
456}
457
458impl<T> FromNapiValue for Mutex<T>
459where
460 T: FromNapiValue,
461{
462 unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
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}