napi_calm_down/bindgen_runtime/js_values/
object.rs

1use crate::{bindgen_prelude::*, check_status, sys, type_of, JsObject, ValueType};
2use std::{ffi::CString, ptr};
3
4pub type Object = JsObject;
5
6impl 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
90impl TypeName for Object {
91  fn type_name() -> &'static str {
92    "Object"
93  }
94
95  fn value_type() -> ValueType {
96    ValueType::Object
97  }
98}
99
100impl ValidateNapiValue for JsObject {}