winit/platform_impl/web/async/
wrapper.rs1use super::super::main_thread::MainThreadMarker;
2use std::cell::{Ref, RefCell};
3use std::future::Future;
4use std::marker::PhantomData;
5use std::sync::Arc;
6
7pub struct Wrapper<V: 'static, S: Clone + Send, E> {
10 value: Value<V>,
11 handler: fn(&RefCell<Option<V>>, E),
12 sender_data: S,
13 sender_handler: fn(&S, E),
14}
15
16struct Value<V> {
17 value: Arc<RefCell<Option<V>>>,
25 local: PhantomData<*const ()>,
27}
28
29unsafe impl<V> Send for Value<V> {}
31unsafe impl<V> Sync for Value<V> {}
33
34impl<V, S: Clone + Send, E> Wrapper<V, S, E> {
35 #[track_caller]
36 pub fn new<R: Future<Output = ()>>(
37 _: MainThreadMarker,
38 value: V,
39 handler: fn(&RefCell<Option<V>>, E),
40 receiver: impl 'static + FnOnce(Arc<RefCell<Option<V>>>) -> R,
41 sender_data: S,
42 sender_handler: fn(&S, E),
43 ) -> Option<Self> {
44 let value = Arc::new(RefCell::new(Some(value)));
45
46 wasm_bindgen_futures::spawn_local({
47 let value = Arc::clone(&value);
48 async move {
49 receiver(Arc::clone(&value)).await;
50 drop(value.borrow_mut().take().unwrap());
51 }
52 });
53
54 Some(Self {
55 value: Value { value, local: PhantomData },
56 handler,
57 sender_data,
58 sender_handler,
59 })
60 }
61
62 pub fn send(&self, event: E) {
63 if MainThreadMarker::new().is_some() {
64 (self.handler)(&self.value.value, event)
65 } else {
66 (self.sender_handler)(&self.sender_data, event)
67 }
68 }
69
70 pub fn value(&self) -> Option<Ref<'_, V>> {
71 MainThreadMarker::new()
72 .map(|_| Ref::map(self.value.value.borrow(), |value| value.as_ref().unwrap()))
73 }
74
75 pub fn with_sender_data<T>(&self, f: impl FnOnce(&S) -> T) -> T {
76 f(&self.sender_data)
77 }
78}
79
80impl<V, S: Clone + Send, E> Clone for Wrapper<V, S, E> {
81 fn clone(&self) -> Self {
82 Self {
83 value: Value { value: self.value.value.clone(), local: PhantomData },
84 handler: self.handler,
85 sender_data: self.sender_data.clone(),
86 sender_handler: self.sender_handler,
87 }
88 }
89}