diff options
| author | troido <troido@protonmail.com> | 2020-02-17 01:14:03 +0100 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-02-17 01:14:03 +0100 |
| commit | 625ab5bb37cbe35fd9662a33bc92f73520e59c81 (patch) | |
| tree | 7117152d2f530d794efd0b139919e041a807020f /src | |
| parent | ca74aa2bb61eb55d1257747edff38f1bad7641c1 (diff) | |
added trait for interacting with persistent storage; tried to make Results easier
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/persistence.rs | 77 | ||||
| -rw-r--r-- | src/playerstate.rs | 2 | ||||
| -rw-r--r-- | src/util.rs | 43 |
4 files changed, 121 insertions, 2 deletions
diff --git a/src/main.rs b/src/main.rs index 92912c2..4301a07 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ mod savestate; mod defaultencyclopedia; mod playerstate; mod playerid; +mod persistence; pub use self::pos::Pos; pub use self::playerid::PlayerId; diff --git a/src/persistence.rs b/src/persistence.rs new file mode 100644 index 0000000..fc04378 --- /dev/null +++ b/src/persistence.rs @@ -0,0 +1,77 @@ + +use std::path::PathBuf; +use std::fs; +use serde_json; +use serde_json::Value; +use crate::{ + PlayerId, + savestate::SaveState, + playerstate::PlayerState, + util::Result, + aerr +}; + +pub trait PersistentStorage { + + fn load_room(&self, name: String) -> Result<SaveState>; + + fn load_player(&self, id: PlayerId) -> Result<PlayerState>; + + fn save_room(&self, name: String, state: SaveState) -> Result<()>; + + fn save_player(&self, id: PlayerId, sate: PlayerState) -> Result<()>; + +} + + +pub struct FileStorage { + directory: PathBuf +} + +impl PersistentStorage for FileStorage { + + fn load_room(&self, name: String) -> Result<SaveState> { + let mut path = self.directory.clone(); + path.push("rooms"); + let fname = name + ".save.json"; + path.push(fname); + let text = fs::read_to_string(path)?; + let json: Value = serde_json::from_str(&text)?; + SaveState::from_json(&json).ok_or(aerr!("not a valid save state")) + } + + fn load_player(&self, id: PlayerId) -> Result<PlayerState> { + let mut path = self.directory.clone(); + path.push("players"); + let fname = id.name + ".save.json"; + path.push(fname); + let text = fs::read_to_string(path)?; + let json: Value = serde_json::from_str(&text)?; + PlayerState::from_json(&json).ok_or(aerr!("not a valid save state")) + } + + fn save_room(&self, name: String, state: SaveState) -> Result<()> { + let mut path = self.directory.clone(); + path.push("rooms"); + fs::create_dir_all(&path)?; + let fname = name + ".save.json"; + path.push(fname); + let text = state.to_json().to_string(); + // todo: write to a temp file first + fs::write(path, text)?; + Ok(()) + } + + fn save_player(&self, id: PlayerId, state: PlayerState) -> Result<()> { + let mut path = self.directory.clone(); + path.push("players"); + fs::create_dir_all(&path)?; + let fname = id.name + ".save.json"; + path.push(fname); + let text = state.to_json().to_string(); + // todo: write to a temp file first + fs::write(path, text)?; + Ok(()) + } +} + diff --git a/src/playerstate.rs b/src/playerstate.rs index b9a7f1f..dac463b 100644 --- a/src/playerstate.rs +++ b/src/playerstate.rs @@ -43,7 +43,7 @@ impl PlayerState { }) } - pub fn from_json(val: Value) -> Option<Self> { + pub fn from_json(val: &Value) -> Option<Self> { let inventory = val.get("inventory")?; let mut items = vec![]; for item in inventory.get("items")?.as_array()? { diff --git a/src/util.rs b/src/util.rs index 34d5670..1aee8a4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,5 +1,6 @@ - +use std::error::Error; +use std::fmt::{Display, Formatter}; use std::cmp::{min, max}; use serde_json::Value; @@ -12,6 +13,46 @@ pub trait ToJson { } +pub type AnyError = Box<dyn Error + 'static>; +pub type Result<T> = std::result::Result<T, AnyError>; + +#[derive(Debug)] +pub struct AError { + text: String +} + +impl AError { + pub fn new(txt: &str) -> Self{ + AError { + text: txt.to_string() + } + } +} + +impl Error for AError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + None + } +} + +impl Display for AError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "Error: {}", self.text) + } +} + + +#[macro_export] +macro_rules! aerr { + ($description:expr) => {Box::new(crate::util::AError::new($description))} +} + +#[macro_export] +macro_rules! err { + ($description:expr) => {Err(crate::aerr!($description))} +} + + #[macro_export] macro_rules! hashmap { ( $($key:expr => $value:expr ),* ) => {{ |
