nw_sys/
options.rs

1//!
2//! Helper trait for managing options struct which extends [Object](js_sys::Object)
3//! ```
4//! // create MyOptions struct
5//!
6//! #[wasm_bindgen]
7//! extern "C" {
8//!     #[wasm_bindgen(extends = js_sys::Object)]
9//!     #[derive(Debug, Clone, PartialEq, Eq)]
10//!     pub type MyOptions;
11//! }
12//!
13//! impl workflow_wasm::options::OptionsTrait for MyOptions{}
14//!
15//! //impl methods as you need
16//! impl MyOptions{
17//!     /// Set title
18//!     pub fn title(mut self, title:&str)->Self{
19//!         self.set("title", JsValue::from(title))
20//!     }
21//!
22//!     /// Set active
23//!     pub fn active(mut self, active:bool)->Self{
24//!         self.set("active", JsValue::from(active))
25//!     }
26//! }
27//!
28//! // use MyOptions
29//!
30//! let options = MyOptions::new()
31//!     .title("title text")
32//!     .active(true);
33//!
34//! ```
35//!
36
37use js_sys::Object;
38use wasm_bindgen::prelude::*;
39
40pub trait OptionsTrait {
41    /// "Construct a new `Options`.
42    ///
43    fn new() -> Self
44    where
45        Self: wasm_bindgen::JsCast,
46    {
47        #[allow(unused_mut)]
48        let mut ret: Self = ::wasm_bindgen::JsCast::unchecked_into(Object::new());
49        ret = ret.initialize();
50        ret
51    }
52
53    fn initialize(self) -> Self
54    where
55        Self: wasm_bindgen::JsCast,
56    {
57        self
58    }
59
60    fn set(self, mut key: &str, value: JsValue) -> Self
61    where
62        Self: wasm_bindgen::JsCast,
63    {
64        let mut target = self.as_ref().clone();
65
66        if key.contains('.') {
67            let mut name_parts: Vec<&str> = key.split('.').collect();
68            key = name_parts.pop().unwrap();
69
70            for name in name_parts {
71                //log_info!("name: {}, target: {:?}", name, target);
72                let r = ::js_sys::Reflect::get(&target, &JsValue::from(name));
73
74                match r {
75                    Ok(r) => {
76                        if !r.is_undefined() {
77                            target = r
78                        } else {
79                            let object = Object::new();
80                            let new_target = JsValue::from(object);
81                            //log_info!("new_target: {:?}", new_target);
82                            let _ =
83                                ::js_sys::Reflect::set(&target, &JsValue::from(name), &new_target);
84
85                            target = new_target;
86                        }
87                    }
88                    Err(err) => {
89                        panic!(
90                            "OptionsExt::set(): unable to find property `{name}`, err: {:?}",
91                            err
92                        );
93                    }
94                }
95            }
96
97            //log_info!("final: key: {}, target: {:?}", key, target);
98        }
99
100        let r = ::js_sys::Reflect::set(&target, &JsValue::from(key), &value);
101        debug_assert!(
102            r.is_ok(),
103            "setting properties should never fail on our dictionary objects"
104        );
105        let _ = r;
106
107        self
108    }
109}