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 | |