workflow_wasm/
options.rs

1//!
2//! Helper trait for managing options struct which extends [Object](js_sys::Object)
3//! ```ignore
4//! # use wasm_bindgen::JsValue;
5//! # use crate::workflow_wasm::options::OptionsTrait;
6//! // create MyOptions struct
7//!
8//! #[wasm_bindgen]
9//! extern "C" {
10//!     #[derive(Debug, Clone, PartialEq, Eq)]
11//!     #[wasm_bindgen(extends = js_sys::Object)]
12//!     pub type MyOptions;
13//! }
14//!
15//!
16//! impl OptionsTrait for MyOptions{}
17//!
18//! //impl methods as you need
19//! impl MyOptions{
20//!     /// Set title
21//!     pub fn title(self, title:&str)->Self{
22//!         self.set("title", JsValue::from(title))
23//!     }
24//!
25//!     /// Set active
26//!     pub fn active(self, active:bool)->Self{
27//!         self.set("active", JsValue::from(active))
28//!     }
29//! }
30//!
31//! // use MyOptions
32//!
33//! let options = MyOptions::new()
34//!     .title("title text")
35//!     .active(true);
36//!
37//! ```
38//!
39
40use js_sys::Object;
41use wasm_bindgen::prelude::*;
42
43pub trait OptionsTrait {
44    /// "Construct a new `Options`.
45    ///
46    fn new() -> Self
47    where
48        Self: wasm_bindgen::JsCast,
49    {
50        #[allow(unused_mut)]
51        let mut ret: Self = ::wasm_bindgen::JsCast::unchecked_into(Object::new());
52        ret = ret.initialize();
53        ret
54    }
55
56    fn initialize(self) -> Self
57    where
58        Self: wasm_bindgen::JsCast,
59    {
60        self
61    }
62
63    fn set(self, mut key: &str, value: JsValue) -> Self
64    where
65        Self: wasm_bindgen::JsCast,
66    {
67        let mut target = self.as_ref().clone();
68
69        if key.contains('.') {
70            let mut name_parts: Vec<&str> = key.split('.').collect();
71            key = name_parts.pop().unwrap();
72
73            for name in name_parts {
74                //log_info!("name: {}, target: {:?}", name, target);
75                let r = ::js_sys::Reflect::get(&target, &JsValue::from(name));
76
77                match r {
78                    Ok(r) => {
79                        if !r.is_undefined() {
80                            target = r
81                        } else {
82                            let object = Object::new();
83                            let new_target = JsValue::from(object);
84                            //log_info!("new_target: {:?}", new_target);
85                            let _ =
86                                ::js_sys::Reflect::set(&target, &JsValue::from(name), &new_target);
87
88                            target = new_target;
89                        }
90                    }
91                    Err(err) => {
92                        panic!("OptionsExt::set(): unable to find property `{name}`, err: {err:?}");
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}
110
111/*
112#[cfg(test)]
113mod test{
114    use super::*;
115    use crate as workflow_wasm;
116    #[test]
117    fn test(){
118        #[wasm_bindgen]
119        extern "C" {
120            #[wasm_bindgen(extends = js_sys::Object)]
121            #[derive(Debug, Clone, PartialEq, Eq)]
122            pub type MyOptions;
123        }
124
125        impl workflow_wasm::options::OptionsTrait for MyOptions{}
126
127        //impl methods as you need
128        impl MyOptions{
129            /// Set title
130            pub fn title(self, title:&str)->Self{
131                self.set("title", JsValue::from(title))
132            }
133
134            /// Set active
135            pub fn active(self, active:bool)->Self{
136                self.set("active", JsValue::from(active))
137            }
138        }
139
140        // use MyOptions
141
142        let options = MyOptions::new()
143            .title("title text")
144            .active(true);
145    }
146}
147
148*/