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