diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/encyclopedia.rs | 3 | ||||
| -rw-r--r-- | src/item.rs | 2 | ||||
| -rw-r--r-- | src/parameter.rs | 2 | ||||
| -rw-r--r-- | src/persistence.rs | 5 | ||||
| -rw-r--r-- | src/pos.rs | 6 | ||||
| -rw-r--r-- | src/roomtemplate.rs | 58 | ||||
| -rw-r--r-- | src/savestate.rs | 76 | ||||
| -rw-r--r-- | src/template.rs | 71 |
8 files changed, 63 insertions, 160 deletions
diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs index 70f0ac6..8acd7e9 100644 --- a/src/encyclopedia.rs +++ b/src/encyclopedia.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use serde_json::{Value, json}; +use serde::Deserialize; use crate::{ assemblage::Assemblage, componentwrapper::PreEntity, @@ -59,7 +60,7 @@ impl Encyclopedia { name: name.clone(), ent: if let Some(ent) = v.get("entity") { - Template::from_json(ent)? + Template::deserialize(ent).map_err(|e| perr!("template json error deserializing {:?} {:?}", ent, e))? } else { let enttyp = EntityType(k.clone()); assemblages.insert(enttyp.clone(), Assemblage::from_json(&json!({ diff --git a/src/item.rs b/src/item.rs index 0abf35d..a663634 100644 --- a/src/item.rs +++ b/src/item.rs @@ -51,7 +51,7 @@ impl ItemAction { Some(match typ.as_str()? { "eat" => Eat(arg.as_i64()?), "build" => Build( - Template::from_json(arg.get(0)?).ok()?, + Template::deserialize(arg.get(0)?).ok()?, arg.get(1)?.as_array()?.iter().map(|v| Flag::from_str(v.as_str()?).ok()).collect::<Option<HashSet<Flag>>>()?, arg.get(2)?.as_array()?.iter().map(|v| Flag::from_str(v.as_str()?).ok()).collect::<Option<HashSet<Flag>>>()? ), diff --git a/src/parameter.rs b/src/parameter.rs index c307a27..6facc40 100644 --- a/src/parameter.rs +++ b/src/parameter.rs @@ -69,7 +69,7 @@ parameters!( Int (i64) int, v (v.as_i64().ok_or(perr!("{:?} not an int", v))?) (json!(v)); Pos (Pos) pos, v (Pos::from_json(v).ok_or(perr!("{:?} not a pos", v))?) (json!(v)); Float (f64) float, v (v.as_f64().ok_or(perr!("{:?} not an float", v))?) (json!(v)); - Template (Template) template, v (Template::from_json(v)?) (json!(["template", v.to_json()])); + Template (Template) template, v (Template::deserialize(v).map_err(|e| perr!("template json error {:?}", e))?) (json!(["template", v])); Bool (bool) bool, v (v.as_bool().ok_or(perr!("{:?} not a bool", v))?) (json!(v)); List (Vec<Parameter>) list, v ({ diff --git a/src/persistence.rs b/src/persistence.rs index 2d927ee..932840a 100644 --- a/src/persistence.rs +++ b/src/persistence.rs @@ -81,8 +81,7 @@ impl PersistentStorage for FileStorage { LoaderError::InvalidResource(Box::new(err)) } })?; - let json: Value = inv!(serde_json::from_str(&text))?; - let state = inv!(SaveState::from_json(&json))?; + let state = inv!(serde_json::from_str(&text))?; Ok(state) } @@ -129,7 +128,7 @@ impl PersistentStorage for FileStorage { fs::create_dir_all(&path)?; let fname = id.to_string() + ".save.json"; path.push(fname); - let text = state.to_json().to_string(); + let text = serde_json::to_string(&state).unwrap(); write_file_safe(path, text)?; Ok(()) } @@ -47,15 +47,13 @@ impl Pos { impl Serialize for Pos { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where S: Serializer, - { + where S: Serializer { (self.x, self.y).serialize(serializer) } } impl<'de> Deserialize<'de> for Pos { fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where D: Deserializer<'de>, - { + where D: Deserializer<'de> { let (x, y) = <(i64, i64)>::deserialize(deserializer)?; Ok(Self{x, y}) } diff --git a/src/roomtemplate.rs b/src/roomtemplate.rs index 7110e64..7f25291 100644 --- a/src/roomtemplate.rs +++ b/src/roomtemplate.rs @@ -1,12 +1,9 @@ use std::collections::HashMap; -use serde_json::{json, Value, value}; use serde::{Deserialize, Deserializer, de, Serialize}; use crate::{ Pos, Template, - PResult, - perr, resources::RoomPermissions }; @@ -65,61 +62,6 @@ impl<'de> Deserialize<'de> for RoomTemplate { } } -impl RoomTemplate { - - pub fn from_json(jsonroom: &Value) -> PResult<RoomTemplate>{ - let size = ( - jsonroom.get("width").ok_or(perr!("no width"))?.as_i64().ok_or(perr!("width not a number"))?, - jsonroom.get("height").ok_or(perr!("no height"))?.as_i64().ok_or(perr!("height not a number"))? - ); - let spawn = Pos::from_json(jsonroom.get("spawn").ok_or(perr!("no spawn"))?).ok_or(perr!("spawn not a pos"))?; - - let mut mapping = HashMap::new(); - for (key, value) in jsonroom.get("mapping").ok_or(perr!("no mapping"))?.as_object().ok_or(perr!("mapping not a json object"))?.iter() { - let mut templates: Vec<Template> = Vec::new(); - if value.is_array() { - for template in value.as_array().unwrap() { - templates.push(Template::from_json(template)?); - } - } else { - templates.push(Template::from_json(value)?); - } - mapping.insert(key.chars().next().ok_or(perr!("mapping key is empty string"))?, templates); - } - - let width = size.0 as usize; - let height = size.1 as usize; - let mut field = Vec::new(); - field.resize_with(width * height, Vec::new); - let jsonfield: &Vec<Value> = jsonroom.get("field").ok_or(perr!("no field"))?.as_array().ok_or(perr!("field not an array"))?; - for (y, row) in jsonfield.iter().take(height).enumerate() { - for (x, ch) in row.as_str().ok_or(perr!("field row not a string"))?.chars().take(width).enumerate() { - field[x + y * width] = mapping.get(&ch).ok_or(perr!("char not found in mapping"))?.clone(); - } - } - - let mut places = HashMap::new(); - for (name, jsonpos) in jsonroom.get("places").unwrap_or(&json!({})).as_object().ok_or(perr!("places not an object"))? { - places.insert(name.to_string(), Pos::from_json(jsonpos).ok_or(perr!("pos of places invalid"))?); - } - - let permissions: RoomPermissions = value::from_value::<RoomPermissions>( - jsonroom - .get("permissions") - .unwrap_or(&json!({})) - .clone() - ).map_err(|e| perr!("can't deserialise permissions: {:?}", e))?; - - Ok(RoomTemplate { - size, - spawn, - field, - places, - permissions - }) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/savestate.rs b/src/savestate.rs index 95f8d84..a81235f 100644 --- a/src/savestate.rs +++ b/src/savestate.rs @@ -1,13 +1,14 @@ use std::collections::HashMap; -use serde_json::{json, Value}; +use serde::{Serialize, Deserialize, Serializer, Deserializer}; + use crate::{ Pos, Template, - PResult, - perr }; + +#[derive(Debug, Clone, PartialEq)] pub struct SaveState { pub changes: HashMap<Pos, Vec<Template>> } @@ -19,27 +20,58 @@ impl SaveState { changes: HashMap::new() } } +} + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +struct SaveStateVec {pub changes: Vec<(Pos, Vec<Template>)>} + +impl Serialize for SaveState { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where S: Serializer { + SaveStateVec{changes: self.changes.clone().into_iter().collect()}.serialize(serializer) + } +} +impl<'de> Deserialize<'de> for SaveState { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where D: Deserializer<'de> { + Ok(Self{changes: SaveStateVec::deserialize(deserializer)?.changes.into_iter().collect()}) + } +} + +#[cfg(test)] +mod tests{ + use super::*; + use crate::hashmap; - pub fn to_json(&self) -> Value { - json!({ - "changes": self.changes.iter().map( - |(pos, templates)| - (pos, templates.iter().map(|t| t.to_json()).collect()) - ).collect::<Vec<(&Pos, Vec<Value>)>>() - }) + #[test] + fn test_empty_deserialize(){ + assert_eq!(SaveState::deserialize(json!({"changes":[]})).unwrap(), SaveState::new()); } - pub fn from_json(val: &Value) -> PResult<Self> { - let mut changes = HashMap::new(); - for v in val.get("changes").ok_or(perr!("save does not have changes"))?.as_array().ok_or(perr!("changes not an array"))? { - let pos = Pos::from_json(v.get(0).ok_or(perr!("change does not have index 0"))?).ok_or(perr!("change index 0 is not a pos"))?; - let mut templates = Vec::new(); - let jsontemplates = v.get(1).ok_or(perr!("change does not have index 1"))?; - for t in jsontemplates.as_array().clone().unwrap_or(&vec![jsontemplates.clone()]) { - templates.push(Template::from_json(t)?); - } - changes.entry(pos).or_insert_with(Vec::new).append(&mut templates); - } - Ok(Self {changes}) + #[test] + fn test_empty_serialize(){ + assert_eq!(serde_json::to_value(SaveState::new()).unwrap(), json!({"changes":[]})); + } + + + #[test] + fn test_change_serialize(){ + assert_eq!( + serde_json::to_value( + SaveState{changes: hashmap!{Pos::new(5,2) => vec![Template::empty("grass"), Template::empty("tree")]}} + ).unwrap(), + json!({"changes":[[[5,2],["grass", "tree"]]]}) + ); + } + + #[test] + fn test_changes_deserialize(){ + assert_eq!( + SaveState::deserialize(json!({"changes":[[[1,1],["grass"]], [[5,2],["grass", "tree"]]]})).unwrap(), + SaveState{changes: hashmap!{ + Pos::new(1,1) => vec![Template::empty("grass")], + Pos::new(5,2) => vec![Template::empty("grass"), Template::empty("tree")] + }} + ); } } diff --git a/src/template.rs b/src/template.rs index da758b6..66d58b9 100644 --- a/src/template.rs +++ b/src/template.rs @@ -1,45 +1,22 @@ use std::collections::HashMap; -use serde_json::{json, Value}; use serde::{Serialize, Deserialize}; use crate::{ parameter::Parameter, - PResult, - perr }; #[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)] pub struct EntityType(pub String); -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)] -#[serde(from="Option<bool>", into="Option<bool>")] +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] pub enum SaveOption { Default, False, Always } -impl From<Option<bool>> for SaveOption { - fn from(b: Option<bool>) -> Self { - match b { - Some(true) => Self::Always, - Some(false) => Self::False, - None => Self::Default - } - } -} -impl Into<Option<bool>> for SaveOption { - fn into(self) -> Option<bool> { - match self { - Self::Always => Some(true), - Self::False => Some(false), - Self::Default => None - } - } -} - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(untagged)] enum TemplateSave { @@ -143,52 +120,6 @@ impl Template { } self } - - pub fn from_json(v: &Value) -> PResult<Template> { - let val = match v { - Value::String(s) => json!({"type": s}), - Value::Array(_) => json!({ - "type": v.get(0).ok_or(perr!("index 0 not in template array {:?}", v))?, - "kwargs": v.get(1).ok_or(perr!("index 1 not in template array {:?}", v))? - }), - Value::Object(_) => v.clone(), - _ => return Err(perr!("invalid template {:?}", v)) - }; - - let name = EntityType(val.get("type").ok_or(perr!("template doesn't have 'type'"))?.as_str().ok_or(perr!("template type not a string"))?.to_string()); - let mut args = Vec::new(); - for arg in val.get("args").unwrap_or(&json!([])).as_array().ok_or(perr!("template args not an array"))? { - args.push(Parameter::guess_from_json(arg)?); - } - let mut kwargs = HashMap::new(); - for (key, arg) in val.get("kwargs").unwrap_or(&json!({})).as_object().ok_or(perr!("template kwargs not a json object"))? { - kwargs.insert(key.to_string(), Parameter::guess_from_json(arg)?); - } - let save = - if let Some(saveval) = val.get("save") { - if saveval.as_bool().ok_or(perr!("save not a bool"))? { - SaveOption::Always - } else { - SaveOption::False - } - } else { - SaveOption::Default - }; - Ok(Template {name, args, kwargs, save}) - } - - pub fn to_json(&self) -> Value { - if self.args.is_empty() && self.kwargs.is_empty() { - return json!(self.name.0); - } - let jsonargs: Vec<Value> = self.args.iter().map(|a| a.to_json()).collect(); - let jsonkwargs: HashMap<&String, Value> = self.kwargs.iter().map(|(k, a)| (k, a.to_json())).collect(); - json!({ - "type": self.name.0, - "args": jsonargs, - "kwargs": jsonkwargs - }) - } } #[cfg(test)] |
