diff --git a/src/quest/error.rs b/src/quest/error.rs index 60c93f6..55ddbcf 100644 --- a/src/quest/error.rs +++ b/src/quest/error.rs @@ -10,8 +10,10 @@ pub enum QuestError { IsNotAFile(PathBuf), /// std::io::Error happenned when loading IoError(std::io::Error), + /// toml::ser::Error happened when loading + TomlSerializeError(toml::ser::Error), /// toml::de::Error happened when loading - TomlError(toml::de::Error) + TomlDeserializeError(toml::de::Error), } impl fmt::Display for QuestError { @@ -19,7 +21,8 @@ impl fmt::Display for QuestError { match self { QuestError::IsNotAFile(path) => write!(f, "{:?} is not a file", path), QuestError::IoError(error) => write!(f, "io error: {error}"), - QuestError::TomlError(error) => write!(f, "parse error: {error}") + QuestError::TomlSerializeError(error) => write!(f, "serialize error: {error}"), + QuestError::TomlDeserializeError(error) => write!(f, "parse error: {error}") } } } diff --git a/src/quest/mod.rs b/src/quest/mod.rs index 64607cb..d675cc1 100644 --- a/src/quest/mod.rs +++ b/src/quest/mod.rs @@ -2,7 +2,7 @@ pub mod error; -use std::path::PathBuf; +use std::{fs, io::Write, path::PathBuf}; use serde::{ Serialize, Deserialize }; use error::QuestError; @@ -76,15 +76,104 @@ impl Default for Quest { impl Quest { /// Parse quest TOML or return error + /// + /// # Examples + /// ```rust + /// use squad_quest::quest::{Quest,error::QuestError}; + /// # fn main() { + /// # let _ = wrapper(); + /// # } + /// + /// # fn wrapper() -> Result<(), QuestError> { + /// let path = "quests/0.toml".into(); + /// + /// let quest = Quest::load(path)?; + /// # + /// # Ok(()) + /// # } + /// ``` pub fn load(path: PathBuf) -> Result { match std::fs::read_to_string(path) { Ok(string) => { match toml::from_str::(&string) { Ok(quest) => Ok(quest), - Err(error) => Err(QuestError::TomlError(error)) + Err(error) => Err(QuestError::TomlDeserializeError(error)) } }, Err(error) => Err(QuestError::IoError(error)) } } + + /// Check if given file is a quest, then delete it or raise an error. + /// If file is not a quest, raises [QuestError::TomlDeserializeError] + /// + /// # Examples + /// ```rust + /// use squad_quest::quest::{Quest,error::QuestError}; + /// + /// let path = "quests/0.toml".into(); + /// + /// if let Err(error) = Quest::delete(path) { + /// // handle the error + /// } + /// ``` + pub fn delete(path: PathBuf) -> Result<(), QuestError> { + match Quest::load(path.clone()) { + Ok(_) => { + if let Err(error) = fs::remove_file(path) { + return Err(QuestError::IoError(error)); + } + + Ok(()) + }, + Err(error) => Err(error) + } + } + + /// Save quest to given folder in TOML format. + /// File will be saved as `{id}.toml`. + /// If file exists, this method will override it. + /// + /// # Examples + /// ```rust + /// # fn main() { + /// use squad_quest::quest::{Quest,error::QuestError}; + /// use std::path::PathBuf; + /// + /// let quest = Quest::default(); + /// + /// let path: PathBuf = "quests".into(); + /// # let path2 = path.clone(); + /// + /// if let Err(error) = quest.save(path) { + /// // handle the error + /// } + /// # let filename = format!("{}.toml", quest.id); + /// # let _ = Quest::delete(path2.with_file_name(filename)); + /// # } + /// ``` + pub fn save(&self, path: PathBuf) -> Result<(), QuestError> { + let filename = format!("{}.toml", self.id); + let full_path = path.with_file_name(filename); + + let str = match toml::to_string_pretty(&self) { + Ok(string) => string, + Err(error) => { + return Err(QuestError::TomlSerializeError(error)); + } + }; + + let mut file = match fs::File::create(full_path) { + Ok(f) => f, + Err(error) => { + return Err(QuestError::IoError(error)); + } + }; + + if let Err(error) = file.write_all(str.as_bytes()) { + return Err(QuestError::IoError(error)); + } + + Ok(()) + } }