Skip to main content

wasm_dom/existing/
access.rs

1use std::fmt;
2
3use js_sys::Reflect;
4use wasm_bindgen::{JsCast, JsValue, UnwrapThrowExt, throw_str};
5use web_sys::{Element, EventTarget, HtmlElement, Node};
6
7pub trait JsObjectAccess {
8    fn get(&self, property: impl Into<JsValue>) -> JsValue;
9    fn set(&self, property: impl Into<JsValue>, value: impl Into<JsValue>) -> bool;
10}
11
12impl JsObjectAccess for JsValue {
13    fn get(&self, property: impl Into<JsValue>) -> JsValue {
14        Reflect::get(self, &property.into()).expect_throw("Target should be an Object")
15    }
16
17    fn set(&self, property: impl Into<JsValue>, value: impl Into<JsValue>) -> bool {
18        Reflect::set(self, &property.into(), &value.into()).expect_throw("Target should be an Object")
19    }
20}
21
22pub trait Cast {
23    fn cast<T: JsCast>(self) -> T;
24    fn maybe_cast<T: JsCast>(self) -> Option<T>;
25
26    fn cast_as<T: JsCast>(&self) -> &T;
27    fn maybe_cast_as<T: JsCast>(&self) -> Option<&T>;
28}
29
30impl<E: JsCast + fmt::Debug> Cast for E {
31    fn cast<T: JsCast>(self) -> T {
32        self.dyn_into::<T>()
33            .unwrap_or_else(|element| throw_str(&format!("{element:?} should cast to target type")))
34    }
35
36    fn maybe_cast<T: JsCast>(self) -> Option<T> {
37        self.dyn_into::<T>().ok()
38    }
39
40    fn cast_as<T: JsCast>(&self) -> &T {
41        self.dyn_ref::<T>()
42            .unwrap_or_else(|| throw_str(&format!("{self:?} should cast to target type")))
43    }
44
45    fn maybe_cast_as<T: JsCast>(&self) -> Option<&T> {
46        self.dyn_ref::<T>()
47    }
48}
49
50pub trait CastToElement {
51    fn into_element(self) -> Element;
52    fn maybe_into_element(self) -> Option<Element>;
53
54    fn as_element(&self) -> &Element;
55    fn maybe_as_element(&self) -> Option<&Element>;
56}
57
58impl CastToElement for EventTarget {
59    fn into_element(self) -> Element {
60        self.cast()
61    }
62
63    fn maybe_into_element(self) -> Option<Element> {
64        self.maybe_cast()
65    }
66
67    fn as_element(&self) -> &Element {
68        self.cast_as()
69    }
70
71    fn maybe_as_element(&self) -> Option<&Element> {
72        self.maybe_cast_as()
73    }
74}
75
76impl CastToElement for Node {
77    fn into_element(self) -> Element {
78        self.cast()
79    }
80
81    fn maybe_into_element(self) -> Option<Element> {
82        self.maybe_cast()
83    }
84
85    fn as_element(&self) -> &Element {
86        self.cast_as()
87    }
88
89    fn maybe_as_element(&self) -> Option<&Element> {
90        self.maybe_cast_as()
91    }
92}
93
94pub trait CastToHtmlElement {
95    fn into_html(self) -> HtmlElement;
96    fn maybe_into_html(self) -> Option<HtmlElement>;
97
98    fn as_html(&self) -> &HtmlElement;
99    fn maybe_as_html(&self) -> Option<&HtmlElement>;
100}
101
102impl CastToHtmlElement for Element {
103    fn into_html(self) -> HtmlElement {
104        self.cast()
105    }
106
107    fn maybe_into_html(self) -> Option<HtmlElement> {
108        self.maybe_cast()
109    }
110
111    fn as_html(&self) -> &HtmlElement {
112        self.cast_as()
113    }
114
115    fn maybe_as_html(&self) -> Option<&HtmlElement> {
116        self.maybe_cast_as()
117    }
118}