| 1 | use crate::{bindgen_prelude::*, check_status, sys, type_of, JsObject, ValueType}; |
| 2 | use std::{ffi::CString, ptr}; |
| 3 | |
| 4 | pub type Object = JsObject; |
| 5 | |
| 6 | impl Object { |
| 7 | #[cfg (feature = "serde-json" )] |
| 8 | pub(crate) fn new(env: sys::napi_env) -> Result<Self> { |
| 9 | let mut ptr = ptr::null_mut(); |
| 10 | unsafe { |
| 11 | check_status!( |
| 12 | sys::napi_create_object(env, &mut ptr), |
| 13 | "Failed to create napi Object" |
| 14 | )?; |
| 15 | } |
| 16 | |
| 17 | Ok(Self(crate::Value { |
| 18 | env, |
| 19 | value: ptr, |
| 20 | value_type: ValueType::Object, |
| 21 | })) |
| 22 | } |
| 23 | |
| 24 | pub fn get<K: AsRef<str>, V: FromNapiValue>(&self, field: K) -> Result<Option<V>> { |
| 25 | unsafe { |
| 26 | self |
| 27 | .get_inner(field.as_ref())? |
| 28 | .map(|v| V::from_napi_value(self.0.env, v)) |
| 29 | .transpose() |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | fn get_inner(&self, field: &str) -> Result<Option<sys::napi_value>> { |
| 34 | let c_field = CString::new(field)?; |
| 35 | |
| 36 | unsafe { |
| 37 | let mut ret = ptr::null_mut(); |
| 38 | |
| 39 | check_status!( |
| 40 | sys::napi_get_named_property(self.0.env, self.0.value, c_field.as_ptr(), &mut ret), |
| 41 | "Failed to get property with field ` {field}`" , |
| 42 | )?; |
| 43 | |
| 44 | let ty = type_of!(self.0.env, ret)?; |
| 45 | |
| 46 | Ok(if ty == ValueType::Undefined { |
| 47 | None |
| 48 | } else { |
| 49 | Some(ret) |
| 50 | }) |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | pub fn set<K: AsRef<str>, V: ToNapiValue>(&mut self, field: K, val: V) -> Result<()> { |
| 55 | unsafe { self.set_inner(field.as_ref(), V::to_napi_value(self.0.env, val)?) } |
| 56 | } |
| 57 | |
| 58 | unsafe fn set_inner(&mut self, field: &str, napi_val: sys::napi_value) -> Result<()> { |
| 59 | let c_field = CString::new(field)?; |
| 60 | |
| 61 | unsafe { |
| 62 | check_status!( |
| 63 | sys::napi_set_named_property(self.0.env, self.0.value, c_field.as_ptr(), napi_val), |
| 64 | "Failed to set property with field ` {field}`" , |
| 65 | )?; |
| 66 | Ok(()) |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | pub fn keys(obj: &Object) -> Result<Vec<String>> { |
| 71 | let mut names = ptr::null_mut(); |
| 72 | unsafe { |
| 73 | check_status!( |
| 74 | sys::napi_get_property_names(obj.0.env, obj.0.value, &mut names), |
| 75 | "Failed to get property names of given object" |
| 76 | )?; |
| 77 | } |
| 78 | |
| 79 | let names = unsafe { Array::from_napi_value(obj.0.env, names)? }; |
| 80 | let mut ret = vec![]; |
| 81 | |
| 82 | for i in 0..names.len() { |
| 83 | ret.push(names.get::<String>(i)?.unwrap()); |
| 84 | } |
| 85 | |
| 86 | Ok(ret) |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | impl TypeName for Object { |
| 91 | fn type_name() -> &'static str { |
| 92 | "Object" |
| 93 | } |
| 94 | |
| 95 | fn value_type() -> ValueType { |
| 96 | ValueType::Object |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | impl ValidateNapiValue for JsObject {} |
| 101 | |