use std::fmt::Display; use async_trait::async_trait; use chrono::ParseError; use gamenight_api_client_rs::apis::configuration::Configuration; use inquire::InquireError; use dyn_clone::DynClone; pub mod main; mod login; mod main_menu; mod exit; mod list_gamenights; mod add_gamenight; mod view_gamenight; pub struct GamenightState { configuration: Configuration, } impl GamenightState { pub fn new() -> Self{ Self { configuration: Configuration::new() } } } impl Default for GamenightState { fn default() -> Self { Self::new() } } #[derive(Debug)] pub struct FlowError { pub error: String } impl From for FlowError { fn from(value: InquireError) -> Self { Self { error: value.to_string() } } } impl From> for FlowError { fn from(value: gamenight_api_client_rs::apis::Error) -> Self { Self { error: value.to_string() } } } impl From for FlowError { fn from(value: ParseError) -> Self { Self { error: value.to_string() } } } #[derive(PartialEq)] pub enum FlowOutcome { Successful, Bool(bool), String(String), Abort } type FlowResult<'a> = Result<(FlowOutcome, &'a mut GamenightState), FlowError>; dyn_clone::clone_trait_object!(for<'a> Flow<'a>); #[async_trait] pub trait Flow<'a>: Sync + DynClone + Send + Display { async fn run(&self, state: &'a mut GamenightState) -> FlowResult<'a>; } async fn handle_choice<'a>(choice: &Box + Send>, flow: &dyn Flow<'a>, state: &'a mut GamenightState) -> FlowResult<'a> { let (outcome, new_state) = choice.run(state).await?; if outcome == FlowOutcome::Abort { Ok((FlowOutcome::Successful, new_state)) } else { flow.run(new_state).await } } async fn handle_choice_option<'a>(choice: &Option + Send>>, flow: &dyn Flow<'a>, state: &'a mut GamenightState) -> FlowResult<'a> { if let Some(choice) = choice { handle_choice(choice, flow, state).await } else { Ok((FlowOutcome::Abort, state)) } }