Skip to main content

blitz_script/
application_document.rs

1use std::sync::Arc;
2use std::task::Context;
3
4use blitz_dom::{DocGuard, DocGuardMut, Document, DocumentConfig};
5use blitz_traits::events::UiEvent;
6
7use crate::ScriptDocument;
8
9#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
10pub enum ScriptBackend {
11    #[default]
12    Boa,
13    Custom,
14}
15
16/// A document backend selected before bootstrap or host installation.
17pub trait ScriptDocumentBackend: Document + Sized {
18    fn from_html(html: Arc<str>, config: DocumentConfig) -> Result<Self, String>;
19    fn execute_scripts(&mut self) -> Result<(), String>;
20}
21
22impl ScriptDocumentBackend for ScriptDocument {
23    fn from_html(html: Arc<str>, config: DocumentConfig) -> Result<Self, String> {
24        Ok(Self::from_html(&html, config))
25    }
26
27    fn execute_scripts(&mut self) -> Result<(), String> {
28        Self::execute_scripts(self);
29        Ok(())
30    }
31}
32
33/// Selection happens before either backend's bootstrap or host installers.
34pub enum ApplicationDocument<D: ScriptDocumentBackend = ScriptDocument> {
35    Boa(Box<ScriptDocument>),
36    Custom(Box<D>),
37}
38
39impl<D: ScriptDocumentBackend> ApplicationDocument<D> {
40    pub fn from_html(
41        html: Arc<str>,
42        config: DocumentConfig,
43        backend: ScriptBackend,
44    ) -> Result<Self, String> {
45        match backend {
46            ScriptBackend::Boa => Ok(Self::Boa(Box::new(ScriptDocument::from_html(
47                &html, config,
48            )))),
49            ScriptBackend::Custom => {
50                D::from_html(html, config).map(|document| Self::Custom(Box::new(document)))
51            }
52        }
53    }
54
55    pub fn backend(&self) -> ScriptBackend {
56        match self {
57            Self::Boa(_) => ScriptBackend::Boa,
58            Self::Custom(_) => ScriptBackend::Custom,
59        }
60    }
61
62    pub fn execute_scripts(&mut self) -> Result<(), String> {
63        match self {
64            Self::Boa(document) => {
65                document.execute_scripts();
66                Ok(())
67            }
68            Self::Custom(document) => document.execute_scripts(),
69        }
70    }
71}
72
73impl<D: ScriptDocumentBackend> Document for ApplicationDocument<D> {
74    fn inner(&self) -> DocGuard<'_> {
75        match self {
76            Self::Boa(document) => document.inner(),
77            Self::Custom(document) => document.inner(),
78        }
79    }
80    fn inner_mut(&mut self) -> DocGuardMut<'_> {
81        match self {
82            Self::Boa(document) => document.inner_mut(),
83            Self::Custom(document) => document.inner_mut(),
84        }
85    }
86    fn handle_ui_event(&mut self, event: UiEvent) {
87        match self {
88            Self::Boa(document) => document.handle_ui_event(event),
89            Self::Custom(document) => document.handle_ui_event(event),
90        }
91    }
92    fn poll(&mut self, context: Option<Context>) -> bool {
93        match self {
94            Self::Boa(document) => document.poll(context),
95            Self::Custom(document) => document.poll(context),
96        }
97    }
98    fn poll_for_settle(&mut self, context: Option<Context>, timers: bool) -> bool {
99        match self {
100            Self::Boa(document) => document.poll_for_settle(context, timers),
101            Self::Custom(document) => document.poll_for_settle(context, timers),
102        }
103    }
104}