napi_h/js_values/
object_property.rs

1use std::convert::From;
2#[cfg(feature = "napi5")]
3use std::ffi::c_void;
4use std::ffi::CString;
5use std::ptr;
6
7use bitflags::bitflags;
8
9#[cfg(feature = "napi5")]
10use crate::{
11  bindgen_runtime::{FromNapiValue, This, ToNapiValue},
12  Env,
13};
14use crate::{sys, Callback, NapiRaw, Result};
15
16#[cfg(feature = "napi5")]
17#[derive(Copy, Clone)]
18pub struct PropertyClosures {
19  pub setter_closure: *mut c_void,
20  pub getter_closure: *mut c_void,
21}
22
23#[cfg(feature = "napi5")]
24impl Default for PropertyClosures {
25  fn default() -> Self {
26    Self {
27      setter_closure: ptr::null_mut(),
28      getter_closure: ptr::null_mut(),
29    }
30  }
31}
32
33#[derive(Clone)]
34pub struct Property {
35  pub name: CString,
36  getter: sys::napi_callback,
37  setter: sys::napi_callback,
38  method: sys::napi_callback,
39  attrs: PropertyAttributes,
40  value: sys::napi_value,
41  pub(crate) is_ctor: bool,
42  #[cfg(feature = "napi5")]
43  pub(crate) closures: PropertyClosures,
44}
45
46impl Default for Property {
47  fn default() -> Self {
48    Property {
49      name: Default::default(),
50      getter: Default::default(),
51      setter: Default::default(),
52      method: Default::default(),
53      attrs: Default::default(),
54      value: ptr::null_mut(),
55      is_ctor: Default::default(),
56      #[cfg(feature = "napi5")]
57      closures: PropertyClosures::default(),
58    }
59  }
60}
61
62bitflags! {
63  #[derive(Debug, Copy, Clone)]
64  pub struct PropertyAttributes: i32 {
65    const Default = sys::PropertyAttributes::default;
66    const Writable = sys::PropertyAttributes::writable;
67    const Enumerable = sys::PropertyAttributes::enumerable;
68    const Configurable = sys::PropertyAttributes::configurable;
69    const Static = sys::PropertyAttributes::static_;
70  }
71}
72
73impl Default for PropertyAttributes {
74  fn default() -> Self {
75    PropertyAttributes::Configurable | PropertyAttributes::Enumerable | PropertyAttributes::Writable
76  }
77}
78
79impl From<PropertyAttributes> for sys::napi_property_attributes {
80  fn from(value: PropertyAttributes) -> Self {
81    value.bits()
82  }
83}
84
85impl Property {
86  pub fn new(name: &str) -> Result<Self> {
87    Ok(Property {
88      name: CString::new(name)?,
89      ..Default::default()
90    })
91  }
92
93  pub fn with_name(mut self, name: &str) -> Self {
94    self.name = CString::new(name).unwrap();
95    self
96  }
97
98  pub fn with_method(mut self, callback: Callback) -> Self {
99    self.method = Some(callback);
100    self
101  }
102
103  pub fn with_getter(mut self, callback: Callback) -> Self {
104    self.getter = Some(callback);
105    self
106  }
107
108  #[cfg(feature = "napi5")]
109  pub fn with_getter_closure<R, F>(mut self, callback: F) -> Self
110  where
111    F: 'static + Fn(Env, This) -> Result<R>,
112    R: ToNapiValue,
113  {
114    let boxed_callback = Box::new(callback);
115    let closure_data_ptr: *mut F = Box::into_raw(boxed_callback);
116    self.closures.getter_closure = closure_data_ptr.cast();
117
118    let fun = crate::trampoline_getter::<R, F>;
119    self.getter = Some(fun);
120    self
121  }
122
123  pub fn with_setter(mut self, callback: Callback) -> Self {
124    self.setter = Some(callback);
125    self
126  }
127
128  #[cfg(feature = "napi5")]
129  pub fn with_setter_closure<F, V>(mut self, callback: F) -> Self
130  where
131    F: 'static + Fn(crate::Env, This, V) -> Result<()>,
132    V: FromNapiValue,
133  {
134    let boxed_callback = Box::new(callback);
135    let closure_data_ptr: *mut F = Box::into_raw(boxed_callback);
136    self.closures.setter_closure = closure_data_ptr.cast();
137
138    let fun = crate::trampoline_setter::<V, F>;
139    self.setter = Some(fun);
140    self
141  }
142
143  pub fn with_property_attributes(mut self, attributes: PropertyAttributes) -> Self {
144    self.attrs = attributes;
145    self
146  }
147
148  pub fn with_value<T: NapiRaw>(mut self, value: &T) -> Self {
149    self.value = unsafe { T::raw(value) };
150    self
151  }
152
153  pub(crate) fn raw(&self) -> sys::napi_property_descriptor {
154    #[cfg(feature = "napi5")]
155    let closures = Box::into_raw(Box::new(self.closures));
156    sys::napi_property_descriptor {
157      utf8name: self.name.as_ptr(),
158      name: ptr::null_mut(),
159      method: self.method,
160      getter: self.getter,
161      setter: self.setter,
162      value: self.value,
163      attributes: self.attrs.into(),
164      #[cfg(not(feature = "napi5"))]
165      data: ptr::null_mut(),
166      #[cfg(feature = "napi5")]
167      data: closures.cast(),
168    }
169  }
170
171  pub fn with_ctor(mut self, callback: Callback) -> Self {
172    self.method = Some(callback);
173    self.is_ctor = true;
174    self
175  }
176}