diff --git a/src/animation.rs b/src/animation.rs index 2cf352c0..a1956ab3 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -3,7 +3,7 @@ use xml::attribute::OwnedAttribute; use crate::{ - error::TiledError, + error::{Error, Result}, util::{get_attrs, parse_tag, XmlEventResult}, }; @@ -20,14 +20,14 @@ pub struct Frame { } impl Frame { - pub(crate) fn new(attrs: Vec) -> Result { + pub(crate) fn new(attrs: Vec) -> Result { let (tile_id, duration) = get_attrs!( attrs, required: [ ("tileid", tile_id, |v:String| v.parse().ok()), ("duration", duration, |v:String| v.parse().ok()), ], - TiledError::MalformedAttributes("A frame must have tileid and duration".to_string()) + Error::MalformedAttributes("A frame must have tileid and duration".to_string()) ); Ok(Frame { tile_id: tile_id, @@ -38,7 +38,7 @@ impl Frame { pub(crate) fn parse_animation( parser: &mut impl Iterator, -) -> Result, TiledError> { +) -> Result> { let mut animation = Vec::new(); parse_tag!(parser, "animation", { "frame" => |attrs| { diff --git a/src/cache.rs b/src/cache.rs index 5c4a3303..de537361 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -15,13 +15,13 @@ pub type ResourcePathBuf = PathBuf; /// [`ResourcePath`] to prevent loading them more than once. pub trait ResourceCache { /// Obtains a tileset from the cache, if it exists. - /// + /// /// # Example /// ``` /// use std::fs::File; /// use tiled::{FilesystemResourceCache, ResourceCache, Tileset}; - /// # use tiled::TiledError; - /// # fn main() -> Result<(), TiledError> { + /// # use tiled::Result; + /// # fn main() -> Result<()> { /// let mut cache = FilesystemResourceCache::new(); /// let path = "assets/tilesheet.tsx"; /// @@ -32,7 +32,7 @@ pub trait ResourceCache { /// # } /// ``` fn get_tileset(&self, path: impl AsRef) -> Option>; - + /// Returns the tileset mapped to `path` if it exists, otherwise calls `f` and, depending on its /// result, it will: /// - Insert the object into the cache, if the result was [`Ok`]. diff --git a/src/error.rs b/src/error.rs index 1c82552a..b7fcbfa7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,7 +3,7 @@ use std::{fmt, path::PathBuf}; /// Errors which occured when parsing the file #[derive(Debug)] #[non_exhaustive] -pub enum TiledError { +pub enum Error { /// A attribute was missing, had the wrong type of wasn't formated /// correctly. MalformedAttributes(String), @@ -51,21 +51,24 @@ pub enum TiledError { }, } -impl fmt::Display for TiledError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { +/// A result with an error variant of [`tiled::error::Error`]. +pub type Result = std::result::Result; + +impl fmt::Display for Error { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> { match self { - TiledError::MalformedAttributes(s) => write!(fmt, "{}", s), - TiledError::DecompressingError(e) => write!(fmt, "{}", e), - TiledError::Base64DecodingError(e) => write!(fmt, "{}", e), - TiledError::XmlDecodingError(e) => write!(fmt, "{}", e), - TiledError::PrematureEnd(e) => write!(fmt, "{}", e), - TiledError::PathIsNotFile => { + Error::MalformedAttributes(s) => write!(fmt, "{}", s), + Error::DecompressingError(e) => write!(fmt, "{}", e), + Error::Base64DecodingError(e) => write!(fmt, "{}", e), + Error::XmlDecodingError(e) => write!(fmt, "{}", e), + Error::PrematureEnd(e) => write!(fmt, "{}", e), + Error::PathIsNotFile => { write!( fmt, "The path given is invalid because it isn't contained in any folder." ) } - TiledError::CouldNotOpenFile { path, err } => { + Error::CouldNotOpenFile { path, err } => { write!( fmt, "Could not open '{}'. Error: {}", @@ -73,34 +76,34 @@ impl fmt::Display for TiledError { err ) } - TiledError::InvalidTileFound => write!(fmt, "Invalid tile found in map being parsed"), - TiledError::InvalidEncodingFormat { encoding: None, compression: None } => + Error::InvalidTileFound => write!(fmt, "Invalid tile found in map being parsed"), + Error::InvalidEncodingFormat { encoding: None, compression: None } => write!( fmt, "Deprecated combination of encoding and compression" ), - TiledError::InvalidEncodingFormat { encoding, compression } => + Error::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} => + Error::InvalidPropertyValue{description} => write!(fmt, "Invalid property value: {}", description), - TiledError::UnknownPropertyType { type_name } => + Error::UnknownPropertyType { type_name } => write!(fmt, "Unknown property value type '{}'", type_name), } } } -impl std::error::Error for TiledError { +impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - TiledError::DecompressingError(e) => Some(e as &dyn std::error::Error), - TiledError::Base64DecodingError(e) => Some(e as &dyn std::error::Error), - TiledError::XmlDecodingError(e) => Some(e as &dyn std::error::Error), - TiledError::CouldNotOpenFile { err, .. } => Some(err as &dyn std::error::Error), + Error::DecompressingError(e) => Some(e as &dyn std::error::Error), + Error::Base64DecodingError(e) => Some(e as &dyn std::error::Error), + Error::XmlDecodingError(e) => Some(e as &dyn std::error::Error), + Error::CouldNotOpenFile { err, .. } => Some(err as &dyn std::error::Error), _ => None, } } diff --git a/src/image.rs b/src/image.rs index b0df041f..0264de03 100644 --- a/src/image.rs +++ b/src/image.rs @@ -2,7 +2,11 @@ use std::path::{Path, PathBuf}; use xml::attribute::OwnedAttribute; -use crate::{error::TiledError, properties::Color, util::*}; +use crate::{ + error::{Error, Result}, + properties::Color, + util::*, +}; /// A reference to an image stored somewhere within the filesystem. #[derive(Debug, PartialEq, Eq, Clone)] @@ -26,7 +30,7 @@ pub struct Image { /// use std::fs::File; /// use tiled::*; /// - /// # fn main() -> Result<(), Box> { + /// # fn main() -> std::result::Result<(), Box> { /// let map = Map::parse_file( /// "assets/folder/tiled_relative_paths.tmx", /// &mut FilesystemResourceCache::new(), @@ -78,7 +82,7 @@ impl Image { parser: &mut impl Iterator, attrs: Vec, path_relative_to: impl AsRef, - ) -> Result { + ) -> Result { let (c, (s, w, h)) = get_attrs!( attrs, optionals: [ @@ -89,10 +93,10 @@ impl Image { ("width", width, |v:String| v.parse().ok()), ("height", height, |v:String| v.parse().ok()), ], - TiledError::MalformedAttributes("Image must have a source, width and height with correct types".to_string()) + Error::MalformedAttributes("Image must have a source, width and height with correct types".to_string()) ); - parse_tag!(parser, "image", { }); + parse_tag!(parser, "image", {}); Ok(Image { source: path_relative_to.as_ref().join(s), width: w, diff --git a/src/layers/group.rs b/src/layers/group.rs index 0a4d8d25..39541ce1 100644 --- a/src/layers/group.rs +++ b/src/layers/group.rs @@ -2,12 +2,12 @@ use std::collections::HashMap; use std::path::Path; use crate::{ - error::TiledError, + error::Result, layers::{LayerData, LayerTag}, map::MapTilesetGid, properties::{parse_properties, Properties}, util::*, - Layer, Map, + Error, Layer, Map, }; #[derive(Debug, PartialEq, Clone)] @@ -21,7 +21,7 @@ impl GroupLayerData { infinite: bool, map_path: &Path, tilesets: &[MapTilesetGid], - ) -> Result<(Self, Properties), TiledError> { + ) -> Result<(Self, Properties)> { let mut properties = HashMap::new(); let mut layers = Vec::new(); parse_tag!(parser, "group", { diff --git a/src/layers/image.rs b/src/layers/image.rs index d8c8ae8d..26418a4a 100644 --- a/src/layers/image.rs +++ b/src/layers/image.rs @@ -2,8 +2,8 @@ use std::{collections::HashMap, path::Path}; use crate::{ parse_properties, - util::{parse_tag, XmlEventResult, map_wrapper}, - Image, Properties, TiledError, + util::{map_wrapper, parse_tag, XmlEventResult}, + Error, Image, Properties, Result, }; #[derive(Debug, PartialEq, Clone)] @@ -15,11 +15,11 @@ impl ImageLayerData { pub(crate) fn new( parser: &mut impl Iterator, map_path: &Path, - ) -> Result<(Self, Properties), TiledError> { + ) -> Result<(Self, Properties)> { let mut image: Option = None; let mut properties = HashMap::new(); - let path_relative_to = map_path.parent().ok_or(TiledError::PathIsNotFile)?; + let path_relative_to = map_path.parent().ok_or(Error::PathIsNotFile)?; parse_tag!(parser, "imagelayer", { "image" => |attrs| { diff --git a/src/layers/mod.rs b/src/layers/mod.rs index 5ce61b25..a2f95fae 100644 --- a/src/layers/mod.rs +++ b/src/layers/mod.rs @@ -2,7 +2,12 @@ use std::path::Path; use xml::attribute::OwnedAttribute; -use crate::{error::TiledError, properties::Properties, util::*, Color, Map, MapTilesetGid}; +use crate::{ + error::{Result}, + properties::Properties, + util::*, + Color, Map, MapTilesetGid, +}; mod image; pub use image::*; @@ -52,7 +57,7 @@ impl LayerData { infinite: bool, map_path: &Path, tilesets: &[MapTilesetGid], - ) -> Result { + ) -> Result { let (opacity, tint_color, visible, offset_x, offset_y, parallax_x, parallax_y, name, id) = get_attrs!( attrs, optionals: [ diff --git a/src/layers/object.rs b/src/layers/object.rs index 5939bfae..28093897 100644 --- a/src/layers/object.rs +++ b/src/layers/object.rs @@ -5,7 +5,7 @@ use xml::attribute::OwnedAttribute; use crate::{ parse_properties, util::{get_attrs, map_wrapper, parse_tag, XmlEventResult}, - Color, Map, MapTilesetGid, Object, ObjectData, Properties, TiledError, + Color, Error, Map, MapTilesetGid, Object, ObjectData, Properties, Result, }; /// Raw data referring to a map object layer or tile collision data. @@ -24,7 +24,7 @@ impl ObjectLayerData { parser: &mut impl Iterator, attrs: Vec, tilesets: Option<&[MapTilesetGid]>, - ) -> Result<(ObjectLayerData, Properties), TiledError> { + ) -> Result<(ObjectLayerData, Properties)> { let c = get_attrs!( attrs, optionals: [ diff --git a/src/layers/tile/finite.rs b/src/layers/tile/finite.rs index ca6f768c..ea2b0083 100644 --- a/src/layers/tile/finite.rs +++ b/src/layers/tile/finite.rs @@ -2,7 +2,7 @@ use xml::attribute::OwnedAttribute; use crate::{ util::{get_attrs, map_wrapper, XmlEventResult}, - LayerTile, LayerTileData, MapTilesetGid, TiledError, + LayerTile, LayerTileData, MapTilesetGid, Result, }; use super::util::parse_data_line; @@ -31,7 +31,7 @@ impl FiniteTileLayerData { width: u32, height: u32, tilesets: &[MapTilesetGid], - ) -> Result { + ) -> Result { let (e, c) = get_attrs!( attrs, optionals: [ @@ -65,7 +65,7 @@ map_wrapper!( impl<'map> FiniteTileLayer<'map> { /// Obtains the tile present at the position given. - /// + /// /// If the position given is invalid or the position is empty, this function will return [`None`]. pub fn get_tile(&self, x: i32, y: i32) -> Option { self.data diff --git a/src/layers/tile/infinite.rs b/src/layers/tile/infinite.rs index 39f5715a..7fd70d5b 100644 --- a/src/layers/tile/infinite.rs +++ b/src/layers/tile/infinite.rs @@ -4,7 +4,7 @@ use xml::attribute::OwnedAttribute; use crate::{ util::{floor_div, get_attrs, map_wrapper, parse_tag, XmlEventResult}, - LayerTile, LayerTileData, MapTilesetGid, TiledError, + Error, LayerTile, LayerTileData, MapTilesetGid, Result, }; use super::util::parse_data_line; @@ -25,7 +25,7 @@ impl InfiniteTileLayerData { parser: &mut impl Iterator, attrs: Vec, tilesets: &[MapTilesetGid], - ) -> Result { + ) -> Result { let (e, c) = get_attrs!( attrs, optionals: [ @@ -123,7 +123,7 @@ impl InternalChunk { encoding: Option, compression: Option, tilesets: &[MapTilesetGid], - ) -> Result { + ) -> Result { let (x, y, width, height) = get_attrs!( attrs, required: [ @@ -132,7 +132,7 @@ impl InternalChunk { ("width", width, |v: String| v.parse().ok()), ("height", height, |v: String| v.parse().ok()), ], - TiledError::MalformedAttributes("chunk must have x, y, width & height attributes".to_string()) + Error::MalformedAttributes("chunk must have x, y, width & height attributes".to_string()) ); let tiles = parse_data_line(encoding, compression, parser, tilesets)?; diff --git a/src/layers/tile/mod.rs b/src/layers/tile/mod.rs index c9746d72..83a018f5 100644 --- a/src/layers/tile/mod.rs +++ b/src/layers/tile/mod.rs @@ -5,7 +5,7 @@ use xml::attribute::OwnedAttribute; use crate::{ parse_properties, util::{get_attrs, map_wrapper, parse_tag, XmlEventResult}, - Gid, Map, MapTilesetGid, Properties, Tile, TileId, TiledError, Tileset, + Error, Gid, Map, MapTilesetGid, Properties, Result, Tile, TileId, Tileset, }; mod finite; @@ -74,14 +74,14 @@ impl TileLayerData { attrs: Vec, infinite: bool, tilesets: &[MapTilesetGid], - ) -> Result<(Self, Properties), TiledError> { + ) -> Result<(Self, Properties)> { let (width, height) = get_attrs!( attrs, required: [ ("width", width, |v: String| v.parse().ok()), ("height", height, |v: String| v.parse().ok()), ], - TiledError::MalformedAttributes("layer parsing error, width and height attributes required".to_string()) + Error::MalformedAttributes("layer parsing error, width and height attributes required".to_string()) ); let mut result = Self::Finite(Default::default()); let mut properties = HashMap::new(); @@ -174,7 +174,7 @@ impl<'map> TileLayer<'map> { } /// Obtains the tile present at the position given. - /// + /// /// If the position given is invalid or the position is empty, this function will return [`None`]. pub fn get_tile(&self, x: i32, y: i32) -> Option { match self { diff --git a/src/layers/tile/util.rs b/src/layers/tile/util.rs index fde41f23..88a44c01 100644 --- a/src/layers/tile/util.rs +++ b/src/layers/tile/util.rs @@ -2,14 +2,14 @@ use std::{convert::TryInto, io::Read}; use xml::reader::XmlEvent; -use crate::{util::XmlEventResult, LayerTileData, MapTilesetGid, TiledError}; +use crate::{util::XmlEventResult, Error, LayerTileData, MapTilesetGid, Result}; pub(crate) fn parse_data_line( encoding: Option, compression: Option, parser: &mut impl Iterator, tilesets: &[MapTilesetGid], -) -> Result>, TiledError> { +) -> Result>> { match (encoding.as_deref(), compression.as_deref()) { (Some("csv"), None) => decode_csv(parser, tilesets), @@ -25,18 +25,18 @@ pub(crate) fn parse_data_line( .and_then(|data| process_decoder(zstd::stream::read::Decoder::with_buffer(&data[..]))) .map(|v| convert_to_tiles(&v, tilesets)), - _ => Err(TiledError::InvalidEncodingFormat { + _ => Err(Error::InvalidEncodingFormat { encoding, compression, }), } } -fn parse_base64(parser: &mut impl Iterator) -> Result, TiledError> { +fn parse_base64(parser: &mut impl Iterator) -> Result> { while let Some(next) = parser.next() { - match next.map_err(TiledError::XmlDecodingError)? { + match next.map_err(Error::XmlDecodingError)? { XmlEvent::Characters(s) => { - return base64::decode(s.trim().as_bytes()).map_err(TiledError::Base64DecodingError) + return base64::decode(s.trim().as_bytes()).map_err(Error::Base64DecodingError) } XmlEvent::EndElement { name, .. } if name.local_name == "data" => { return Ok(Vec::new()); @@ -44,25 +44,25 @@ fn parse_base64(parser: &mut impl Iterator) -> Result {} } } - Err(TiledError::PrematureEnd("Ran out of XML data".to_owned())) + Err(Error::PrematureEnd("Ran out of XML data".to_owned())) } -fn process_decoder(decoder: std::io::Result) -> Result, TiledError> { +fn process_decoder(decoder: std::io::Result) -> Result> { decoder .and_then(|mut decoder| { let mut data = Vec::new(); decoder.read_to_end(&mut data)?; Ok(data) }) - .map_err(|e| TiledError::DecompressingError(e)) + .map_err(|e| Error::DecompressingError(e)) } fn decode_csv( parser: &mut impl Iterator, tilesets: &[MapTilesetGid], -) -> Result>, TiledError> { +) -> Result>> { while let Some(next) = parser.next() { - match next.map_err(TiledError::XmlDecodingError)? { + match next.map_err(Error::XmlDecodingError)? { XmlEvent::Characters(s) => { let tiles = s .split(',') @@ -77,7 +77,7 @@ fn decode_csv( _ => {} } } - Err(TiledError::PrematureEnd("Ran out of XML data".to_owned())) + Err(Error::PrematureEnd("Ran out of XML data".to_owned())) } fn convert_to_tiles(data: &[u8], tilesets: &[MapTilesetGid]) -> Vec> { diff --git a/src/map.rs b/src/map.rs index 17504b9b..86620e5b 100644 --- a/src/map.rs +++ b/src/map.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, fmt, fs::File, io::Read, path::Path, str::FromSt use xml::{attribute::OwnedAttribute, reader::XmlEvent, EventReader}; use crate::{ - error::TiledError, + error::{Error, Result}, layers::{LayerData, LayerTag}, properties::{parse_properties, Color, Properties}, tileset::Tileset, @@ -61,10 +61,10 @@ impl Map { reader: R, path: impl AsRef, cache: &mut impl ResourceCache, - ) -> Result { + ) -> Result { let mut parser = EventReader::new(reader); loop { - match parser.next().map_err(TiledError::XmlDecodingError)? { + match parser.next().map_err(Error::XmlDecodingError)? { XmlEvent::StartElement { name, attributes, .. } => { @@ -78,7 +78,7 @@ impl Map { } } XmlEvent::EndDocument => { - return Err(TiledError::PrematureEnd( + return Err(Error::PrematureEnd( "Document ended before map was parsed".to_string(), )) } @@ -91,11 +91,8 @@ impl Map { /// files will be loaded relative to the path given. /// /// The tileset cache is used to store and refer to any tilesets found along the way. - pub fn parse_file( - path: impl AsRef, - cache: &mut impl ResourceCache, - ) -> Result { - let reader = File::open(path.as_ref()).map_err(|err| TiledError::CouldNotOpenFile { + pub fn parse_file(path: impl AsRef, cache: &mut impl ResourceCache) -> Result { + let reader = File::open(path.as_ref()).map_err(|err| Error::CouldNotOpenFile { path: path.as_ref().to_owned(), err, })?; @@ -155,7 +152,7 @@ impl Map { attrs: Vec, map_path: &Path, cache: &mut impl ResourceCache, - ) -> Result { + ) -> Result { let ((c, infinite), (v, o, w, h, tw, th)) = get_attrs!( attrs, optionals: [ @@ -170,7 +167,7 @@ impl Map { ("tilewidth", tile_width, |v:String| v.parse().ok()), ("tileheight", tile_height, |v:String| v.parse().ok()), ], - TiledError::MalformedAttributes("map must have version, width, height, tilewidth, tileheight and orientation with correct types".to_string()) + Error::MalformedAttributes("map must have version, width, height, tilewidth, tileheight and orientation with correct types".to_string()) ); let infinite = infinite.unwrap_or(false); @@ -187,7 +184,7 @@ impl Map { let res = Tileset::parse_xml_in_map(parser, attrs, map_path)?; match res.result_type { EmbeddedParseResultType::ExternalReference { tileset_path } => { - let file = File::open(&tileset_path).map_err(|err| TiledError::CouldNotOpenFile{path: tileset_path.clone(), err })?; + let file = File::open(&tileset_path).map_err(|err| Error::CouldNotOpenFile{path: tileset_path.clone(), err })?; let tileset = cache.get_or_try_insert_tileset_with(tileset_path.clone(), || Tileset::parse_reader(file, &tileset_path))?; tilesets.push(MapTilesetGid{first_gid: res.first_gid, tileset}); } @@ -279,7 +276,7 @@ pub enum Orientation { impl FromStr for Orientation { type Err = (); - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> std::result::Result { match s { "orthogonal" => Ok(Orientation::Orthogonal), "isometric" => Ok(Orientation::Isometric), diff --git a/src/objects.rs b/src/objects.rs index f59df80b..e61d2680 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use xml::attribute::OwnedAttribute; use crate::{ - error::TiledError, + error::{Error, Result}, properties::{parse_properties, Properties}, util::{get_attrs, map_wrapper, parse_tag, XmlEventResult}, LayerTile, LayerTileData, MapTilesetGid, @@ -67,7 +67,7 @@ impl ObjectData { parser: &mut impl Iterator, attrs: Vec, tilesets: Option<&[MapTilesetGid]>, - ) -> Result { + ) -> Result { let ((id, tile, n, t, w, h, v, r), (x, y)) = get_attrs!( attrs, optionals: [ @@ -85,7 +85,7 @@ impl ObjectData { ("x", x, |v:String| v.parse().ok()), ("y", y, |v:String| v.parse().ok()), ], - TiledError::MalformedAttributes("objects must have an x and a y number".to_string()) + Error::MalformedAttributes("objects must have an x and a y number".to_string()) ); let visible = v.unwrap_or(true); let width = w.unwrap_or(0f32); @@ -144,38 +144,38 @@ impl ObjectData { } impl ObjectData { - fn new_polyline(attrs: Vec) -> Result { + fn new_polyline(attrs: Vec) -> Result { let s = get_attrs!( attrs, required: [ ("points", points, |v| Some(v)), ], - TiledError::MalformedAttributes("A polyline must have points".to_string()) + Error::MalformedAttributes("A polyline must have points".to_string()) ); let points = ObjectData::parse_points(s)?; Ok(ObjectShape::Polyline { points }) } - fn new_polygon(attrs: Vec) -> Result { + fn new_polygon(attrs: Vec) -> Result { let s = get_attrs!( attrs, required: [ ("points", points, |v| Some(v)), ], - TiledError::MalformedAttributes("A polygon must have points".to_string()) + Error::MalformedAttributes("A polygon must have points".to_string()) ); let points = ObjectData::parse_points(s)?; Ok(ObjectShape::Polygon { points: points }) } - fn parse_points(s: String) -> Result, TiledError> { + fn parse_points(s: String) -> Result> { let pairs = s.split(' '); pairs .map(|point| point.split(',')) .map(|components| { let v: Vec<&str> = components.collect(); if v.len() != 2 { - return Err(TiledError::MalformedAttributes( + return Err(Error::MalformedAttributes( "one of a polyline's points does not have an x and y coordinate" .to_string(), )); @@ -183,7 +183,7 @@ impl ObjectData { let (x, y) = (v[0].parse().ok(), v[1].parse().ok()); match (x, y) { (Some(x), Some(y)) => Ok((x, y)), - _ => Err(TiledError::MalformedAttributes( + _ => Err(Error::MalformedAttributes( "one of polyline's points does not have i32eger coordinates".to_string(), )), } diff --git a/src/properties.rs b/src/properties.rs index 8ee94484..a1e8bb05 100644 --- a/src/properties.rs +++ b/src/properties.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, str::FromStr}; use xml::{attribute::OwnedAttribute, reader::XmlEvent}; use crate::{ - error::TiledError, + error::{Error, Result}, util::{get_attrs, parse_tag, XmlEventResult}, }; @@ -20,7 +20,7 @@ pub struct Color { impl FromStr for Color { type Err = (); - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> std::result::Result { let s = if s.starts_with("#") { &s[1..] } else { s }; match s.len() { 6 => { @@ -81,41 +81,41 @@ pub enum PropertyValue { } impl PropertyValue { - fn new(property_type: String, value: String) -> Result { + fn new(property_type: String, value: String) -> Result { // Check the property type against the value. match property_type.as_str() { "bool" => match value.parse() { Ok(val) => Ok(PropertyValue::BoolValue(val)), - Err(err) => Err(TiledError::InvalidPropertyValue { + Err(err) => Err(Error::InvalidPropertyValue { description: err.to_string(), }), }, "float" => match value.parse() { Ok(val) => Ok(PropertyValue::FloatValue(val)), - Err(err) => Err(TiledError::InvalidPropertyValue { + Err(err) => Err(Error::InvalidPropertyValue { description: err.to_string(), }), }, "int" => match value.parse() { Ok(val) => Ok(PropertyValue::IntValue(val)), - Err(err) => Err(TiledError::InvalidPropertyValue { + Err(err) => Err(Error::InvalidPropertyValue { description: err.to_string(), }), }, "color" if value.len() > 1 => Color::from_str(&value) .map(|color| PropertyValue::ColorValue(color)) - .map_err(|_| TiledError::InvalidPropertyValue { + .map_err(|_| Error::InvalidPropertyValue { description: "Couldn't parse color".to_string(), }), "string" => Ok(PropertyValue::StringValue(value)), "object" => match value.parse() { Ok(val) => Ok(PropertyValue::ObjectValue(val)), - Err(err) => Err(TiledError::InvalidPropertyValue { + Err(err) => Err(Error::InvalidPropertyValue { description: err.to_string(), }), }, "file" => Ok(PropertyValue::FileValue(value)), - _ => Err(TiledError::UnknownPropertyType { + _ => Err(Error::UnknownPropertyType { type_name: property_type, }), } @@ -127,7 +127,7 @@ pub type Properties = HashMap; pub(crate) fn parse_properties( parser: &mut impl Iterator, -) -> Result { +) -> Result { let mut p = HashMap::new(); parse_tag!(parser, "properties", { "property" => |attrs:Vec| { @@ -140,7 +140,7 @@ pub(crate) fn parse_properties( required: [ ("name", key, |v| Some(v)), ], - TiledError::MalformedAttributes("property must have a name and a value".to_string()) + Error::MalformedAttributes("property must have a name and a value".to_string()) ); let t = t.unwrap_or("string".into()); @@ -150,9 +150,9 @@ pub(crate) fn parse_properties( // if the "value" attribute was missing, might be a multiline string match parser.next() { Some(Ok(XmlEvent::Characters(s))) => Ok(s), - Some(Err(err)) => Err(TiledError::XmlDecodingError(err)), + Some(Err(err)) => Err(Error::XmlDecodingError(err)), None => unreachable!(), // EndDocument or error must come first - _ => Err(TiledError::MalformedAttributes(format!("property '{}' is missing a value", k))), + _ => Err(Error::MalformedAttributes(format!("property '{}' is missing a value", k))), }? } }; diff --git a/src/tile.rs b/src/tile.rs index 5563d647..fea65998 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -4,12 +4,12 @@ use xml::attribute::OwnedAttribute; use crate::{ animation::{parse_animation, Frame}, - error::TiledError, + error::Error, image::Image, layers::ObjectLayerData, properties::{parse_properties, Properties}, util::{get_attrs, parse_tag, XmlEventResult}, - Tileset, + Result, Tileset, }; /// A tile ID, local to a tileset. @@ -78,7 +78,7 @@ impl TileData { parser: &mut impl Iterator, attrs: Vec, path_relative_to: &Path, - ) -> Result<(TileId, TileData), TiledError> { + ) -> Result<(TileId, TileData)> { let ((tile_type, probability), id) = get_attrs!( attrs, optionals: [ @@ -88,7 +88,7 @@ impl TileData { required: [ ("id", id, |v:String| v.parse::().ok()), ], - TiledError::MalformedAttributes("tile must have an id with the correct type".to_string()) + Error::MalformedAttributes("tile must have an id with the correct type".to_string()) ); let mut image = Option::None; diff --git a/src/tileset.rs b/src/tileset.rs index 146844a4..c88a0bda 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -6,14 +6,14 @@ use xml::attribute::OwnedAttribute; use xml::reader::XmlEvent; use xml::EventReader; -use crate::error::TiledError; +use crate::error::{Error, Result}; use crate::image::Image; use crate::properties::{parse_properties, Properties}; use crate::tile::TileData; use crate::{util::*, Gid, Tile}; /// A collection of tiles for usage in maps and template objects. -/// +/// /// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tileset). #[derive(Debug, PartialEq, Clone)] pub struct Tileset { @@ -21,12 +21,12 @@ pub struct Tileset { pub name: String, /// The (maximum) width in pixels of the tiles in this tileset. Irrelevant for [image collection] /// tilesets. - /// + /// /// [image collection]: Self::image pub tile_width: u32, /// The (maximum) height in pixels of the tiles in this tileset. Irrelevant for [image collection] /// tilesets. - /// + /// /// [image collection]: Self::image pub tile_height: u32, /// The spacing in pixels between the tiles in this tileset (applies to the tileset image). @@ -99,13 +99,10 @@ impl Tileset { /// /// assert_eq!(tileset.image.unwrap().source, PathBuf::from("assets/tilesheet.png")); /// ``` - pub fn parse_reader(reader: R, path: impl AsRef) -> Result { + pub fn parse_reader(reader: R, path: impl AsRef) -> Result { let mut tileset_parser = EventReader::new(reader); loop { - match tileset_parser - .next() - .map_err(TiledError::XmlDecodingError)? - { + match tileset_parser.next().map_err(Error::XmlDecodingError)? { XmlEvent::StartElement { name, attributes, .. } if name.local_name == "tileset" => { @@ -116,7 +113,7 @@ impl Tileset { ); } XmlEvent::EndDocument => { - return Err(TiledError::PrematureEnd( + return Err(Error::PrematureEnd( "Tileset Document ended before map was parsed".to_string(), )) } @@ -137,9 +134,9 @@ impl Tileset { parser: &mut impl Iterator, attrs: Vec, map_path: &Path, - ) -> Result { + ) -> Result { Tileset::parse_xml_embedded(parser, &attrs, map_path).or_else(|err| { - if matches!(err, TiledError::MalformedAttributes(_)) { + if matches!(err, Error::MalformedAttributes(_)) { Tileset::parse_xml_reference(&attrs, map_path) } else { Err(err) @@ -151,7 +148,7 @@ impl Tileset { parser: &mut impl Iterator, attrs: &Vec, map_path: &Path, - ) -> Result { + ) -> Result { let ((spacing, margin, columns, name), (tilecount, first_gid, tile_width, tile_height)) = get_attrs!( attrs, optionals: [ @@ -166,13 +163,10 @@ impl Tileset { ("tilewidth", width, |v:String| v.parse().ok()), ("tileheight", height, |v:String| v.parse().ok()), ], - TiledError::MalformedAttributes("tileset must have a firstgid, name tile width and height with correct types".to_string()) + Error::MalformedAttributes("tileset must have a firstgid, name tile width and height with correct types".to_string()) ); - let root_path = map_path - .parent() - .ok_or(TiledError::PathIsNotFile)? - .to_owned(); + let root_path = map_path.parent().ok_or(Error::PathIsNotFile)?.to_owned(); Self::finish_parsing_xml( parser, @@ -196,20 +190,17 @@ impl Tileset { fn parse_xml_reference( attrs: &Vec, map_path: &Path, - ) -> Result { + ) -> Result { let (first_gid, source) = get_attrs!( attrs, required: [ ("firstgid", first_gid, |v:String| v.parse().ok().map(|n| Gid(n))), ("source", name, |v| Some(v)), ], - TiledError::MalformedAttributes("Tileset reference must have a firstgid and source with correct types".to_string()) + Error::MalformedAttributes("Tileset reference must have a firstgid and source with correct types".to_string()) ); - let tileset_path = map_path - .parent() - .ok_or(TiledError::PathIsNotFile)? - .join(source); + let tileset_path = map_path.parent().ok_or(Error::PathIsNotFile)?.join(source); Ok(EmbeddedParseResult { first_gid, @@ -221,7 +212,7 @@ impl Tileset { parser: &mut impl Iterator, attrs: &Vec, path: &Path, - ) -> Result { + ) -> Result { let ((spacing, margin, columns, name), (tilecount, tile_width, tile_height)) = get_attrs!( attrs, optionals: [ @@ -235,10 +226,10 @@ impl Tileset { ("tilewidth", width, |v:String| v.parse().ok()), ("tileheight", height, |v:String| v.parse().ok()), ], - TiledError::MalformedAttributes("tileset must have a name, tile width and height with correct types".to_string()) + Error::MalformedAttributes("tileset must have a name, tile width and height with correct types".to_string()) ); - let root_path = path.parent().ok_or(TiledError::PathIsNotFile)?.to_owned(); + let root_path = path.parent().ok_or(Error::PathIsNotFile)?.to_owned(); Self::finish_parsing_xml( parser, @@ -258,26 +249,26 @@ impl Tileset { fn finish_parsing_xml( parser: &mut impl Iterator, prop: TilesetProperties, - ) -> Result { + ) -> Result { let mut image = Option::None; let mut tiles = HashMap::with_capacity(prop.tilecount as usize); let mut properties = HashMap::new(); parse_tag!(parser, "tileset", { - "image" => |attrs| { - image = Some(Image::new(parser, attrs, &prop.root_path)?); - Ok(()) - }, - "properties" => |_| { - properties = parse_properties(parser)?; - Ok(()) - }, - "tile" => |attrs| { - let (id, tile) = TileData::new(parser, attrs, &prop.root_path)?; - tiles.insert(id, tile); - Ok(()) - }, - }); + "image" => |attrs| { + image = Some(Image::new(parser, attrs, &prop.root_path)?); + Ok(()) + }, + "properties" => |_| { + properties = parse_properties(parser)?; + Ok(()) + }, + "tile" => |attrs| { + let (id, tile) = TileData::new(parser, attrs, &prop.root_path)?; + tiles.insert(id, tile); + Ok(()) + }, + }); // A tileset is considered an image collection tileset if there is no image attribute (because its tiles do). let is_image_collection_tileset = image.is_none(); @@ -314,10 +305,10 @@ impl Tileset { tile_width: u32, margin: u32, spacing: u32, - ) -> Result { + ) -> Result { image .as_ref() - .ok_or(TiledError::MalformedAttributes( + .ok_or(Error::MalformedAttributes( "No nor columns attribute in ".to_string(), )) .and_then(|image| Ok((image.width as u32 - margin + spacing) / (tile_width + spacing))) diff --git a/src/util.rs b/src/util.rs index aca93cdf..bf10f252 100644 --- a/src/util.rs +++ b/src/util.rs @@ -55,7 +55,7 @@ macro_rules! match_attrs { macro_rules! parse_tag { ($parser:expr, $close_tag:expr, {$($open_tag:expr => $open_method:expr),* $(,)*}) => { while let Some(next) = $parser.next() { - match next.map_err(TiledError::XmlDecodingError)? { + match next.map_err(Error::XmlDecodingError)? { #[allow(unused_variables)] $( xml::reader::XmlEvent::StartElement {name, attributes, ..} @@ -68,7 +68,7 @@ macro_rules! parse_tag { } xml::reader::XmlEvent::EndDocument => { - return Err(TiledError::PrematureEnd("Document ended before we expected.".to_string())); + return Err(Error::PrematureEnd("Document ended before we expected.".to_string())); } _ => {} }