px_wsdom_core/
js_cast.rs

1use core::{future::Future, marker::PhantomData};
2
3use crate::js::value::JsValue;
4
5/// For converting between JavaScript types.
6///
7/// Note that most class types generated by WSDOM also comes with `Into` and `AsRef` impls for converting to their ancestors in the inheritance chain.
8pub trait JsCast
9where
10    Self: AsRef<JsValue> + Into<JsValue>,
11{
12    // fn instanceof(val: &JsValue) -> bool;
13    fn unchecked_from_js(val: JsValue) -> Self;
14    fn unchecked_from_js_ref(val: &JsValue) -> &Self;
15
16    // fn has_type<T>(&self) -> bool
17    //    where T: JsCast { ... }
18    // fn dyn_into<T>(self) -> Result<T, Self>
19    //    where T: JsCast { ... }
20    // fn dyn_ref<T>(&self) -> Option<&T>
21    //    where T: JsCast { ... }
22    fn unchecked_into<T>(self) -> T
23    where
24        T: JsCast,
25    {
26        T::unchecked_from_js(self.into())
27    }
28    fn unchecked_ref<T>(&self) -> &T
29    where
30        T: JsCast,
31    {
32        T::unchecked_from_js_ref(self.as_ref())
33    }
34    // fn is_instance_of<T>(&self) -> bool
35    //    where T: JsCast { ... }
36    // fn is_type_of(val: &JsValue) -> bool { ... }
37}
38pin_project_lite::pin_project! {
39    #[derive(Clone, Copy)]
40    pub struct Cast<T,U>{
41        #[pin]
42        pub value: T,
43        pub phantom: PhantomData<U>
44    }
45}
46impl<T: Future<Output: JsCast>, U: JsCast> Future for Cast<T, U> {
47    type Output = U;
48
49    fn poll(
50        self: core::pin::Pin<&mut Self>,
51        cx: &mut core::task::Context<'_>,
52    ) -> core::task::Poll<Self::Output> {
53        self.project().value.poll(cx).map(|a| a.unchecked_into())
54    }
55}