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 | let c_field = CString::new(field.as_ref())?; |
26 | |
27 | unsafe { |
28 | let mut ret = ptr::null_mut(); |
29 | |
30 | check_status!( |
31 | sys::napi_get_named_property(self.0.env, self.0.value, c_field.as_ptr(), &mut ret), |
32 | "Failed to get property with field ` {}`" , |
33 | field.as_ref(), |
34 | )?; |
35 | |
36 | let ty = type_of!(self.0.env, ret)?; |
37 | |
38 | Ok(if ty == ValueType::Undefined { |
39 | None |
40 | } else { |
41 | Some(V::from_napi_value(self.0.env, ret)?) |
42 | }) |
43 | } |
44 | } |
45 | |
46 | pub fn set<K: AsRef<str>, V: ToNapiValue>(&mut self, field: K, val: V) -> Result<()> { |
47 | let c_field = CString::new(field.as_ref())?; |
48 | |
49 | unsafe { |
50 | let napi_val = V::to_napi_value(self.0.env, val)?; |
51 | |
52 | check_status!( |
53 | sys::napi_set_named_property(self.0.env, self.0.value, c_field.as_ptr(), napi_val), |
54 | "Failed to set property with field ` {}`" , |
55 | c_field.to_string_lossy(), |
56 | )?; |
57 | |
58 | Ok(()) |
59 | } |
60 | } |
61 | |
62 | pub fn keys(obj: &Object) -> Result<Vec<String>> { |
63 | let mut names = ptr::null_mut(); |
64 | unsafe { |
65 | check_status!( |
66 | sys::napi_get_property_names(obj.0.env, obj.0.value, &mut names), |
67 | "Failed to get property names of given object" |
68 | )?; |
69 | } |
70 | |
71 | let names = unsafe { Array::from_napi_value(obj.0.env, names)? }; |
72 | let mut ret = vec![]; |
73 | |
74 | for i in 0..names.len() { |
75 | ret.push(names.get::<String>(i)?.unwrap()); |
76 | } |
77 | |
78 | Ok(ret) |
79 | } |
80 | } |
81 | |
82 | impl TypeName for Object { |
83 | fn type_name() -> &'static str { |
84 | "Object" |
85 | } |
86 | |
87 | fn value_type() -> ValueType { |
88 | ValueType::Object |
89 | } |
90 | } |
91 | |
92 | impl ValidateNapiValue for JsObject {} |
93 | |