node_api/value/
array.rs

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}