diff options
| author | troido <troido@protonmail.com> | 2020-04-08 18:03:44 +0200 |
|---|---|---|
| committer | troido <troido@protonmail.com> | 2020-04-08 18:03:44 +0200 |
| commit | 15da8ce3af4e943939d6976ccfe5c46785638c7e (patch) | |
| tree | 96d63166d3a0914cf84b635417049310b6741bfa /src/persistence.rs | |
| parent | 950e15f7f7bbf354399c0d710ff8fb195a941e92 (diff) | |
don't ignore loading errors anymore
Diffstat (limited to 'src/persistence.rs')
| -rw-r--r-- | src/persistence.rs | 82 |
1 files changed, 56 insertions, 26 deletions
diff --git a/src/persistence.rs b/src/persistence.rs index b97f857..1174ceb 100644 --- a/src/persistence.rs +++ b/src/persistence.rs @@ -2,6 +2,7 @@ use std::path::{PathBuf, Path}; use std::fs; use std::env; +use std::io::ErrorKind; use serde_json; use serde_json::{Value, json}; use crate::{ @@ -10,19 +11,30 @@ use crate::{ savestate::SaveState, playerstate::PlayerState, Timestamp, - Result, - aerr + aerr, + errors::AnyError }; + +pub enum LoaderError { + MissingResource(AnyError), + InvalidResource(AnyError) +} + +macro_rules! inv { + ($code:expr) => {($code).map_err(|err| LoaderError::InvalidResource(Box::new(err)))} +} + + pub trait PersistentStorage { - fn load_room(&self, id: RoomId) -> Result<SaveState>; - fn load_player(&self, id: PlayerId) -> Result<PlayerState>; - fn load_world_meta(&self) -> Result<Timestamp>; + fn load_room(&self, id: RoomId) -> Result<SaveState, LoaderError>; + fn load_player(&self, id: PlayerId) -> Result<PlayerState, LoaderError>; + fn load_world_meta(&self) -> Result<Timestamp, LoaderError>; - fn save_room(&self, id: RoomId, state: SaveState) -> Result<()>; - fn save_player(&self, id: PlayerId, sate: PlayerState) -> Result<()>; - fn save_world_meta(&self, time: Timestamp) -> Result<()>; + fn save_room(&self, id: RoomId, state: SaveState) -> Result<(), AnyError>; + fn save_player(&self, id: PlayerId, sate: PlayerState) -> Result<(), AnyError>; + fn save_world_meta(&self, time: Timestamp) -> Result<(), AnyError>; } @@ -56,43 +68,61 @@ impl FileStorage { impl PersistentStorage for FileStorage { - fn load_room(&self, id: RoomId) -> Result<SaveState> { + fn load_room(&self, id: RoomId) -> Result<SaveState, LoaderError> { let mut path = self.directory.clone(); path.push("rooms"); let fname = id.to_string() + ".save.json"; path.push(fname); - let text = fs::read_to_string(path)?; - let json: Value = serde_json::from_str(&text)?; - let state = SaveState::from_json(&json)?; + let text = fs::read_to_string(path).map_err(|err| { + if err.kind() == ErrorKind::NotFound { + LoaderError::MissingResource(Box::new(err)) + } else { + LoaderError::InvalidResource(Box::new(err)) + } + })?; + let json: Value = inv!(serde_json::from_str(&text))?; + let state = inv!(SaveState::from_json(&json))?; Ok(state) } - fn load_player(&self, id: PlayerId) -> Result<PlayerState> { + fn load_player(&self, id: PlayerId) -> Result<PlayerState, LoaderError> { let mut path = self.directory.clone(); path.push("players"); let fname = id.to_string() + ".save.json"; path.push(fname); - let text = fs::read_to_string(path)?; - let json: Value = serde_json::from_str(&text)?; - let state = PlayerState::from_json(&json)?; + let text = fs::read_to_string(path).map_err(|err| { + if err.kind() == ErrorKind::NotFound { + LoaderError::MissingResource(Box::new(err)) + } else { + LoaderError::InvalidResource(Box::new(err)) + } + })?; + let json: Value = inv!(serde_json::from_str(&text))?; + let state = inv!(PlayerState::from_json(&json))?; Ok(state) } - fn load_world_meta(&self) -> Result<Timestamp> { + fn load_world_meta(&self) -> Result<Timestamp, LoaderError> { let mut path = self.directory.clone(); path.push("world.save.json"); - let text = fs::read_to_string(path)?; - let json: Value = serde_json::from_str(&text)?; + let text = fs::read_to_string(path).map_err(|err| { + if err.kind() == ErrorKind::NotFound { + LoaderError::MissingResource(Box::new(err)) + } else { + LoaderError::InvalidResource(Box::new(err)) + } + })?; + let json: Value = inv!(serde_json::from_str(&text))?; Ok( Timestamp( - json - .get("steps").ok_or(aerr!("world data does not have steps"))? - .as_i64().ok_or(aerr!("timestamp not an int"))? + inv!(inv!(json + .get("steps").ok_or(aerr!("world data does not have steps")))? + .as_i64().ok_or(aerr!("timestamp not an int")))? ) ) } - fn save_room(&self, id: RoomId, state: SaveState) -> Result<()> { + fn save_room(&self, id: RoomId, state: SaveState) -> Result<(), AnyError> { let mut path = self.directory.clone(); path.push("rooms"); fs::create_dir_all(&path)?; @@ -103,7 +133,7 @@ impl PersistentStorage for FileStorage { Ok(()) } - fn save_player(&self, id: PlayerId, state: PlayerState) -> Result<()> { + fn save_player(&self, id: PlayerId, state: PlayerState) -> Result<(), AnyError> { let mut path = self.directory.clone(); path.push("players"); fs::create_dir_all(&path)?; @@ -114,7 +144,7 @@ impl PersistentStorage for FileStorage { Ok(()) } - fn save_world_meta(&self, time: Timestamp) -> Result<()> { + fn save_world_meta(&self, time: Timestamp) -> Result<(), AnyError> { let mut path = self.directory.clone(); fs::create_dir_all(&path)?; path.push("world.save.json"); @@ -123,7 +153,7 @@ impl PersistentStorage for FileStorage { } } -fn write_file_safe<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<()> { +fn write_file_safe<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<(), AnyError> { let temppath = path .as_ref() .with_file_name( |
