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