use serde::{
Deserialize,
Serialize
};
use std::fs::{
self,
File
};
use crate::{
base::PrependErrorString,
play::automaton::Automaton,
sys::System
};
const STATE_DIRPATH: &str = "state";
const STATE_FILENAME: &str = "state.json";
#[derive(Serialize, Deserialize)]
pub struct State {
#[serde(skip, default="def_automaton")] pub automaton: Option<Automaton>,
pub playtime: i128, }
fn def_automaton() -> Option<Automaton> {
None
}
fn file_exists(filepath: impl ToString) -> bool {
let filepath = filepath.to_string();
match File::open(&filepath) {
Ok(_) => true,
Err(_) => false
}
}
impl State {
pub fn load_or_new_default(sys: &System) -> Result<Self, String> {
let state_filepath = format!("{}/{}", STATE_DIRPATH, STATE_FILENAME);
if file_exists(&state_filepath) {
let json = fs::read(&state_filepath).pre_err(format!("cannot read from '{}'", &state_filepath))?;
let mut state: Self = serde_json::from_slice(&json).pre_err(format!("cannot deserialize '{}' to state", &state_filepath))?;
state.automaton = match Automaton::load(STATE_DIRPATH) {
Ok(automaton) => Some(automaton),
_ => {
Some(Automaton::new_default(sys))
}
};
Ok(state)
} else {
Ok(Self{
automaton: Some(Automaton::new_default(sys)),
playtime: 0
})
}
}
pub fn save(&self) -> Result<(), String> {
fs::create_dir_all(STATE_DIRPATH).unwrap_or(());
if let Some(automaton) = & self.automaton {
automaton.save(STATE_DIRPATH)?;
}
let state_filepath = format!("{}/{}", STATE_DIRPATH, STATE_FILENAME);
let json = serde_json::to_vec_pretty(self).pre_err("cannot serialize state")?;
fs::write(&state_filepath, &json).pre_err(format!("cannot write to '{}'", &state_filepath))?;
Ok(())
}
}