1use crate::{
2 sys::{
3 napi_create_array, napi_get_array_length, napi_get_element, napi_set_element, napi_status,
4 },
5 Env, Error, Result, Value,
6};
7use num::ToPrimitive;
8use std::mem::MaybeUninit;
9
10#[derive(Clone, Copy)]
11pub struct Array<'a>(Value<'a>);
12
13impl<'a> Array<'a> {
14 pub(crate) fn from_value(value: Value) -> Array {
15 Array(value)
16 }
17
18 pub fn value(&self) -> Value<'a> {
19 self.0
20 }
21
22 pub fn env(&self) -> Env<'a> {
23 self.0.env()
24 }
25
26 pub fn new(env: Env) -> Result<Array> {
27 let value = unsafe {
28 let mut result = MaybeUninit::uninit();
29 let status = napi_create_array(env.raw(), result.as_mut_ptr());
30 if status != napi_status::napi_ok {
31 return Err(Error::from_last_node_api_error(env.raw(), status));
32 }
33 result.assume_init()
34 };
35 Ok(Array(Value::from_raw(env, value)))
36 }
37
38 pub fn size(&self) -> Result<usize> {
39 let len = unsafe {
40 let mut result = MaybeUninit::uninit();
41 let status =
42 napi_get_array_length(self.env().raw(), self.value().raw(), result.as_mut_ptr());
43 if status != napi_status::napi_ok {
44 return Err(Error::from_last_node_api_error(self.env().raw(), status));
45 }
46 result.assume_init()
47 };
48 let len = len
49 .to_usize()
50 .ok_or_else(|| Error::message("could not cast array length to usize"))?;
51 Ok(len)
52 }
53
54 pub fn get(&self, index: usize) -> Result<Value<'a>> {
55 let index = index
56 .to_u32()
57 .ok_or_else(|| Error::message("could not cast index to u32"))?;
58 let value = unsafe {
59 let mut result = MaybeUninit::uninit();
60 let status = napi_get_element(
61 self.env().raw(),
62 self.value().raw(),
63 index,
64 result.as_mut_ptr(),
65 );
66 if status != napi_status::napi_ok {
67 return Err(Error::from_last_node_api_error(self.env().raw(), status));
68 }
69 result.assume_init()
70 };
71 let value = Value::from_raw(self.env(), value);
72 Ok(value)
73 }
74
75 pub fn set(&mut self, index: usize, value: impl Into<Value<'a>>) -> Result<()> {
76 let index = index
77 .to_u32()
78 .ok_or_else(|| Error::message("could not cast index to u32"))?;
79 let value = value.into();
80 unsafe {
81 let status = napi_set_element(self.env().raw(), self.value().raw(), index, value.raw());
82 if status != napi_status::napi_ok {
83 return Err(Error::from_last_node_api_error(self.env().raw(), status));
84 }
85 }
86 Ok(())
87 }
88
89 pub fn push(&mut self, value: impl Into<Value<'a>>) -> Result<()> {
90 let len = self.size()?;
91 self.set(len, value)?;
92 Ok(())
93 }
94
95 pub fn iter(&self) -> Result<ArrayIterator<'a>> {
96 Ok(ArrayIterator {
97 array: *self,
98 len: self.size()?,
99 i: 0,
100 })
101 }
102}
103
104pub struct ArrayIterator<'a> {
105 array: Array<'a>,
106 len: usize,
107 i: usize,
108}
109
110impl<'a> ArrayIterator<'a> {
111 pub fn is_empty(&self) -> bool {
112 self.len == 0
113 }
114
115 pub fn len(&self) -> usize {
116 self.len
117 }
118}
119
120impl<'a> Iterator for ArrayIterator<'a> {
121 type Item = Result<Value<'a>>;
122
123 fn next(&mut self) -> Option<Self::Item> {
124 if self.i >= self.len {
125 None
126 } else {
127 let result = self.array.get(self.i);
128 self.i += 1;
129 Some(result)
130 }
131 }
132}