forked from Roflin/gamenight
99 lines
2.2 KiB
Rust
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))
|
|
}
|
|
} |