use crate::launchpad::wiring::configuration::DefaultConfigurationWiring;
use crate::launchpad::wiring::preflight::DefaultPreflightWiring;
use crate::launchpad::wiring::runtime::DefaultRuntimeWiring;
use crate::{ConfigurationWiring, PreflightWiring, RuntimeWiring};
use strut_config::AssemblerChoices;
use strut_core::{AppContext, AppSpindown};
use tokio::select;
pub mod wiring {
pub mod configuration;
pub mod preflight;
pub mod runtime;
}
pub struct Launchpad<Main>
where
Main: Future<Output = ()>,
{
async_main: Main,
configuration_choices: AssemblerChoices,
configuration_wiring: Box<dyn ConfigurationWiring>,
runtime_wiring: Box<dyn RuntimeWiring>,
preflight_wiring: Box<dyn PreflightWiring>,
}
impl<Main> Launchpad<Main>
where
Main: Future<Output = ()>,
{
pub fn new(async_main: Main) -> Self {
Self {
async_main,
configuration_choices: AssemblerChoices::default(),
configuration_wiring: Box::new(DefaultConfigurationWiring),
runtime_wiring: Box::new(DefaultRuntimeWiring),
preflight_wiring: Box::new(DefaultPreflightWiring),
}
}
}
impl<Main> Launchpad<Main>
where
Main: Future<Output = ()>,
{
pub fn with_config_dir(self, name: impl Into<String>) -> Self {
Self {
configuration_choices: AssemblerChoices {
dir_name: Some(name.into()),
..self.configuration_choices
},
..self
}
}
pub fn with_env(self, enabled: bool) -> Self {
Self {
configuration_choices: AssemblerChoices {
env_enabled: enabled,
..self.configuration_choices
},
..self
}
}
pub fn with_env_prefix(self, prefix: impl Into<String>) -> Self {
Self {
configuration_choices: AssemblerChoices {
env_prefix: Some(prefix.into()),
..self.configuration_choices
},
..self
}
}
pub fn with_env_separator(self, separator: impl Into<String>) -> Self {
Self {
configuration_choices: AssemblerChoices {
env_separator: Some(separator.into()),
..self.configuration_choices
},
..self
}
}
pub fn with_configuration_wiring<W>(self, configuration_wiring: W) -> Self
where
W: ConfigurationWiring + 'static,
{
let configuration_wiring = Box::new(configuration_wiring);
Self {
configuration_wiring,
..self
}
}
pub fn with_runtime_wiring<S>(self, runtime_wiring: S) -> Self
where
S: RuntimeWiring + 'static,
{
let runtime_wiring = Box::new(runtime_wiring);
Self {
runtime_wiring,
..self
}
}
pub fn with_preflight_wiring<W>(self, preflight_wiring: W) -> Self
where
W: PreflightWiring + 'static,
{
let preflight_wiring = Box::new(preflight_wiring);
Self {
preflight_wiring,
..self
}
}
}
impl<Main> Launchpad<Main>
where
Main: Future<Output = ()>,
{
pub fn boot(self) {
let config = self.configuration_wiring.run(&self.configuration_choices);
let runtime = self.runtime_wiring.run(config);
self.preflight_wiring.run(config, &runtime);
runtime.block_on(self.run_async_main());
}
async fn run_async_main(self) {
select! {
biased;
_ = AppContext::terminated() => {},
_ = self.async_main => {},
}
AppContext::terminate();
AppSpindown::completed().await;
}
}