1use crate::{macros::trace, Runtime, Tree};
2use slotmap::Key;
3use std::{
4 task::{Poll, Waker},
5 time::{Duration, Instant},
6};
7
8pub struct VirtualDom<T> {
10 cx: Runtime,
11 tree: T,
12}
13
14impl<T> VirtualDom<T> {
15 pub fn new(tree: T) -> Self {
17 VirtualDom {
18 cx: Runtime::default(),
19 tree,
20 }
21 }
22
23 pub fn build(&mut self)
25 where
26 T: Tree,
27 {
28 self.cx.enter();
29
30 unsafe { self.tree.build() }
32 }
33
34 pub async fn rebuild(&mut self) {
36 futures::future::poll_fn(|cx| {
37 self.try_rebuild_with_limit_inner(None, Some(cx.waker().clone()));
38
39 Poll::Pending
40 })
41 .await
42 }
43
44 pub async fn rebuild_with_limit(&mut self, limit: Duration) {
45 futures::future::poll_fn(|cx| {
46 let instant = Instant::now() + limit;
47 self.try_rebuild_with_limit_inner(Some(instant), Some(cx.waker().clone()));
48 Poll::Pending
49 })
50 .await
51 }
52
53 pub fn try_rebuild(&mut self) {
54 self.try_rebuild_with_limit_inner(None, None)
55 }
56
57 pub fn try_rebuild_with_limit(&mut self, limit: Duration) {
58 let instant = Instant::now() + limit;
59 self.try_rebuild_with_limit_inner(Some(instant), None)
60 }
61
62 fn try_rebuild_with_limit_inner(&mut self, limit: Option<Instant>, waker: Option<Waker>) {
63 let mut inner = self.cx.inner.borrow_mut();
64 inner.limit = limit;
65 inner.waker = waker;
66
67 if let Some(key) = inner.pending.pop_front() {
68 trace!("Received rebuild event for {:?}", key.data());
69
70 if let Some(raw) = inner.nodes.get(key).copied() {
71 drop(inner);
72
73 self.cx.enter();
74
75 unsafe { (&mut *raw).build() };
77 }
78 }
79 }
80}