use std::ffi::CString; use std::ptr; use super::Value; use crate::error::check_status; use crate::{sys, Error, JsString, NapiValue, Property, Result, Status}; #[derive(Debug)] pub struct JsObject(pub(crate) Value); impl JsObject { pub fn set_property(&mut self, key: JsString, value: V) -> Result<()> where V: NapiValue, { check_status(unsafe { sys::napi_set_property(self.0.env, self.0.value, key.0.value, value.raw_value()) }) } pub fn get_property(&self, key: &K) -> Result where K: NapiValue, T: NapiValue, { let mut raw_value = ptr::null_mut(); check_status(unsafe { sys::napi_get_property(self.0.env, self.0.value, key.raw_value(), &mut raw_value) })?; T::from_raw(self.0.env, raw_value) } pub fn set_named_property(&mut self, name: &str, value: T) -> Result<()> where T: NapiValue, { let key = CString::new(name)?; check_status(unsafe { sys::napi_set_named_property(self.0.env, self.0.value, key.as_ptr(), value.raw_value()) }) } pub fn get_named_property(&self, name: &str) -> Result where T: NapiValue, { let key = CString::new(name)?; let mut raw_value = ptr::null_mut(); check_status(unsafe { sys::napi_get_named_property(self.0.env, self.0.value, key.as_ptr(), &mut raw_value) })?; T::from_raw(self.0.env, raw_value) } pub fn has_named_property(&self, name: S) -> Result where S: AsRef, { let mut result = false; let key = CString::new(name.as_ref())?; check_status(unsafe { sys::napi_has_named_property(self.0.env, self.0.value, key.as_ptr(), &mut result) })?; Ok(result) } pub fn delete_property(&mut self, name: S) -> Result where S: NapiValue, { let mut result = false; check_status(unsafe { sys::napi_delete_property(self.0.env, self.0.value, name.raw_value(), &mut result) })?; Ok(result) } pub fn delete_named_property(&mut self, name: &str) -> Result { let mut result = false; let key_str = CString::new(name)?; let mut js_key = ptr::null_mut(); check_status(unsafe { sys::napi_create_string_utf8(self.0.env, key_str.as_ptr(), name.len() as _, &mut js_key) })?; check_status(unsafe { sys::napi_delete_property(self.0.env, self.0.value, js_key, &mut result) })?; Ok(result) } pub fn has_own_property(&self, key: &str) -> Result { let mut result = false; let string = CString::new(key)?; let mut js_key = ptr::null_mut(); check_status(unsafe { sys::napi_create_string_utf8(self.0.env, string.as_ptr(), key.len() as _, &mut js_key) })?; check_status(unsafe { sys::napi_has_own_property(self.0.env, self.0.value, js_key, &mut result) })?; Ok(result) } pub fn has_own_property_js(&self, key: K) -> Result where K: NapiValue, { let mut result = false; check_status(unsafe { sys::napi_has_own_property(self.0.env, self.0.value, key.raw_value(), &mut result) })?; Ok(result) } pub fn has_property(&self, name: &str) -> Result { let string = CString::new(name)?; let mut js_key = ptr::null_mut(); let mut result = false; check_status(unsafe { sys::napi_create_string_utf8(self.0.env, string.as_ptr(), name.len() as _, &mut js_key) })?; check_status(unsafe { sys::napi_has_property(self.0.env, self.0.value, js_key, &mut result) })?; Ok(result) } pub fn has_property_js(&self, name: K) -> Result where K: NapiValue, { let mut result = false; check_status(unsafe { sys::napi_has_property(self.0.env, self.0.value, name.raw_value(), &mut result) })?; Ok(result) } pub fn get_property_names(&self) -> Result where T: NapiValue, { let mut raw_value = ptr::null_mut(); let status = unsafe { sys::napi_get_property_names(self.0.env, self.0.value, &mut raw_value) }; check_status(status)?; T::from_raw(self.0.env, raw_value) } pub fn get_prototype(&self) -> Result where T: NapiValue, { let mut result = ptr::null_mut(); check_status(unsafe { sys::napi_get_prototype(self.0.env, self.0.value, &mut result) })?; T::from_raw(self.0.env, result) } pub fn set_element(&mut self, index: u32, value: T) -> Result<()> where T: NapiValue, { check_status(unsafe { sys::napi_set_element(self.0.env, self.0.value, index, value.raw_value()) }) } pub fn has_element(&self, index: u32) -> Result { let mut result = false; check_status(unsafe { sys::napi_has_element(self.0.env, self.0.value, index, &mut result) })?; Ok(result) } pub fn delete_element(&mut self, index: u32) -> Result { let mut result = false; check_status(unsafe { sys::napi_delete_element(self.0.env, self.0.value, index, &mut result) })?; Ok(result) } pub fn get_element(&self, index: u32) -> Result where T: NapiValue, { let mut raw_value = ptr::null_mut(); check_status(unsafe { sys::napi_get_element(self.0.env, self.0.value, index, &mut raw_value) })?; T::from_raw(self.0.env, raw_value) } pub fn define_properties(&mut self, properties: &[Property]) -> Result<()> { check_status(unsafe { sys::napi_define_properties( self.0.env, self.0.value, properties.len() as _, properties .iter() .map(|property| property.raw()) .collect::>() .as_ptr(), ) }) } pub fn get_array_length(&self) -> Result { if self.is_array()? != true { return Err(Error::new( Status::ArrayExpected, "Object is not array".to_owned(), )); } self.get_array_length_unchecked() } #[inline] pub fn get_array_length_unchecked(&self) -> Result { let mut length: u32 = 0; check_status(unsafe { sys::napi_get_array_length(self.0.env, self.raw_value(), &mut length) })?; Ok(length) } }