2025-05-19 21:01:38 +02:00

99 lines
2.2 KiB
Rust

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<InquireError> for FlowError {
fn from(value: InquireError) -> Self {
Self {
error: value.to_string()
}
}
}
impl<T> From<gamenight_api_client_rs::apis::Error<T>> for FlowError {
fn from(value: gamenight_api_client_rs::apis::Error<T>) -> Self {
Self {
error: value.to_string()
}
}
}
impl From<ParseError> 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<dyn Flow<'a> + 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<Box<dyn Flow<'a> + 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))
}
}