1 | use std::convert::From; |
2 | #[cfg (feature = "napi5" )] |
3 | use std::ffi::c_void; |
4 | use std::ffi::CString; |
5 | use std::ptr; |
6 | |
7 | use bitflags::bitflags; |
8 | |
9 | #[cfg (feature = "napi5" )] |
10 | use crate::{ |
11 | bindgen_runtime::{FromNapiValue, This, ToNapiValue}, |
12 | Env, |
13 | }; |
14 | use crate::{sys, Callback, NapiRaw, Result}; |
15 | |
16 | #[cfg (feature = "napi5" )] |
17 | #[derive (Copy, Clone)] |
18 | pub struct PropertyClosures { |
19 | pub setter_closure: *mut c_void, |
20 | pub getter_closure: *mut c_void, |
21 | } |
22 | |
23 | #[cfg (feature = "napi5" )] |
24 | impl 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)] |
34 | pub 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 | |
46 | impl 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 | |
62 | bitflags! { |
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 | |
73 | impl Default for PropertyAttributes { |
74 | fn default() -> Self { |
75 | PropertyAttributes::Configurable | PropertyAttributes::Enumerable | PropertyAttributes::Writable |
76 | } |
77 | } |
78 | |
79 | impl From<PropertyAttributes> for sys::napi_property_attributes { |
80 | fn from(value: PropertyAttributes) -> Self { |
81 | value.bits() |
82 | } |
83 | } |
84 | |
85 | impl 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 (*mut napi_env__, *mut napi_callback_info__) -> *mut napi_value__" title="fun">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 (*mut napi_env__, *mut napi_callback_info__) -> *mut napi_value__" title="fun">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 | } |
177 | |