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 /// Create `Array` from `Vec<T>`
132 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 /// Create `Array` from `&Vec<String>`
145 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 /// Create `Array` from `&Vec<T: Copy + ToNapiValue>`
155 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 = Array::new(env, val.len() as u32)?;
186
187 for (i: usize, v: T) in val.into_iter().enumerate() {
188 arr.set(index:i as u32, val:v)?;
189 }
190
191 unsafe { Array::to_napi_value(env, val: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 = Array::new(env, val.len() as u32)?;
201
202 for (i: usize, v: &T) in val.iter().enumerate() {
203 arr.set(index:i as u32, *v)?;
204 }
205
206 unsafe { Array::to_napi_value(env, val: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 = Array::new(env, val.len() as u32)?;
216
217 for (i: usize, v: T) in val.into_iter().enumerate() {
218 arr.set(index:i as u32, val:v)?;
219 }
220
221 unsafe { Array::to_napi_value(env, val: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 = Array::new(env, val.len() as u32)?;
254
255 for (i: usize, v: &String) in val.iter().enumerate() {
256 arr.set(index:i as u32, val:v.as_str())?;
257 }
258
259 unsafe { Array::to_napi_value(env, val: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: Array = unsafe { Array::from_napi_value(env, napi_val)? };
269 let mut vec: Vec = vec![];
270
271 for i: u32 in 0..arr.len() {
272 if let Some(val: T) = arr.get::<T>(index:i)? {
273 vec.push(val);
274 } else {
275 return Err(Error::new(
276 Status::InvalidArg,
277 reason:"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: bool = 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 reason:"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
338impl<T0, T1> FromNapiValue for (T0, T1)
339where
340 T0: FromNapiValue,
341 T1: FromNapiValue,
342{
343 tuple_from_napi_value!(2, 0, 1);
344}
345
346impl<T0, T1, T2> FromNapiValue for (T0, T1, T2)
347where
348 T0: FromNapiValue,
349 T1: FromNapiValue,
350 T2: FromNapiValue,
351{
352 tuple_from_napi_value!(3, 0, 1, 2);
353}
354
355impl<T0, T1, T2, T3> FromNapiValue for (T0, T1, T2, T3)
356where
357 T0: FromNapiValue,
358 T1: FromNapiValue,
359 T2: FromNapiValue,
360 T3: FromNapiValue,
361{
362 tuple_from_napi_value!(4, 0, 1, 2, 3);
363}
364
365impl<T0, T1, T2, T3, T4> FromNapiValue for (T0, T1, T2, T3, T4)
366where
367 T0: FromNapiValue,
368 T1: FromNapiValue,
369 T2: FromNapiValue,
370 T3: FromNapiValue,
371 T4: FromNapiValue,
372{
373 tuple_from_napi_value!(5, 0, 1, 2, 3, 4);
374}
375
376impl<T0, T1, T2, T3, T4, T5> FromNapiValue for (T0, T1, T2, T3, T4, T5)
377where
378 T0: FromNapiValue,
379 T1: FromNapiValue,
380 T2: FromNapiValue,
381 T3: FromNapiValue,
382 T4: FromNapiValue,
383 T5: FromNapiValue,
384{
385 tuple_from_napi_value!(6, 0, 1, 2, 3, 4, 5);
386}
387
388impl<T0, T1, T2, T3, T4, T5, T6> FromNapiValue for (T0, T1, T2, T3, T4, T5, T6)
389where
390 T0: FromNapiValue,
391 T1: FromNapiValue,
392 T2: FromNapiValue,
393 T3: FromNapiValue,
394 T4: FromNapiValue,
395 T5: FromNapiValue,
396 T6: FromNapiValue,
397{
398 tuple_from_napi_value!(7, 0, 1, 2, 3, 4, 5, 6);
399}
400
401impl<T0, T1, T2, T3, T4, T5, T6, T7> FromNapiValue for (T0, T1, T2, T3, T4, T5, T6, T7)
402where
403 T0: FromNapiValue,
404 T1: FromNapiValue,
405 T2: FromNapiValue,
406 T3: FromNapiValue,
407 T4: FromNapiValue,
408 T5: FromNapiValue,
409 T6: FromNapiValue,
410 T7: FromNapiValue,
411{
412 tuple_from_napi_value!(8, 0, 1, 2, 3, 4, 5, 6, 7);
413}
414
415impl<T0, T1, T2, T3, T4, T5, T6, T7, T8> FromNapiValue for (T0, T1, T2, T3, T4, T5, T6, T7, T8)
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 T8: FromNapiValue,
426{
427 tuple_from_napi_value!(9, 0, 1, 2, 3, 4, 5, 6, 7, 8);
428}
429
430impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> FromNapiValue
431 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9)
432where
433 T0: FromNapiValue,
434 T1: FromNapiValue,
435 T2: FromNapiValue,
436 T3: FromNapiValue,
437 T4: FromNapiValue,
438 T5: FromNapiValue,
439 T6: FromNapiValue,
440 T7: FromNapiValue,
441 T8: FromNapiValue,
442 T9: FromNapiValue,
443{
444 tuple_from_napi_value!(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
445}
446
447impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> FromNapiValue
448 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)
449where
450 T0: FromNapiValue,
451 T1: FromNapiValue,
452 T2: FromNapiValue,
453 T3: FromNapiValue,
454 T4: FromNapiValue,
455 T5: FromNapiValue,
456 T6: FromNapiValue,
457 T7: FromNapiValue,
458 T8: FromNapiValue,
459 T9: FromNapiValue,
460 T10: FromNapiValue,
461{
462 tuple_from_napi_value!(11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
463}
464
465impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> FromNapiValue
466 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)
467where
468 T0: FromNapiValue,
469 T1: FromNapiValue,
470 T2: FromNapiValue,
471 T3: FromNapiValue,
472 T4: FromNapiValue,
473 T5: FromNapiValue,
474 T6: FromNapiValue,
475 T7: FromNapiValue,
476 T8: FromNapiValue,
477 T9: FromNapiValue,
478 T10: FromNapiValue,
479 T11: FromNapiValue,
480{
481 tuple_from_napi_value!(12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
482}
483
484impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> FromNapiValue
485 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)
486where
487 T0: FromNapiValue,
488 T1: FromNapiValue,
489 T2: FromNapiValue,
490 T3: FromNapiValue,
491 T4: FromNapiValue,
492 T5: FromNapiValue,
493 T6: FromNapiValue,
494 T7: FromNapiValue,
495 T8: FromNapiValue,
496 T9: FromNapiValue,
497 T10: FromNapiValue,
498 T11: FromNapiValue,
499 T12: FromNapiValue,
500{
501 tuple_from_napi_value!(13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
502}
503
504impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> FromNapiValue
505 for (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13)
506where
507 T0: FromNapiValue,
508 T1: FromNapiValue,
509 T2: FromNapiValue,
510 T3: FromNapiValue,
511 T4: FromNapiValue,
512 T5: FromNapiValue,
513 T6: FromNapiValue,
514 T7: FromNapiValue,
515 T8: FromNapiValue,
516 T9: FromNapiValue,
517 T10: FromNapiValue,
518 T11: FromNapiValue,
519 T12: FromNapiValue,
520 T13: FromNapiValue,
521{
522 tuple_from_napi_value!(14, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
523}
524
525impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> FromNapiValue
526 for (
527 T0,
528 T1,
529 T2,
530 T3,
531 T4,
532 T5,
533 T6,
534 T7,
535 T8,
536 T9,
537 T10,
538 T11,
539 T12,
540 T13,
541 T14,
542 )
543where
544 T0: FromNapiValue,
545 T1: FromNapiValue,
546 T2: FromNapiValue,
547 T3: FromNapiValue,
548 T4: FromNapiValue,
549 T5: FromNapiValue,
550 T6: FromNapiValue,
551 T7: FromNapiValue,
552 T8: FromNapiValue,
553 T9: FromNapiValue,
554 T10: FromNapiValue,
555 T11: FromNapiValue,
556 T12: FromNapiValue,
557 T13: FromNapiValue,
558 T14: FromNapiValue,
559{
560 tuple_from_napi_value!(15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
561}
562
563impl<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> FromNapiValue
564 for (
565 T0,
566 T1,
567 T2,
568 T3,
569 T4,
570 T5,
571 T6,
572 T7,
573 T8,
574 T9,
575 T10,
576 T11,
577 T12,
578 T13,
579 T14,
580 T15,
581 )
582where
583 T0: FromNapiValue,
584 T1: FromNapiValue,
585 T2: FromNapiValue,
586 T3: FromNapiValue,
587 T4: FromNapiValue,
588 T5: FromNapiValue,
589 T6: FromNapiValue,
590 T7: FromNapiValue,
591 T8: FromNapiValue,
592 T9: FromNapiValue,
593 T10: FromNapiValue,
594 T11: FromNapiValue,
595 T12: FromNapiValue,
596 T13: FromNapiValue,
597 T14: FromNapiValue,
598 T15: FromNapiValue,
599{
600 tuple_from_napi_value!(16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
601}
602