summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/encyclopedia.rs3
-rw-r--r--src/item.rs2
-rw-r--r--src/parameter.rs2
-rw-r--r--src/persistence.rs5
-rw-r--r--src/pos.rs6
-rw-r--r--src/roomtemplate.rs58
-rw-r--r--src/savestate.rs76
-rw-r--r--src/template.rs71
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(())
}
diff --git a/src/pos.rs b/src/pos.rs
index 4c0d9cc..355ba74 100644
--- a/src/pos.rs
+++ b/src/pos.rs
@@ -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)]