summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortroido <troido@protonmail.com>2020-04-06 10:37:53 +0200
committertroido <troido@protonmail.com>2020-04-06 10:37:53 +0200
commite8d3e3c4f69fc5bab2b32b16b7c8c2c4a8a89a4b (patch)
tree67986bb0c0af1abe61dc9846d1a6c8c9b8e2c4b0
parentff457701ff56072914acb8a7160cd02c2a07095a (diff)
made parseerrors their own thing
-rw-r--r--src/assemblage.rs85
-rw-r--r--src/componentparameter.rs20
-rw-r--r--src/encyclopedia.rs31
-rw-r--r--src/errors.rs47
-rw-r--r--src/main.rs4
-rw-r--r--src/persistence.rs6
-rw-r--r--src/playerstate.rs44
-rw-r--r--src/room.rs5
-rw-r--r--src/roomtemplate.rs28
-rw-r--r--src/savestate.rs12
-rw-r--r--src/server/address.rs2
-rw-r--r--src/template.rs18
-rw-r--r--src/util.rs36
-rw-r--r--src/world.rs2
14 files changed, 187 insertions, 153 deletions
diff --git a/src/assemblage.rs b/src/assemblage.rs
index aa3154f..8f36556 100644
--- a/src/assemblage.rs
+++ b/src/assemblage.rs
@@ -8,7 +8,9 @@ use crate::{
components::Serialise,
Template,
Result,
- aerr
+ aerr,
+ PResult,
+ perr
};
type ArgumentDef = (String, ParameterType, Option<Parameter>);
@@ -24,18 +26,18 @@ pub struct Assemblage {
impl Assemblage {
- fn parse_definition_arguments(args: &Value) -> Result<Vec<ArgumentDef>> {
+ fn parse_definition_arguments(args: &Value) -> PResult<Vec<ArgumentDef>> {
let mut arguments: Vec<ArgumentDef> = Vec::new();
- for arg in args.as_array().ok_or(aerr!("arguments is not an array"))? {
- let tup = arg.as_array().ok_or(aerr!("argument is not an array"))?;
- let key = tup.get(0).ok_or(aerr!("argument has no name"))?.as_str().ok_or(aerr!("argument name is not a string"))?.to_string();
- let typ = ParameterType::from_str(tup.get(1).ok_or(aerr!("argument has no type"))?.as_str().ok_or(aerr!("argument type not a string"))?).ok_or(aerr!("failed to parse argument type"))?;
+ for arg in args.as_array().ok_or(perr!("arguments is not an array"))? {
+ let tup = arg.as_array().ok_or(perr!("argument is not an array"))?;
+ let key = tup.get(0).ok_or(perr!("argument has no name"))?.as_str().ok_or(perr!("argument name is not a string"))?.to_string();
+ let typ = ParameterType::from_str(tup.get(1).ok_or(perr!("argument has no type"))?.as_str().ok_or(perr!("argument type not a string"))?).ok_or(perr!("failed to parse argument type"))?;
if let Some(def) = tup.get(2){
arguments.push(
(
key.clone(),
typ,
- Some(Parameter::from_typed_json(typ, def).ok_or(aerr!("invalid argument default"))?)
+ Some(Parameter::from_typed_json(typ, def).ok_or(perr!("invalid argument default"))?)
)
);
} else {
@@ -45,18 +47,18 @@ impl Assemblage {
Ok(arguments)
}
- fn parse_definition_components(comps: &[Value]) -> Result<Vec<(ComponentType, HashMap<String, ComponentParameter>)>> {
+ fn parse_definition_components(comps: &[Value]) -> PResult<Vec<(ComponentType, HashMap<String, ComponentParameter>)>> {
let mut components = Vec::new();
for tup in comps {
if let Some(name) = tup.as_str() {
- components.push((ComponentType::from_str(name).ok_or(aerr!("not a valid componenttype"))?, HashMap::new()));
+ components.push((ComponentType::from_str(name).ok_or(perr!("not a valid componenttype"))?, HashMap::new()));
} else {
let comptype = ComponentType::from_str(tup
- .get(0).ok_or(aerr!("index 0 not in component"))?
- .as_str().ok_or(aerr!("component name not a string"))?
- ).ok_or("not a valid componenttype")?;
+ .get(0).ok_or(perr!("index 0 not in component"))?
+ .as_str().ok_or(perr!("component name not a string"))?
+ ).ok_or(perr!("not a valid componenttype"))?;
let mut parameters: HashMap<String, ComponentParameter> = HashMap::new();
- for (key, value) in tup.get(1).ok_or(aerr!("index 1 not in component"))?.as_object().ok_or(aerr!("component parameters not a json object"))? {
+ for (key, value) in tup.get(1).ok_or(perr!("index 1 not in component"))?.as_object().ok_or(perr!("component parameters not a json object"))? {
let param = ComponentParameter::from_json(value)?;
parameters.insert(key.clone(), param);
}
@@ -66,31 +68,19 @@ impl Assemblage {
Ok(components)
}
- fn validate(&self) -> Result<()> {
- for (comptype, parameters) in &self.components {
- for (paramname, paramtype) in comptype.parameters() {
- let param = parameters.get(paramname).ok_or(aerr!("missing parameter"))?;
- let actualtype = param.get_type(&self.arguments)?;
- if actualtype != paramtype {
- return Err(aerr!("parameter type incorrect"));
- }
- }
- }
- Ok(())
- }
- fn preprocess(val: &Value) -> Result<Vec<Value>> {
+ fn preprocess(val: &Value) -> PResult<Vec<Value>> {
let mut components = Vec::new();
let name = if let Some(nameval) = val.get("name") {
- Some(nameval.as_str().ok_or(aerr!("name not a string"))?.to_string())
+ Some(nameval.as_str().ok_or(perr!("name not a string"))?.to_string())
} else {None};
// visible component is so common that shortcuts are very helpful
if let Some(spritename) = val.get("sprite") {
- let sprite = spritename.as_str().ok_or(aerr!("sprite not a string"))?.to_string();
+ let sprite = spritename.as_str().ok_or(perr!("sprite not a string"))?.to_string();
let height = val
- .get("height").ok_or(aerr!("defining a sprite requires also defining a height"))?
- .as_f64().ok_or(aerr!("height not a float"))?;
+ .get("height").ok_or(perr!("defining a sprite requires also defining a height"))?
+ .as_f64().ok_or(perr!("height not a float"))?;
components.push(json!(["Visible", {
"name": ["string", name.clone().unwrap_or(sprite.clone())],
"sprite": ["string", sprite],
@@ -113,42 +103,55 @@ impl Assemblage {
Ok(components)
}
- pub fn from_json(val: &Value) -> Result<Self>{
+ pub fn from_json(val: &Value) -> PResult<Self>{
let mut json_components: Vec<Value> = val
.get("components")
.unwrap_or(&json!([]))
.as_array()
- .ok_or(aerr!("components is not a json array"))?
+ .ok_or(perr!("components is not a json array"))?
.to_vec();
json_components.append(&mut Self::preprocess(val)?);
let assemblage = Self {
arguments: Self::parse_definition_arguments(val.get("arguments").unwrap_or(&json!([])))?,
components: Self::parse_definition_components(&json_components)?,
- save: val.get("save").unwrap_or(&json!(true)).as_bool().ok_or(aerr!("assemblage save not a bool"))?,
+ save: val.get("save").unwrap_or(&json!(true)).as_bool().ok_or(perr!("assemblage save not a bool"))?,
extract: val
.get("extract")
.unwrap_or(&json!({}))
- .as_object().ok_or(aerr!("assemblage extract not a bool"))?
+ .as_object().ok_or(perr!("assemblage extract not a bool"))?
.into_iter()
.map(|(argname, val)| {
Ok((
argname.to_string(),
ComponentType::from_str(
val
- .get(0).ok_or(aerr!("index 0 not in extract value"))?
- .as_str().ok_or(aerr!("extract component name not a string"))?
- ).ok_or(aerr!("extract invalid component name"))?,
+ .get(0).ok_or(perr!("index 0 not in extract value"))?
+ .as_str().ok_or(perr!("extract component name not a string"))?
+ ).ok_or(perr!("extract invalid component name"))?,
val.get(1)
- .ok_or(aerr!("index 1 not in extract value"))?
- .as_str().ok_or(aerr!("extract member name not a string"))?.to_string()
+ .ok_or(perr!("index 1 not in extract value"))?
+ .as_str().ok_or(perr!("extract member name not a string"))?.to_string()
))
})
- .collect::<Result<Vec<(String, ComponentType, String)>>>()?
+ .collect::<PResult<Vec<(String, ComponentType, String)>>>()?
};
- assemblage.validate()?;
Ok(assemblage)
}
+
+ pub fn validate(&self) -> Result<()> {
+ for (comptype, parameters) in &self.components {
+ for (paramname, paramtype) in comptype.parameters() {
+ let param = parameters.get(paramname).ok_or(aerr!("missing parameter"))?;
+ let actualtype = param.get_type(&self.arguments)?;
+ if actualtype != paramtype {
+ return Err(aerr!("parameter type incorrect"));
+ }
+ }
+ }
+ Ok(())
+ }
+
fn prepare_arguments(&self, args: &[Parameter], kwargs: &HashMap<String, Parameter>) -> Result<HashMap<&str, Parameter>> {
let mut arguments: HashMap<&str, Parameter> = HashMap::new();
for (idx, (name, typ, def)) in self.arguments.iter().enumerate() {
diff --git a/src/componentparameter.rs b/src/componentparameter.rs
index 28e77ce..73c7b30 100644
--- a/src/componentparameter.rs
+++ b/src/componentparameter.rs
@@ -6,7 +6,9 @@ use crate::{
parameter::{Parameter, ParameterType},
Template,
Result,
- aerr
+ aerr,
+ PResult,
+ perr
};
const MAX_NESTING: usize = 5;
@@ -60,21 +62,21 @@ impl ComponentParameter {
}
}
- pub fn from_json(value: &Value) -> Result<Self> {
- let paramvalue = value.get(1).ok_or(aerr!("index 1 not in component parameter"))?;
- let typename = value.get(0).ok_or(aerr!("index 0 not in component parameter"))?.as_str().ok_or(aerr!("compparam type not a string"))?;
+ pub fn from_json(value: &Value) -> PResult<Self> {
+ let paramvalue = value.get(1).ok_or(perr!("index 1 not in component parameter"))?;
+ let typename = value.get(0).ok_or(perr!("index 0 not in component parameter"))?.as_str().ok_or(perr!("compparam type not a string"))?;
if let Some(paramtype) = ParameterType::from_str(typename) {
Ok(Self::Constant(Parameter::from_typed_json(paramtype, paramvalue).ok_or_else(||
- aerr!("failed to parse parameter constant: {:?} {:?}", paramtype, paramvalue)
+ perr!("failed to parse parameter constant: {:?} {:?}", paramtype, paramvalue)
)?))
} else {
match typename {
"A" | "arg" => {
- let argname = paramvalue.as_str().ok_or(aerr!("argument parameter not a string"))?.to_string();
+ let argname = paramvalue.as_str().ok_or(perr!("argument parameter not a string"))?.to_string();
Ok(Self::Argument(argname))
},
"random" => {
- let optionvalues = paramvalue.as_array().ok_or(aerr!("random argument not an array"))?;
+ let optionvalues = paramvalue.as_array().ok_or(perr!("random argument not an array"))?;
let mut options = Vec::new();
for option in optionvalues {
options.push(Self::from_json(option)?)
@@ -82,7 +84,7 @@ impl ComponentParameter {
Ok(Self::Random(options))
},
"concat" => {
- let values = paramvalue.as_array().ok_or(aerr!("concat argument not an array"))?;
+ let values = paramvalue.as_array().ok_or(perr!("concat argument not an array"))?;
let mut options = Vec::new();
for option in values {
options.push(Self::from_json(option)?)
@@ -91,7 +93,7 @@ impl ComponentParameter {
},
"self" => Ok(Self::TemplateSelf),
"name" => Ok(Self::TemplateName),
- _ => Err(aerr!("unknown compparam type '{}'", typename))
+ _ => Err(perr!("unknown compparam type '{}'", typename))
}
}
}
diff --git a/src/encyclopedia.rs b/src/encyclopedia.rs
index fe9a9d3..c378b84 100644
--- a/src/encyclopedia.rs
+++ b/src/encyclopedia.rs
@@ -10,7 +10,9 @@ use crate::{
aerr,
ItemId,
item::Item,
- item::ItemAction
+ item::ItemAction,
+ PResult,
+ perr
};
#[derive(Default, Clone)]
@@ -21,34 +23,34 @@ pub struct Encyclopedia {
impl Encyclopedia {
- pub fn from_json(val: Value) -> Result<Encyclopedia> {
+ pub fn from_json(val: Value) -> PResult<Encyclopedia> {
let mut assemblages =
val
.get("assemblages")
- .ok_or(aerr!("no assemblages in encyclopedia json"))?
+ .ok_or(perr!("no assemblages in encyclopedia json"))?
.as_object()
- .ok_or(aerr!("encyclopedia assemblages not a json object"))?
+ .ok_or(perr!("encyclopedia assemblages not a json object"))?
.into_iter()
.map(|(k, v)| Ok((EntityType(k.clone()), Assemblage::from_json(v)?)))
- .collect::<Result<HashMap<EntityType, Assemblage>>>()?;
+ .collect::<PResult<HashMap<EntityType, Assemblage>>>()?;
let items =
val
.get("items")
- .ok_or(aerr!("no items in encyclopedia json"))?
+ .ok_or(perr!("no items in encyclopedia json"))?
.as_object()
- .ok_or(aerr!("encyclopedia items not a json object"))?
+ .ok_or(perr!("encyclopedia items not a json object"))?
.into_iter()
.map(|(k, v)| {
let id = ItemId(k.clone());
let sprite =
if let Some(sprite) = v.get("sprite") {
- sprite.as_str().ok_or(aerr!("item sprite not a string: {:?}", v))?
+ sprite.as_str().ok_or(perr!("item sprite not a string: {:?}", v))?
} else {
k
};
let name =
if let Some(name) = v.get("name") {
- name.as_str().ok_or(aerr!("item name not a string: {:?}", v))?.to_string()
+ name.as_str().ok_or(perr!("item name not a string: {:?}", v))?.to_string()
} else {
k.to_string()
};
@@ -69,14 +71,14 @@ impl Encyclopedia {
},
action:
if let Some(action) = v.get("action") {
- ItemAction::from_json(action).ok_or(aerr!("failed to parse ItemAction: {:?}", v))?
+ ItemAction::from_json(action).ok_or(perr!("failed to parse ItemAction: {:?}", v))?
} else {
ItemAction::None
}
};
Ok((id, item))
})
- .collect::<Result<HashMap<ItemId, Item>>>()?;
+ .collect::<PResult<HashMap<ItemId, Item>>>()?;
Ok(Encyclopedia{
assemblages,
@@ -84,6 +86,13 @@ impl Encyclopedia {
})
}
+ pub fn validate(&self) -> Result<()> {
+ for assemblage in self.assemblages.values() {
+ assemblage.validate()?;
+ }
+ Ok(())
+ }
+
pub fn construct(&self, template: &Template) -> Result<PreEntity> {
let assemblage = self.assemblages
.get(&template.name)
diff --git a/src/errors.rs b/src/errors.rs
new file mode 100644
index 0000000..294159c
--- /dev/null
+++ b/src/errors.rs
@@ -0,0 +1,47 @@
+
+use std::error::Error;
+use std::fmt::{Display, Formatter};
+
+pub type AnyError = Box<dyn Error + 'static>;
+pub type Result<T> = std::result::Result<T, AnyError>;
+
+#[derive(Debug)]
+pub struct AError {
+ pub text: 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:tt)*) => {Box::new(crate::errors::AError{text: format!($($description)*)})}
+}
+
+
+
+#[derive(Debug)]
+pub struct ParseError {
+ pub text: String
+}
+impl Error for ParseError {
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ None
+ }
+}
+impl Display for ParseError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ write!(f, "Error: {}", self.text)
+ }
+}
+#[macro_export]
+macro_rules! perr {
+ ($($description:tt)*) => {crate::errors::ParseError{text: format!($($description)*)}}
+}
+pub type PResult<T> = std::result::Result<T, ParseError>;
diff --git a/src/main.rs b/src/main.rs
index 21d3ccc..8c2c716 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -37,13 +37,14 @@ mod purgatory;
mod config;
mod item;
mod exchange;
+mod errors;
use self::{
pos::Pos,
playerid::PlayerId,
roomid::RoomId,
item::ItemId,
- util::Result,
+ errors::{Result, PResult},
sprite::Sprite,
template::Template,
encyclopedia::Encyclopedia,
@@ -92,6 +93,7 @@ fn main() -> Result<()>{
)?
)?
)?;
+ encyclopedia.validate()?;
let save_dir = config.save_dir.unwrap_or(
FileStorage::default_save_dir().expect("couldn't find any save directory")
diff --git a/src/persistence.rs b/src/persistence.rs
index 9eb6e54..b97f857 100644
--- a/src/persistence.rs
+++ b/src/persistence.rs
@@ -63,7 +63,8 @@ impl PersistentStorage for FileStorage {
path.push(fname);
let text = fs::read_to_string(path)?;
let json: Value = serde_json::from_str(&text)?;
- SaveState::from_json(&json)
+ let state = SaveState::from_json(&json)?;
+ Ok(state)
}
fn load_player(&self, id: PlayerId) -> Result<PlayerState> {
@@ -73,7 +74,8 @@ impl PersistentStorage for FileStorage {
path.push(fname);
let text = fs::read_to_string(path)?;
let json: Value = serde_json::from_str(&text)?;
- PlayerState::from_json(&json)
+ let state = PlayerState::from_json(&json)?;
+ Ok(state)
}
fn load_world_meta(&self) -> Result<Timestamp> {
diff --git a/src/playerstate.rs b/src/playerstate.rs
index 9dec879..acc49ff 100644
--- a/src/playerstate.rs
+++ b/src/playerstate.rs
@@ -28,7 +28,9 @@ use crate::{
Sprite,
Encyclopedia,
Pos,
- hashmap
+ hashmap,
+ PResult,
+ perr
};
#[derive(Debug, Clone)]
@@ -99,44 +101,44 @@ impl PlayerState {
})
}
- pub fn from_json(val: &Value) -> Result<Self> {
- let inventory = val.get("inventory").ok_or(aerr!("player json does not have inventory"))?;
+ pub fn from_json(val: &Value) -> PResult<Self> {
+ let inventory = val.get("inventory").ok_or(perr!("player json does not have inventory"))?;
let items =
inventory
.get("items")
- .ok_or(aerr!("inventory does not have items"))?
+ .ok_or(perr!("inventory does not have items"))?
.as_array()
- .ok_or(aerr!("inventory items not an array"))?
+ .ok_or(perr!("inventory items not an array"))?
.into_iter()
.map(|entry| {
let itemid = ItemId(
entry
.get(0)
- .ok_or(aerr!("item does not have name"))?
+ .ok_or(perr!("item does not have name"))?
.as_str()
- .ok_or(aerr!("item name not a string"))?
+ .ok_or(perr!("item name not a string"))?
.to_string()
);
let is_equipped =
entry
.get(1)
- .ok_or(aerr!("item does not have equipped flag"))?
+ .ok_or(perr!("item does not have equipped flag"))?
.as_bool()
- .ok_or(aerr!("item is_equipped not a bool"))?;
+ .ok_or(perr!("item is_equipped not a bool"))?;
Ok((itemid, is_equipped))
})
- .collect::<Result<Vec<(ItemId, bool)>>>()?;
+ .collect::<PResult<Vec<(ItemId, bool)>>>()?;
Ok(Self {
- id: PlayerId{name: val.get("name").ok_or(aerr!("player json does not have name"))?.as_str().ok_or(aerr!("player name not a string"))?.to_string()},
- room: match val.get("roomname").ok_or(aerr!("player json does not have room name"))? {
+ id: PlayerId{name: val.get("name").ok_or(perr!("player json does not have name"))?.as_str().ok_or(perr!("player name not a string"))?.to_string()},
+ room: match val.get("roomname").ok_or(perr!("player json does not have room name"))? {
Value::String(name) => Some(RoomId::from_str(name)),
_ => None
},
pos: RoomPos::Unknown,
inventory: items,
- health: val.get("health").ok_or(aerr!("player json does not have health"))?.as_i64().ok_or(aerr!("player health not a number"))?,
- inventory_capacity: inventory.get("capacity").ok_or(aerr!("inventory does no have capacity"))?.as_i64().ok_or(aerr!("inventory capacity not a number"))? as usize,
- maximum_health: val.get("maxhealth").ok_or(aerr!("player json does not have maxhealth"))?.as_i64().ok_or(aerr!("maxhealth not a number"))?,
+ health: val.get("health").ok_or(perr!("player json does not have health"))?.as_i64().ok_or(perr!("player health not a number"))?,
+ inventory_capacity: inventory.get("capacity").ok_or(perr!("inventory does not have capacity"))?.as_i64().ok_or(perr!("inventory capacity not a number"))? as usize,
+ maximum_health: val.get("maxhealth").ok_or(perr!("player json does not have maxhealth"))?.as_i64().ok_or(perr!("maxhealth not a number"))?,
equipment: HashMap::new()
})
}
@@ -147,15 +149,15 @@ impl PlayerState {
self.health = self.maximum_health / 2;
}
- pub fn construct(&self, encyclopedia: &Encyclopedia) -> PreEntity {
- vec![
+ pub fn construct(&self, encyclopedia: &Encyclopedia) -> Result<PreEntity> {
+ Ok(vec![
ComponentWrapper::Visible(Visible{sprite: Sprite{name: "player".to_string()}, height: 1.75, name: self.id.name.clone()}),
ComponentWrapper::Player(Player::new(self.id.clone())),
ComponentWrapper::Inventory(Inventory{
items: self.inventory.iter().map( |(itemid, is_equipped)| {
- let item = encyclopedia.get_item(itemid).unwrap();
- InventoryEntry{itemid: itemid.clone(), item, is_equipped: *is_equipped}
- }).collect(),
+ let item = encyclopedia.get_item(itemid).ok_or(aerr!("failed to load item '{:?} in inventory of player {:?}", itemid, self))?;
+ Ok(InventoryEntry{itemid: itemid.clone(), item, is_equipped: *is_equipped})
+ }).collect::<Result<Vec<InventoryEntry>>>()?,
capacity: self.inventory_capacity
}),
ComponentWrapper::Health(Health{health: self.health, maxhealth: self.maximum_health}),
@@ -166,6 +168,6 @@ impl PlayerState {
ComponentWrapper::Faction(Faction::Good),
ComponentWrapper::Equipment(Equipment{slots: vec!(Slot::Hand, Slot::Body)}),
ComponentWrapper::Ear(Ear::default())
- ]
+ ])
}
}
diff --git a/src/room.rs b/src/room.rs
index 46948cb..bc5b651 100644
--- a/src/room.rs
+++ b/src/room.rs
@@ -181,14 +181,15 @@ impl <'a, 'b>Room<'a, 'b> {
self.world.fetch_mut::<Input>().actions.insert(player, control);
}
- pub fn add_player(&mut self, state: &PlayerState){
- let pre_player = state.construct(&self.world.fetch::<NewEntities>().encyclopedia);
+ pub fn add_player(&mut self, state: &PlayerState) -> Result<()> {
+ let pre_player = state.construct(&self.world.fetch::<NewEntities>().encyclopedia)?;
let spawn = match &state.pos {
RoomPos::Unknown => self.world.fetch::<SpawnPosition>().pos,
RoomPos::Pos(pos) => *pos,
RoomPos::Name(name) => *self.places.get(name).unwrap()
};
self.world.fetch_mut::<NewEntities>().to_build.push((spawn, pre_player));
+ Ok(())
}
pub fn remove_player(&mut self, id: &PlayerId) -> Result<PlayerState>{
diff --git a/src/roomtemplate.rs b/src/roomtemplate.rs
index b5834e9..da4d3a5 100644
--- a/src/roomtemplate.rs
+++ b/src/roomtemplate.rs
@@ -4,8 +4,8 @@ use serde_json::{json, Value};
use crate::{
Pos,
Template,
- Result,
- aerr
+ PResult,
+ perr
};
#[derive(Debug, Clone)]
@@ -18,39 +18,39 @@ pub struct RoomTemplate {
impl RoomTemplate {
- pub fn from_json(jsonroom: &Value) -> Result<RoomTemplate>{
+ pub fn from_json(jsonroom: &Value) -> PResult<RoomTemplate>{
let size = (
- jsonroom.get("width").ok_or("no with")?.as_i64().ok_or("with not a number")?,
- jsonroom.get("height").ok_or("no height")?.as_i64().ok_or("height not a number")?
+ jsonroom.get("width").ok_or(perr!("no with"))?.as_i64().ok_or(perr!("with 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("no spawn")?).ok_or("spawn not a pos")?;
+ 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("no mapping")?.as_object().ok_or("mapping not a json object")?.iter() {
+ 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().ok_or("weird")? {
+ 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("mapping key is empty string")?, templates);
+ mapping.insert(key.chars().next().ok_or(perr!("mapping key is empty string"))?, templates);
}
let mut field = Vec::new();
field.resize((size.0 * size.1) as usize, Vec::new());
- let jsonfield: &Vec<Value> = jsonroom.get("field").ok_or("no field")?.as_array().ok_or("field not an array")?;
+ let jsonfield: &Vec<Value> = jsonroom.get("field").ok_or(perr!("no field"))?.as_array().ok_or(perr!("field not an array"))?;
// todo: what if size doesn't match actual dimensions
for (y, row) in jsonfield.iter().enumerate() {
- for (x, ch) in row.as_str().ok_or("field row not a string")?.chars().enumerate() {
- field[x + y * (size.0 as usize)] = mapping.get(&ch).ok_or(aerr!("char not found in mapping"))?.clone();
+ for (x, ch) in row.as_str().ok_or(perr!("field row not a string"))?.chars().enumerate() {
+ field[x + y * (size.0 as usize)] = 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("places not an object")? {
- places.insert(name.to_string(), Pos::from_json(jsonpos).ok_or("pos of places invalid")?);
+ 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"))?);
}
Ok(RoomTemplate {
diff --git a/src/savestate.rs b/src/savestate.rs
index 2992531..4482fca 100644
--- a/src/savestate.rs
+++ b/src/savestate.rs
@@ -5,7 +5,9 @@ use crate::{
Pos,
Template,
Result,
- aerr
+ aerr,
+ PResult,
+ perr
};
pub struct SaveState {
@@ -29,12 +31,12 @@ impl SaveState {
})
}
- pub fn from_json(val: &Value) -> Result<Self> {
+ pub fn from_json(val: &Value) -> PResult<Self> {
let mut changes = HashMap::new();
- for v in val.get("changes").ok_or(aerr!("save does not have changes"))?.as_array().ok_or(aerr!("changes not an array"))? {
- let pos = Pos::from_json(v.get(0).ok_or(aerr!("change does not have index 0"))?).ok_or(aerr!("change index 0 is not a pos"))?;
+ 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();
- for t in v.get(1).ok_or(aerr!("change does not have index 1"))?.as_array().ok_or(aerr!("change index 1 not an array"))? {
+ for t in v.get(1).ok_or(perr!("change does not have index 1"))?.as_array().ok_or(perr!("change index 1 not an array"))? {
templates.push(Template::from_json(t)?);
}
changes.insert(pos, templates);
diff --git a/src/server/address.rs b/src/server/address.rs
index 1cf49ac..6256f41 100644
--- a/src/server/address.rs
+++ b/src/server/address.rs
@@ -5,7 +5,7 @@ use std::str::FromStr;
use crate::{
Result,
aerr,
- util::AnyError
+ errors::AnyError
};
use super::tcpserver::TcpServer;
use super::unixserver::UnixServer;
diff --git a/src/template.rs b/src/template.rs
index 0f62754..c2f905f 100644
--- a/src/template.rs
+++ b/src/template.rs
@@ -4,8 +4,8 @@ use std::collections::HashMap;
use serde_json::{json, Value};
use crate::{
parameter::Parameter,
- Result,
- aerr
+ PResult,
+ perr
};
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
@@ -49,20 +49,20 @@ impl Template {
self
}
- pub fn from_json(val: &Value) -> Result<Template> {
+ pub fn from_json(val: &Value) -> PResult<Template> {
if val.is_string(){
return Ok(Self::empty(val.as_str().unwrap()));
}
- let name = EntityType(val.get("type").ok_or(aerr!("template doesn't have 'type'"))?.as_str().ok_or(aerr!("template type not a string"))?.to_string());
+ 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(aerr!("template args not an array"))? {
- args.push(Parameter::guess_from_json(arg).ok_or(aerr!("template arg not a parameter"))?);
+ 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).ok_or(perr!("template arg not a parameter"))?);
}
let mut kwargs = HashMap::new();
- for (key, arg) in val.get("kwargs").unwrap_or(&json!({})).as_object().ok_or(aerr!("template kwargs not a json object"))? {
- kwargs.insert(key.to_string(), Parameter::guess_from_json(arg).ok_or(aerr!("template arg not a parameter"))?);
+ 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).ok_or(perr!("template arg not a parameter"))?);
}
- let save = val.get("save").unwrap_or(&json!(true)).as_bool().ok_or(aerr!("save not a bool"))?;
+ let save = val.get("save").unwrap_or(&json!(true)).as_bool().ok_or(perr!("save not a bool"))?;
Ok(Template {name, args, kwargs, save})
}
diff --git a/src/util.rs b/src/util.rs
index a5aca1a..c9557b2 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,46 +1,10 @@
-use std::error::Error;
-use std::fmt::{Display, Formatter};
use std::cmp::{min, max};
pub fn clamp<T: Ord>(val: T, lower: T, upper: T) -> T{
max(min(val, upper), lower)
}
-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:tt)*) => {Box::new(crate::util::AError::new(&format!($($description)*)))}
-}
-
#[macro_export]
macro_rules! hashmap {
diff --git a/src/world.rs b/src/world.rs
index 71a4eb7..6e59a5b 100644
--- a/src/world.rs
+++ b/src/world.rs
@@ -77,7 +77,7 @@ impl <'a, 'b>World<'a, 'b> {
fn add_loaded_player(&mut self, state: PlayerState) -> Result<()> {
let roomid = state.clone().room.unwrap_or_else(|| self.default_room.clone());
let room = self.get_room_mut(&roomid)?;
- room.add_player(&state);
+ room.add_player(&state)?;
self.players.insert(state.id, roomid);
Ok(())
}