1use crate::convert::*;
6use crate::error::Error;
7use crate::extensions::jsvalue::JsValueExtension;
8use crate::utils::*;
9use js_sys::{Object, Reflect};
10use wasm_bindgen::prelude::*;
11
12pub trait ObjectExtension {
14 fn get<T>(&self, prop: &str) -> Result<T, Error>
16 where
17 T: TryFrom<JsValue>,
18 <T as TryFrom<wasm_bindgen::JsValue>>::Error: std::fmt::Display;
19
20 fn try_get<T>(&self, prop: &str) -> Result<Option<T>, Error>
23 where
24 T: TryFrom<JsValue>,
25 <T as TryFrom<wasm_bindgen::JsValue>>::Error: std::fmt::Display;
26
27 fn cast_into<T>(&self, prop: &str) -> Result<T, Error>
29 where
30 T: TryCastFromJs,
31 <T as TryCastFromJs>::Error: std::fmt::Display;
32
33 fn cast_from<T>(&self, prop: &str) -> Result<Cast<'static, T>, Error>
34 where
35 T: TryCastFromJs,
36 <T as TryCastFromJs>::Error: std::fmt::Display;
37
38 fn try_cast_into<T>(&self, prop: &str) -> Result<Option<T>, Error>
41 where
42 T: TryCastFromJs,
43 <T as TryCastFromJs>::Error: std::fmt::Display;
44
45 fn try_cast_from<T>(&self, prop: &str) -> Result<Option<Cast<'static, T>>, Error>
46 where
47 T: TryCastFromJs,
48 <T as TryCastFromJs>::Error: std::fmt::Display;
49
50 fn get_value(&self, prop: &str) -> Result<JsValue, Error>;
52 fn get_object(&self, prop: &str) -> Result<Object, Error>;
54 fn try_get_object(&self, prop: &str) -> Result<Option<Object>, Error>;
56 fn try_get_value(&self, prop: &str) -> Result<Option<JsValue>, Error>;
58 fn get_string(&self, prop: &str) -> Result<String, Error>;
60 fn try_get_string(&self, prop: &str) -> Result<Option<String>, Error>;
62 fn get_u8(&self, prop: &str) -> Result<u8, Error>;
64 fn get_u16(&self, prop: &str) -> Result<u16, Error>;
66 fn get_u32(&self, prop: &str) -> Result<u32, Error>;
68 fn get_u64(&self, prop: &str) -> Result<u64, Error>;
70 fn get_f64(&self, prop: &str) -> Result<f64, Error>;
72 fn get_bool(&self, prop: &str) -> Result<bool, Error>;
74 fn try_get_bool(&self, prop: &str) -> Result<Option<bool>, Error>;
75 fn get_vec(&self, prop: &str) -> Result<Vec<JsValue>, Error>;
77 fn get_vec_u8(&self, prop: &str) -> Result<Vec<u8>, Error>;
79 fn get_vec_u8_from_number_array(&self, prop: &str) -> Result<Vec<u8>, Error>;
81 fn get_vec_u8_from_uint8_array(&self, prop: &str) -> Result<Vec<u8>, Error>;
83 fn set(&self, prop: &str, value: &JsValue) -> Result<bool, Error>;
85 fn set_vec(&self, prop: &str, values: &[JsValue]) -> Result<bool, Error>;
87 fn set_properties(&self, props: &[(&str, &JsValue)]) -> Result<(), Error>;
89 fn delete(&self, prop: &str) -> Result<bool, Error>;
91}
92
93impl ObjectExtension for Object {
94 fn get<T>(&self, prop: &str) -> Result<T, Error>
95 where
96 T: TryFrom<JsValue>,
97 <T as TryFrom<wasm_bindgen::JsValue>>::Error: std::fmt::Display,
98 {
99 let js_value = Reflect::get(self, &JsValue::from(prop))?;
100 T::try_from(js_value).map_err(Error::custom)
101 }
102
103 fn try_get<T>(&self, prop: &str) -> Result<Option<T>, Error>
104 where
105 T: TryFrom<JsValue>,
106 <T as TryFrom<wasm_bindgen::JsValue>>::Error: std::fmt::Display,
107 {
108 let js_value = Reflect::get(self, &JsValue::from(prop))?;
109 if js_value.is_undefined() {
110 Ok(None)
111 } else {
112 Ok(Some(T::try_from(js_value).map_err(Error::custom)?))
113 }
114 }
115
116 fn cast_into<T>(&self, prop: &str) -> Result<T, Error>
117 where
118 T: TryCastFromJs,
119 <T as TryCastFromJs>::Error: std::fmt::Display,
120 {
121 let js_value = Reflect::get(self, &JsValue::from(prop))?;
122 T::try_owned_from(&js_value).map_err(Error::custom)
123 }
124
125 fn cast_from<T>(&self, prop: &str) -> Result<Cast<'static, T>, Error>
126 where
127 T: TryCastFromJs,
128 <T as TryCastFromJs>::Error: std::fmt::Display,
129 {
130 let js_value = Reflect::get(self, &JsValue::from(prop))?;
131 T::try_captured_cast_from(&js_value).map_err(Error::custom)
132 }
133
134 fn try_cast_into<T>(&self, prop: &str) -> Result<Option<T>, Error>
135 where
136 T: TryCastFromJs,
137 <T as TryCastFromJs>::Error: std::fmt::Display,
138 {
139 let js_value = Reflect::get(self, &JsValue::from(prop))?;
140 if js_value.is_undefined() {
141 Ok(None)
142 } else {
143 Ok(Some(T::try_owned_from(js_value).map_err(Error::custom)?))
144 }
145 }
146
147 fn try_cast_from<T>(&self, prop: &str) -> Result<Option<Cast<'static, T>>, Error>
148 where
149 T: TryCastFromJs,
150 <T as TryCastFromJs>::Error: std::fmt::Display,
151 {
152 let js_value = Reflect::get(self, &JsValue::from(prop))?;
153 if js_value.is_undefined() {
154 Ok(None)
155 } else {
156 Ok(Some(
157 T::try_captured_cast_from(js_value).map_err(Error::custom)?,
158 ))
159 }
160 }
161
162 fn get_value(&self, prop: &str) -> Result<JsValue, Error> {
163 Ok(Reflect::get(self, &JsValue::from(prop))?)
164 }
165
166 fn get_object(&self, prop: &str) -> Result<Object, Error> {
167 let value = Reflect::get(self, &JsValue::from(prop))?;
168 let object = Object::try_from(&value).ok_or(Error::MissingProperty(prop.to_string()))?;
169 Ok(object.clone())
170 }
171
172 fn try_get_object(&self, prop: &str) -> Result<Option<Object>, Error> {
173 let value = Reflect::get(self, &JsValue::from(prop))?;
174 Ok(Object::try_from(&value).cloned())
175 }
176
177 fn try_get_value(&self, prop: &str) -> Result<Option<JsValue>, Error> {
178 let js_value = Reflect::get(self, &JsValue::from(prop))?;
179 if js_value == JsValue::UNDEFINED {
180 Ok(None)
181 } else {
182 Ok(Some(js_value))
183 }
184 }
185
186 fn get_string(&self, prop: &str) -> Result<String, Error> {
187 try_get_string_from_prop(self, prop)
188 }
189
190 fn try_get_string(&self, prop: &str) -> Result<Option<String>, Error> {
191 Ok(self.get_value(prop)?.as_string())
192 }
193
194 fn get_bool(&self, prop: &str) -> Result<bool, Error> {
195 try_get_bool_from_prop(self, prop)
196 }
197
198 fn try_get_bool(&self, prop: &str) -> Result<Option<bool>, Error> {
199 Ok(self.get_value(prop)?.as_bool())
200 }
201
202 fn get_u8(&self, prop: &str) -> Result<u8, Error> {
203 try_get_u8_from_prop(self, prop)
204 }
205
206 fn get_u16(&self, prop: &str) -> Result<u16, Error> {
207 try_get_u16_from_prop(self, prop)
208 }
209
210 fn get_u32(&self, prop: &str) -> Result<u32, Error> {
211 try_get_u32_from_prop(self, prop)
212 }
213
214 fn get_u64(&self, prop: &str) -> Result<u64, Error> {
215 try_get_u64_from_prop(self, prop)
216 }
217
218 fn get_vec(&self, prop: &str) -> Result<Vec<JsValue>, Error> {
219 try_get_vec_from_prop(self, prop)
220 }
221
222 fn get_vec_u8(&self, prop: &str) -> Result<Vec<u8>, Error> {
223 let v = Reflect::get(self, &JsValue::from(prop))?;
224 v.try_as_vec_u8()
225 }
226
227 fn get_vec_u8_from_number_array(&self, prop: &str) -> Result<Vec<u8>, Error> {
228 try_get_vec_u8_from_number_array_prop(self, prop)
229 }
230
231 fn get_vec_u8_from_uint8_array(&self, prop: &str) -> Result<Vec<u8>, Error> {
232 try_get_vec_u8_from_uint8_array_prop(self, prop)
233 }
234
235 fn get_f64(&self, prop: &str) -> Result<f64, Error> {
236 try_get_f64_from_prop(self, prop)
237 }
238
239 fn set(&self, prop: &str, value: &JsValue) -> Result<bool, Error> {
240 Ok(Reflect::set(self, &JsValue::from(prop), value)?)
241 }
242
243 fn set_vec(&self, prop: &str, values: &[JsValue]) -> Result<bool, Error> {
244 let array = js_sys::Array::new();
245 for v in values {
246 array.push(v);
247 }
248 Ok(Reflect::set(self, &JsValue::from(prop), &array)?)
249 }
250
251 fn set_properties(&self, props: &[(&str, &JsValue)]) -> Result<(), Error> {
252 for (k, v) in props.iter() {
253 Reflect::set(self, &JsValue::from(*k), v)?;
254 }
255 Ok(())
256 }
257
258 fn delete(&self, prop: &str) -> Result<bool, Error> {
259 Ok(Reflect::delete_property(self, &JsValue::from(prop))?)
260 }
261}