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