1use std::ptr;
2
3use crate::napi::bindgen_prelude::*;
4use crate::napi::check_status;
5use crate::napi::JsObject;
6use crate::napi::Value;
7
8pub struct Array {
9 env: libnode_sys::napi_env,
10 inner: libnode_sys::napi_value,
11 len: u32,
12}
13
14impl Array {
15 pub(crate) fn new(
16 env: libnode_sys::napi_env,
17 len: u32,
18 ) -> Result<Self> {
19 let mut ptr = ptr::null_mut();
20 unsafe {
21 check_status!(
22 libnode_sys::napi_create_array_with_length(env, len as usize, &mut ptr),
23 "Failed to create napi Array"
24 )?;
25 }
26
27 Ok(Array {
28 env,
29 inner: ptr,
30 len,
31 })
32 }
33
34 pub fn get<T: FromNapiValue>(
35 &self,
36 index: u32,
37 ) -> Result<Option<T>> {
38 if index >= self.len() {
39 return Ok(None);
40 }
41
42 let mut ret = ptr::null_mut();
43 unsafe {
44 check_status!(
45 libnode_sys::napi_get_element(self.env, self.inner, index, &mut ret),
46 "Failed to get element with index `{}`",
47 index,
48 )?;
49
50 Ok(Some(T::from_napi_value(self.env, ret)?))
51 }
52 }
53
54 pub fn set<T: ToNapiValue>(
55 &mut self,
56 index: u32,
57 val: T,
58 ) -> Result<()> {
59 unsafe {
60 let napi_val = T::to_napi_value(self.env, val)?;
61
62 check_status!(
63 libnode_sys::napi_set_element(self.env, self.inner, index, napi_val),
64 "Failed to set element with index `{}`",
65 index,
66 )?;
67
68 if index >= self.len() {
69 self.len = index + 1;
70 }
71
72 Ok(())
73 }
74 }
75
76 pub fn insert<T: ToNapiValue>(
77 &mut self,
78 val: T,
79 ) -> Result<()> {
80 self.set(self.len(), val)?;
81 Ok(())
82 }
83
84 #[allow(clippy::len_without_is_empty)]
85 pub fn len(&self) -> u32 {
86 self.len
87 }
88
89 pub fn coerce_to_object(self) -> Result<JsObject> {
90 let mut new_raw_value = ptr::null_mut();
91 check_status!(unsafe {
92 libnode_sys::napi_coerce_to_object(self.env, self.inner, &mut new_raw_value)
93 })?;
94 Ok(JsObject(Value {
95 env: self.env,
96 value: new_raw_value,
97 value_type: ValueType::Object,
98 }))
99 }
100}
101
102impl TypeName for Array {
103 fn type_name() -> &'static str {
104 "Array"
105 }
106
107 fn value_type() -> ValueType {
108 ValueType::Object
109 }
110}
111
112impl ToNapiValue for Array {
113 unsafe fn to_napi_value(
114 _env: libnode_sys::napi_env,
115 val: Self,
116 ) -> Result<libnode_sys::napi_value> {
117 Ok(val.inner)
118 }
119}
120
121impl FromNapiValue for Array {
122 unsafe fn from_napi_value(
123 env: libnode_sys::napi_env,
124 napi_val: libnode_sys::napi_value,
125 ) -> Result<Self> {
126 let mut is_arr = false;
127 check_status!(
128 unsafe { libnode_sys::napi_is_array(env, napi_val, &mut is_arr) },
129 "Failed to check given napi value is array"
130 )?;
131
132 if is_arr {
133 let mut len = 0;
134
135 check_status!(
136 unsafe { libnode_sys::napi_get_array_length(env, napi_val, &mut len) },
137 "Failed to get Array length",
138 )?;
139
140 Ok(Array {
141 inner: napi_val,
142 env,
143 len,
144 })
145 } else {
146 Err(Error::new(
147 Status::InvalidArg,
148 "Given napi value is not an array".to_owned(),
149 ))
150 }
151 }
152}
153
154impl Array {
155 pub fn from_vec<T>(
157 env: &Env,
158 value: Vec<T>,
159 ) -> Result<Self>
160 where
161 T: ToNapiValue,
162 {
163 let mut arr = Array::new(env.0, value.len() as u32)?;
164 value.into_iter().enumerate().try_for_each(|(index, val)| {
165 arr.set(index as u32, val)?;
166 Ok::<(), Error>(())
167 })?;
168 Ok(arr)
169 }
170
171 pub fn from_ref_vec_string(
173 env: &Env,
174 value: &[String],
175 ) -> Result<Self> {
176 let mut arr = Array::new(env.0, value.len() as u32)?;
177 value.iter().enumerate().try_for_each(|(index, val)| {
178 arr.set(index as u32, val.as_str())?;
179 Ok::<(), Error>(())
180 })?;
181 Ok(arr)
182 }
183
184 pub fn from_ref_vec<T>(
186 env: &Env,
187 value: &[T],
188 ) -> Result<Self>
189 where
190 T: ToNapiValue + Copy,
191 {
192 let mut arr = Array::new(env.0, value.len() as u32)?;
193 value.iter().enumerate().try_for_each(|(index, val)| {
194 arr.set(index as u32, *val)?;
195 Ok::<(), Error>(())
196 })?;
197 Ok(arr)
198 }
199}
200
201impl ValidateNapiValue for Array {}
202
203impl<T> TypeName for Vec<T> {
204 fn type_name() -> &'static str {
205 "Array<T>"
206 }
207
208 fn value_type() -> ValueType {
209 ValueType::Object
210 }
211}
212
213impl<T, const N: usize> ToNapiValue for [T; N]
214where
215 T: ToNapiValue + Copy,
216{
217 unsafe fn to_napi_value(
218 env: libnode_sys::napi_env,
219 val: Self,
220 ) -> Result<libnode_sys::napi_value> {
221 let mut arr = Array::new(env, val.len() as u32)?;
222
223 for (i, v) in val.into_iter().enumerate() {
224 arr.set(i as u32, v)?;
225 }
226
227 unsafe { Array::to_napi_value(env, arr) }
228 }
229}
230
231impl<T> ToNapiValue for &[T]
232where
233 T: ToNapiValue + Copy,
234{
235 unsafe fn to_napi_value(
236 env: libnode_sys::napi_env,
237 val: Self,
238 ) -> Result<libnode_sys::napi_value> {
239 let mut arr = Array::new(env, val.len() as u32)?;
240
241 for (i, v) in val.iter().enumerate() {
242 arr.set(i as u32, *v)?;
243 }
244
245 unsafe { Array::to_napi_value(env, arr) }
246 }
247}
248
249impl<T> ToNapiValue for Vec<T>
250where
251 T: ToNapiValue,
252{
253 unsafe fn to_napi_value(
254 env: libnode_sys::napi_env,
255 val: Self,
256 ) -> Result<libnode_sys::napi_value> {
257 let mut arr = Array::new(env, val.len() as u32)?;
258
259 for (i, v) in val.into_iter().enumerate() {
260 arr.set(i as u32, v)?;
261 }
262
263 unsafe { Array::to_napi_value(env, arr) }
264 }
265}
266
267macro_rules! impl_for_primitive_type {
268 ($primitive_type:ident) => {
269 impl ToNapiValue for &Vec<$primitive_type> {
270 unsafe fn to_napi_value(
271 env: libnode_sys::napi_env,
272 val: Self,
273 ) -> Result<libnode_sys::napi_value> {
274 let mut arr = Array::new(env, val.len() as u32)?;
275
276 for (i, v) in val.iter().enumerate() {
277 arr.set(i as u32, *v)?;
278 }
279
280 unsafe { Array::to_napi_value(env, arr) }
281 }
282 }
283 };
284}
285
286impl_for_primitive_type!(u8);
287impl_for_primitive_type!(i8);
288impl_for_primitive_type!(u16);
289impl_for_primitive_type!(i16);
290impl_for_primitive_type!(u32);
291impl_for_primitive_type!(i32);
292impl_for_primitive_type!(i64);
293impl_for_primitive_type!(f64);
294impl_for_primitive_type!(bool);
295
296impl ToNapiValue for &Vec<String> {
297 unsafe fn to_napi_value(
298 env: libnode_sys::napi_env,
299 val: Self,
300 ) -> Result<libnode_sys::napi_value> {
301 let mut arr = Array::new(env, val.len() as u32)?;
302
303 for (i, v) in val.iter().enumerate() {
304 arr.set(i as u32, v.as_str())?;
305 }
306
307 unsafe { Array::to_napi_value(env, arr) }
308 }
309}
310
311impl<T> FromNapiValue for Vec<T>
312where
313 T: FromNapiValue,
314{
315 unsafe fn from_napi_value(
316 env: libnode_sys::napi_env,
317 napi_val: libnode_sys::napi_value,
318 ) -> Result<Self> {
319 let arr = unsafe { Array::from_napi_value(env, napi_val)? };
320 let mut vec = vec![];
321
322 for i in 0..arr.len() {
323 if let Some(val) = arr.get::<T>(i)? {
324 vec.push(val);
325 } else {
326 return Err(Error::new(
327 Status::InvalidArg,
328 "Found inconsistent data type in Array<T> when converting to Rust Vec<T>".to_owned(),
329 ));
330 }
331 }
332
333 Ok(vec)
334 }
335}
336
337impl<T> ValidateNapiValue for Vec<T>
338where
339 T: FromNapiValue,
340{
341 unsafe fn validate(
342 env: libnode_sys::napi_env,
343 napi_val: libnode_sys::napi_value,
344 ) -> Result<libnode_sys::napi_value> {
345 let mut is_array = false;
346 check_status!(
347 unsafe { libnode_sys::napi_is_array(env, napi_val, &mut is_array) },
348 "Failed to check given napi value is array"
349 )?;
350 if !is_array {
351 return Err(Error::new(
352 Status::InvalidArg,
353 "Expected an array".to_owned(),
354 ));
355 }
356 Ok(ptr::null_mut())
357 }
358}
359
360macro_rules! arr_get {
361 ($arr:expr, $n:expr) => {
362 if let Some(e) = $arr.get($n)? {
363 e
364 } else {
365 return Err(Error::new(
366 Status::InvalidArg,
367 format!(
368 "Found inconsistent data type in Array[{}] when converting to Rust T",
369 $n
370 )
371 .to_owned(),
372 ));
373 }
374 };
375}
376
377macro_rules! tuple_from_napi_value {
378 ($total:expr, $($n:expr),+) => {
379 unsafe fn from_napi_value(env: libnode_sys::napi_env, napi_val: libnode_sys::napi_value) -> Result<Self> {
380 let arr = unsafe { Array::from_napi_value(env, napi_val)? };
381 if arr.len() < $total {
382 return Err(Error::new(
383 Status::InvalidArg,
384 format!("Array length < {}",$total).to_owned(),
385 ));
386 }
387 Ok(($(arr_get!(arr,$n)),+))
388 }
389 }
390}
391
392macro_rules! impl_tuple_validate_napi_value {
393 ($($ident:ident),+) => {
394 impl<$($ident: FromNapiValue),*> ValidateNapiValue for ($($ident,)*) {}
395 impl<$($ident: FromNapiValue),*> TypeName for ($($ident,)*) {
396 fn type_name() -> &'static str {
397 concat!("Tuple", "(", $(stringify!($ident), ","),*, ")")
398 }
399 fn value_type() -> ValueType {
400 ValueType::Object
401 }
402 }
403 };
404}
405
406impl<T0, T1> FromNapiValue for (T0, T1)
407where
408 T0: FromNapiValue,
409 T1: FromNapiValue,
410{
411 tuple_from_napi_value!(2, 0, 1);
412}
413
414impl<T0, T1, T2> FromNapiValue for (T0, T1, T2)
415where
416 T0: FromNapiValue,
417 T1: FromNapiValue,
418 T2: FromNapiValue,
419{
420 tuple_from_napi_value!(3, 0, 1, 2);
421}
422
423impl<T0, T1, T2, T3> FromNapiValue for (T0, T1, T2, T3)
424where
425 T0: FromNapiValue,
426 T1: FromNapiValue,
427 T2: FromNapiValue,
428 T3: FromNapiValue,
429{
430 tuple_from_napi_value!(4, 0, 1, 2, 3);
431}
432
433impl<T0, T1, T2, T3, T4> FromNapiValue for (T0, T1, T2, T3, T4)
434where
435 T0: FromNapiValue,
436 T1: FromNapiValue,
437 T2: FromNapiValue,
438 T3: FromNapiValue,
439 T4: FromNapiValue,
440{
441 tuple_from_napi_value!(5, 0, 1, 2, 3, 4);
442}
443
444impl<T0, T1, T2, T3, T4, T5> FromNapiValue for (T0, T1, T2, T3, T4, T5)
445where
446 T0: FromNapiValue,
447 T1: FromNapiValue,
448 T2: FromNapiValue,
449 T3: FromNapiValue,
450 T4: FromNapiValue,
451 T5: FromNapiValue,
452{
453 tuple_from_napi_value!(6, 0, 1, 2, 3, 4, 5);
454}
455
456impl<T0, T1, T2, T3, T4, T5, T6> FromNapiValue for (T0, T1, T2, T3, T4, T5, T6)
457where
458 T0: FromNapiValue,
459 T1: FromNapiValue,
460 T2: FromNapiValue,
461 T3: FromNapiValue,
462 T4: FromNapiValue,
463 T5: FromNapiValue,
464 T6: FromNapiValue,
465{
466 tuple_from_napi_value!(7, 0, 1, 2, 3, 4, 5, 6);
467}
468
469impl<T0, T1, T2, T3, T4, T5, T6, T7> FromNapiValue for (T0, T1, T2, T3, T4, T5, T6, T7)
470where
471 T0: FromNapiValue,
472 T1: FromNapiValue,
473 T2: FromNapiValue,
474 T3: FromNapiValue,
475 T4: FromNapiValue,
476 T5: FromNapiValue,
477 T6: FromNapiValue,
478 T7: FromNapiValue,
479{
480 tuple_from_napi_value!(8, 0, 1, 2, 3, 4, 5, 6, 7);
481}
482
483impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> FromNapiValue for (T0, T1, T2, T3, T4, T5, T6, T7, T8)
484where
485 T0: FromNapiValue,
486 T1: FromNapiValue,
487 T2: FromNapiValue,
488 T3: FromNapiValue,
489 T4: FromNapiValue,
490 T5: FromNapiValue,
491 T6: FromNapiValue,
492 T7: FromNapiValue,
493 T8: FromNapiValue,
494{
495 tuple_from_napi_value!(9, 0, 1, 2, 3, 4, 5, 6, 7, 8);
496}
497
498impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> FromNapiValue
499 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)
500where
501 T0: FromNapiValue,
502 T1: FromNapiValue,
503 T2: FromNapiValue,
504 T3: FromNapiValue,
505 T4: FromNapiValue,
506 T5: FromNapiValue,
507 T6: FromNapiValue,
508 T7: FromNapiValue,
509 T8: FromNapiValue,
510 T9: FromNapiValue,
511{
512 tuple_from_napi_value!(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
513}
514
515impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> FromNapiValue
516 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)
517where
518 T0: FromNapiValue,
519 T1: FromNapiValue,
520 T2: FromNapiValue,
521 T3: FromNapiValue,
522 T4: FromNapiValue,
523 T5: FromNapiValue,
524 T6: FromNapiValue,
525 T7: FromNapiValue,
526 T8: FromNapiValue,
527 T9: FromNapiValue,
528 T10: FromNapiValue,
529{
530 tuple_from_napi_value!(11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
531}
532
533impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> FromNapiValue
534 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)
535where
536 T0: FromNapiValue,
537 T1: FromNapiValue,
538 T2: FromNapiValue,
539 T3: FromNapiValue,
540 T4: FromNapiValue,
541 T5: FromNapiValue,
542 T6: FromNapiValue,
543 T7: FromNapiValue,
544 T8: FromNapiValue,
545 T9: FromNapiValue,
546 T10: FromNapiValue,
547 T11: FromNapiValue,
548{
549 tuple_from_napi_value!(12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
550}
551
552impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> FromNapiValue
553 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)
554where
555 T0: FromNapiValue,
556 T1: FromNapiValue,
557 T2: FromNapiValue,
558 T3: FromNapiValue,
559 T4: FromNapiValue,
560 T5: FromNapiValue,
561 T6: FromNapiValue,
562 T7: FromNapiValue,
563 T8: FromNapiValue,
564 T9: FromNapiValue,
565 T10: FromNapiValue,
566 T11: FromNapiValue,
567 T12: FromNapiValue,
568{
569 tuple_from_napi_value!(13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
570}
571
572impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> FromNapiValue
573 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)
574where
575 T0: FromNapiValue,
576 T1: FromNapiValue,
577 T2: FromNapiValue,
578 T3: FromNapiValue,
579 T4: FromNapiValue,
580 T5: FromNapiValue,
581 T6: FromNapiValue,
582 T7: FromNapiValue,
583 T8: FromNapiValue,
584 T9: FromNapiValue,
585 T10: FromNapiValue,
586 T11: FromNapiValue,
587 T12: FromNapiValue,
588 T13: FromNapiValue,
589{
590 tuple_from_napi_value!(14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
591}
592
593impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> FromNapiValue
594 for (
595 T0,
596 T1,
597 T2,
598 T3,
599 T4,
600 T5,
601 T6,
602 T7,
603 T8,
604 T9,
605 T10,
606 T11,
607 T12,
608 T13,
609 T14,
610 )
611where
612 T0: FromNapiValue,
613 T1: FromNapiValue,
614 T2: FromNapiValue,
615 T3: FromNapiValue,
616 T4: FromNapiValue,
617 T5: FromNapiValue,
618 T6: FromNapiValue,
619 T7: FromNapiValue,
620 T8: FromNapiValue,
621 T9: FromNapiValue,
622 T10: FromNapiValue,
623 T11: FromNapiValue,
624 T12: FromNapiValue,
625 T13: FromNapiValue,
626 T14: FromNapiValue,
627{
628 tuple_from_napi_value!(15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
629}
630
631impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> FromNapiValue
632 for (
633 T0,
634 T1,
635 T2,
636 T3,
637 T4,
638 T5,
639 T6,
640 T7,
641 T8,
642 T9,
643 T10,
644 T11,
645 T12,
646 T13,
647 T14,
648 T15,
649 )
650where
651 T0: FromNapiValue,
652 T1: FromNapiValue,
653 T2: FromNapiValue,
654 T3: FromNapiValue,
655 T4: FromNapiValue,
656 T5: FromNapiValue,
657 T6: FromNapiValue,
658 T7: FromNapiValue,
659 T8: FromNapiValue,
660 T9: FromNapiValue,
661 T10: FromNapiValue,
662 T11: FromNapiValue,
663 T12: FromNapiValue,
664 T13: FromNapiValue,
665 T14: FromNapiValue,
666 T15: FromNapiValue,
667{
668 tuple_from_napi_value!(16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
669}
670
671impl_tuple_validate_napi_value!(T0, T1);
672impl_tuple_validate_napi_value!(T0, T1, T2);
673impl_tuple_validate_napi_value!(T0, T1, T2, T3);
674impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4);
675impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5);
676impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6);
677impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7);
678impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
679impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
680impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
681impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
682impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
683impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
684impl_tuple_validate_napi_value!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
685impl_tuple_validate_napi_value!(
686 T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
687);