use std::fmt::Debug;
use std::process::ExitCode;
use id_effect::{Effect, TracingConfig, install_tracing_layer, runtime::run_blocking};
use crate::exit_code_for_result;
#[derive(Clone, Debug)]
pub struct RunMainConfig {
pub install_tracing: bool,
}
impl RunMainConfig {
#[inline]
pub fn minimal() -> Self {
Self {
install_tracing: false,
}
}
#[inline]
pub fn with_tracing() -> Self {
Self {
install_tracing: true,
}
}
}
#[inline]
pub fn run_main<A, E, R>(effect: Effect<A, E, R>, env: R, config: RunMainConfig) -> ExitCode
where
A: 'static,
E: 'static + Debug,
R: 'static,
{
if config.install_tracing {
let _ = run_blocking(install_tracing_layer(TracingConfig::enabled()), ());
}
let result = run_blocking(effect, env);
if let Err(ref e) = result {
eprintln!("error: {e:?}");
}
exit_code_for_result(result)
}
#[cfg(test)]
mod tests {
use super::*;
use id_effect::{fail, succeed};
mod run_main {
use super::*;
#[test]
fn with_success_returns_success_exit_code() {
let code = run_main(succeed::<u8, (), ()>(9), (), RunMainConfig::minimal());
assert_eq!(code, ExitCode::SUCCESS);
}
#[test]
fn with_failure_returns_nonzero_exit_code() {
let code = run_main(fail::<u8, &str, ()>("boom"), (), RunMainConfig::minimal());
assert_eq!(code, ExitCode::from(1u8));
}
#[test]
fn with_tracing_flag_does_not_panic_on_success() {
let code = run_main(succeed::<(), (), ()>(()), (), RunMainConfig::with_tracing());
assert_eq!(code, ExitCode::SUCCESS);
}
}
}