Skip to content
Snippets Groups Projects
Unverified Commit dfe84584 authored by Alejandro Perea's avatar Alejandro Perea Committed by GitHub
Browse files

Better errors (#152)

* Close #124

* Add `TiledError::InvalidEncodingFormat`

* Rename `DecompressingError` to `IoError`

* Add `InvalidPropertyValue` & `UnknownPropertyType`

* Remove `Other`

* Remove `ParseTileError`

* Misc comment improvements

* Revert  `IoError` back to `DecompressingError`
- Use `CouldNotOpenFile` for `Map`

* Address PR comments
parent bb77240f
No related branches found
No related tags found
No related merge requests found
use std::{fmt, path::PathBuf}; use std::{fmt, path::PathBuf};
#[derive(Debug, Copy, Clone)]
pub enum ParseTileError {
ColorError,
OrientationError,
}
/// Errors which occured when parsing the file /// Errors which occured when parsing the file
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive]
pub enum TiledError { pub enum TiledError {
/// A attribute was missing, had the wrong type of wasn't formated /// A attribute was missing, had the wrong type of wasn't formated
/// correctly. /// correctly.
...@@ -31,7 +26,19 @@ pub enum TiledError { ...@@ -31,7 +26,19 @@ pub enum TiledError {
}, },
/// There was an invalid tile in the map parsed. /// There was an invalid tile in the map parsed.
InvalidTileFound, InvalidTileFound,
Other(String), /// Unknown encoding or compression format or invalid combination of both (for tile layers)
InvalidEncodingFormat {
encoding: Option<String>,
compression: Option<String>,
},
/// There was an error parsing the value of a [`PropertyValue`].
///
/// [`PropertyValue`]: crate::PropertyValue
InvalidPropertyValue{description: String},
/// Found an unknown property value type while parsing a [`PropertyValue`].
///
/// [`PropertyValue`]: crate::PropertyValue
UnknownPropertyType{name: String},
} }
impl fmt::Display for TiledError { impl fmt::Display for TiledError {
...@@ -62,12 +69,26 @@ impl fmt::Display for TiledError { ...@@ -62,12 +69,26 @@ impl fmt::Display for TiledError {
) )
} }
TiledError::InvalidTileFound => write!(fmt, "Invalid tile found in map being parsed"), TiledError::InvalidTileFound => write!(fmt, "Invalid tile found in map being parsed"),
TiledError::Other(s) => write!(fmt, "{}", s), TiledError::InvalidEncodingFormat { encoding: None, compression: None } =>
write!(
fmt,
"Deprecated combination of encoding and compression"
),
TiledError::InvalidEncodingFormat { encoding, compression } =>
write!(
fmt,
"Unknown encoding or compression format or invalid combination of both (for tile layers): {} encoding with {} compression",
encoding.as_deref().unwrap_or("no"),
compression.as_deref().unwrap_or("no")
),
TiledError::InvalidPropertyValue{description} =>
write!(fmt, "Invalid property value: {}", description),
TiledError::UnknownPropertyType { name } =>
write!(fmt, "Unknown property value type '{}'", name),
} }
} }
} }
// This is a skeleton implementation, which should probably be extended in the future.
impl std::error::Error for TiledError { impl std::error::Error for TiledError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self { match self {
......
...@@ -10,18 +10,18 @@ pub(crate) fn parse_data_line( ...@@ -10,18 +10,18 @@ pub(crate) fn parse_data_line(
parser: &mut impl Iterator<Item = XmlEventResult>, parser: &mut impl Iterator<Item = XmlEventResult>,
tilesets: &[MapTilesetGid], tilesets: &[MapTilesetGid],
) -> Result<Vec<Option<LayerTileData>>, TiledError> { ) -> Result<Vec<Option<LayerTileData>>, TiledError> {
match (encoding, compression) { match (encoding.as_deref(), compression.as_deref()) {
(None, None) => { (Some("base64"), None) => {
return Err(TiledError::Other( return parse_base64(parser).map(|v| convert_to_tiles(&v, tilesets))
"XML format is currently not supported".to_string(),
))
} }
(Some(e), None) => match e.as_ref() { (Some("csv"), None) => return decode_csv(parser, tilesets),
"base64" => return parse_base64(parser).map(|v| convert_to_tiles(&v, tilesets)), (Some(_), None) => {
"csv" => return decode_csv(parser, tilesets), return Err(TiledError::InvalidEncodingFormat {
e => return Err(TiledError::Other(format!("Unknown encoding format {}", e))), encoding,
}, compression,
(Some(e), Some(c)) => match (e.as_ref(), c.as_ref()) { })
}
(Some(e), Some(c)) => match (e, c) {
("base64", "zlib") => { ("base64", "zlib") => {
return parse_base64(parser) return parse_base64(parser)
.and_then(decode_zlib) .and_then(decode_zlib)
...@@ -38,14 +38,19 @@ pub(crate) fn parse_data_line( ...@@ -38,14 +38,19 @@ pub(crate) fn parse_data_line(
.and_then(decode_zstd) .and_then(decode_zstd)
.map(|v| convert_to_tiles(&v, tilesets)) .map(|v| convert_to_tiles(&v, tilesets))
} }
(e, c) => { _ => {
return Err(TiledError::Other(format!( return Err(TiledError::InvalidEncodingFormat {
"Unknown combination of {} encoding and {} compression", encoding,
e, c compression,
))) })
} }
}, },
_ => return Err(TiledError::Other("Missing encoding format".to_string())), _ => {
return Err(TiledError::InvalidEncodingFormat {
encoding,
compression,
})
}
}; };
} }
......
...@@ -3,7 +3,7 @@ use std::{collections::HashMap, fmt, fs::File, io::Read, path::Path, rc::Rc, str ...@@ -3,7 +3,7 @@ use std::{collections::HashMap, fmt, fs::File, io::Read, path::Path, rc::Rc, str
use xml::{attribute::OwnedAttribute, reader::XmlEvent, EventReader}; use xml::{attribute::OwnedAttribute, reader::XmlEvent, EventReader};
use crate::{ use crate::{
error::{ParseTileError, TiledError}, error::TiledError,
layers::{LayerData, LayerTag}, layers::{LayerData, LayerTag},
properties::{parse_properties, Color, Properties}, properties::{parse_properties, Color, Properties},
tileset::Tileset, tileset::Tileset,
...@@ -90,8 +90,10 @@ impl Map { ...@@ -90,8 +90,10 @@ impl Map {
path: impl AsRef<Path>, path: impl AsRef<Path>,
cache: &mut impl ResourceCache, cache: &mut impl ResourceCache,
) -> Result<Self, TiledError> { ) -> Result<Self, TiledError> {
let reader = File::open(path.as_ref()) let reader = File::open(path.as_ref()).map_err(|err| TiledError::CouldNotOpenFile {
.map_err(|_| TiledError::Other(format!("Map file not found: {:?}", path.as_ref())))?; path: path.as_ref().to_owned(),
err,
})?;
Self::parse_reader(reader, path.as_ref(), cache) Self::parse_reader(reader, path.as_ref(), cache)
} }
} }
...@@ -268,15 +270,15 @@ pub enum Orientation { ...@@ -268,15 +270,15 @@ pub enum Orientation {
} }
impl FromStr for Orientation { impl FromStr for Orientation {
type Err = ParseTileError; type Err = ();
fn from_str(s: &str) -> Result<Orientation, ParseTileError> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s { match s {
"orthogonal" => Ok(Orientation::Orthogonal), "orthogonal" => Ok(Orientation::Orthogonal),
"isometric" => Ok(Orientation::Isometric), "isometric" => Ok(Orientation::Isometric),
"staggered" => Ok(Orientation::Staggered), "staggered" => Ok(Orientation::Staggered),
"hexagonal" => Ok(Orientation::Hexagonal), "hexagonal" => Ok(Orientation::Hexagonal),
_ => Err(ParseTileError::OrientationError), _ => Err(()),
} }
} }
} }
......
...@@ -74,32 +74,39 @@ impl PropertyValue { ...@@ -74,32 +74,39 @@ impl PropertyValue {
match property_type.as_str() { match property_type.as_str() {
"bool" => match value.parse() { "bool" => match value.parse() {
Ok(val) => Ok(PropertyValue::BoolValue(val)), Ok(val) => Ok(PropertyValue::BoolValue(val)),
Err(err) => Err(TiledError::Other(err.to_string())), Err(err) => Err(TiledError::InvalidPropertyValue {
description: err.to_string(),
}),
}, },
"float" => match value.parse() { "float" => match value.parse() {
Ok(val) => Ok(PropertyValue::FloatValue(val)), Ok(val) => Ok(PropertyValue::FloatValue(val)),
Err(err) => Err(TiledError::Other(err.to_string())), Err(err) => Err(TiledError::InvalidPropertyValue {
description: err.to_string(),
}),
}, },
"int" => match value.parse() { "int" => match value.parse() {
Ok(val) => Ok(PropertyValue::IntValue(val)), Ok(val) => Ok(PropertyValue::IntValue(val)),
Err(err) => Err(TiledError::Other(err.to_string())), Err(err) => Err(TiledError::InvalidPropertyValue {
description: err.to_string(),
}),
}, },
"color" if value.len() > 1 => match u32::from_str_radix(&value[1..], 16) { "color" if value.len() > 1 => match u32::from_str_radix(&value[1..], 16) {
Ok(color) => Ok(PropertyValue::ColorValue(color)), Ok(color) => Ok(PropertyValue::ColorValue(color)),
Err(_) => Err(TiledError::Other(format!( Err(err) => Err(TiledError::InvalidPropertyValue {
"Improperly formatted color property" description: err.to_string(),
))), }),
}, },
"string" => Ok(PropertyValue::StringValue(value)), "string" => Ok(PropertyValue::StringValue(value)),
"object" => match value.parse() { "object" => match value.parse() {
Ok(val) => Ok(PropertyValue::ObjectValue(val)), Ok(val) => Ok(PropertyValue::ObjectValue(val)),
Err(err) => Err(TiledError::Other(err.to_string())), Err(err) => Err(TiledError::InvalidPropertyValue {
description: err.to_string(),
}),
}, },
"file" => Ok(PropertyValue::FileValue(value)), "file" => Ok(PropertyValue::FileValue(value)),
_ => Err(TiledError::Other(format!( _ => Err(TiledError::UnknownPropertyType {
"Unknown property type \"{}\"", name: property_type,
property_type }),
))),
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment