diff --git a/src/animation.rs b/src/animation.rs
index 1ffe8802ac24a87e8a05f30c2bb30c4e587bf796..bf0d5364d7ba4126829672e3697380526b3ce87c 100644
--- a/src/animation.rs
+++ b/src/animation.rs
@@ -1,6 +1,6 @@
 use xml::attribute::OwnedAttribute;
 
-use crate::{error::TiledError, util::get_attrs};
+use crate::{error::TiledError, util::{get_attrs, XmlEventResult, parse_tag}};
 
 #[derive(Debug, PartialEq, Clone)]
 pub struct Frame {
@@ -25,3 +25,17 @@ impl Frame {
         })
     }
 }
+
+
+pub(crate) fn parse_animation(
+    parser: &mut impl Iterator<Item = XmlEventResult>,
+) -> Result<Vec<Frame>, TiledError> {
+    let mut animation = Vec::new();
+    parse_tag!(parser, "animation", {
+        "frame" => |attrs| {
+            animation.push(Frame::new(attrs)?);
+            Ok(())
+        },
+    });
+    Ok(animation)
+}
\ No newline at end of file
diff --git a/src/layers/tile/util.rs b/src/layers/tile/util.rs
index 8937a318919bdffb72b2605c84dd9b61525b93d1..fde41f23412a8d5979e9087e8b6ff3e825b3bfc3 100644
--- a/src/layers/tile/util.rs
+++ b/src/layers/tile/util.rs
@@ -1,4 +1,4 @@
-use std::io::{BufReader, Read};
+use std::{convert::TryInto, io::Read};
 
 use xml::reader::XmlEvent;
 
@@ -11,47 +11,25 @@ pub(crate) fn parse_data_line(
     tilesets: &[MapTilesetGid],
 ) -> Result<Vec<Option<LayerTileData>>, TiledError> {
     match (encoding.as_deref(), compression.as_deref()) {
-        (Some("base64"), None) => {
-            return parse_base64(parser).map(|v| convert_to_tiles(&v, tilesets))
-        }
-        (Some("csv"), None) => return decode_csv(parser, tilesets),
-        (Some(_), None) => {
-            return Err(TiledError::InvalidEncodingFormat {
-                encoding,
-                compression,
-            })
-        }
-        (Some(e), Some(c)) => match (e, c) {
-            ("base64", "zlib") => {
-                return parse_base64(parser)
-                    .and_then(decode_zlib)
-                    .map(|v| convert_to_tiles(&v, tilesets))
-            }
-            ("base64", "gzip") => {
-                return parse_base64(parser)
-                    .and_then(decode_gzip)
-                    .map(|v| convert_to_tiles(&v, tilesets))
-            }
-            #[cfg(feature = "zstd")]
-            ("base64", "zstd") => {
-                return parse_base64(parser)
-                    .and_then(decode_zstd)
-                    .map(|v| convert_to_tiles(&v, tilesets))
-            }
-            _ => {
-                return Err(TiledError::InvalidEncodingFormat {
-                    encoding,
-                    compression,
-                })
-            }
-        },
-        _ => {
-            return Err(TiledError::InvalidEncodingFormat {
-                encoding,
-                compression,
-            })
-        }
-    };
+        (Some("csv"), None) => decode_csv(parser, tilesets),
+
+        (Some("base64"), None) => parse_base64(parser).map(|v| convert_to_tiles(&v, tilesets)),
+        (Some("base64"), Some("zlib")) => parse_base64(parser)
+            .and_then(|data| process_decoder(libflate::zlib::Decoder::new(&data[..])))
+            .map(|v| convert_to_tiles(&v, tilesets)),
+        (Some("base64"), Some("gzip")) => parse_base64(parser)
+            .and_then(|data| process_decoder(libflate::gzip::Decoder::new(&data[..])))
+            .map(|v| convert_to_tiles(&v, tilesets)),
+        #[cfg(feature = "zstd")]
+        (Some("base64"), Some("zstd")) => parse_base64(parser)
+            .and_then(|data| process_decoder(zstd::stream::read::Decoder::with_buffer(&data[..])))
+            .map(|v| convert_to_tiles(&v, tilesets)),
+
+        _ => Err(TiledError::InvalidEncodingFormat {
+            encoding,
+            compression,
+        }),
+    }
 }
 
 fn parse_base64(parser: &mut impl Iterator<Item = XmlEventResult>) -> Result<Vec<u8>, TiledError> {
@@ -60,10 +38,8 @@ fn parse_base64(parser: &mut impl Iterator<Item = XmlEventResult>) -> Result<Vec
             XmlEvent::Characters(s) => {
                 return base64::decode(s.trim().as_bytes()).map_err(TiledError::Base64DecodingError)
             }
-            XmlEvent::EndElement { name, .. } => {
-                if name.local_name == "data" {
-                    return Ok(Vec::new());
-                }
+            XmlEvent::EndElement { name, .. } if name.local_name == "data" => {
+                return Ok(Vec::new());
             }
             _ => {}
         }
@@ -71,40 +47,14 @@ fn parse_base64(parser: &mut impl Iterator<Item = XmlEventResult>) -> Result<Vec
     Err(TiledError::PrematureEnd("Ran out of XML data".to_owned()))
 }
 
-fn decode_zlib(data: Vec<u8>) -> Result<Vec<u8>, TiledError> {
-    use libflate::zlib::Decoder;
-    let mut zd =
-        Decoder::new(BufReader::new(&data[..])).map_err(|e| TiledError::DecompressingError(e))?;
-    let mut data = Vec::new();
-    match zd.read_to_end(&mut data) {
-        Ok(_v) => {}
-        Err(e) => return Err(TiledError::DecompressingError(e)),
-    }
-    Ok(data)
-}
-
-fn decode_gzip(data: Vec<u8>) -> Result<Vec<u8>, TiledError> {
-    use libflate::gzip::Decoder;
-    let mut zd =
-        Decoder::new(BufReader::new(&data[..])).map_err(|e| TiledError::DecompressingError(e))?;
-
-    let mut data = Vec::new();
-    zd.read_to_end(&mut data)
-        .map_err(|e| TiledError::DecompressingError(e))?;
-    Ok(data)
-}
-
-fn decode_zstd(data: Vec<u8>) -> Result<Vec<u8>, TiledError> {
-    use std::io::Cursor;
-    use zstd::stream::read::Decoder;
-
-    let buff = Cursor::new(&data);
-    let mut zd = Decoder::with_buffer(buff).map_err(|e| TiledError::DecompressingError(e))?;
-
-    let mut data = Vec::new();
-    zd.read_to_end(&mut data)
-        .map_err(|e| TiledError::DecompressingError(e))?;
-    Ok(data)
+fn process_decoder(decoder: std::io::Result<impl Read>) -> Result<Vec<u8>, TiledError> {
+    decoder
+        .and_then(|mut decoder| {
+            let mut data = Vec::new();
+            decoder.read_to_end(&mut data)?;
+            Ok(data)
+        })
+        .map_err(|e| TiledError::DecompressingError(e))
 }
 
 fn decode_csv(
@@ -121,10 +71,8 @@ fn decode_csv(
                     .collect();
                 return Ok(tiles);
             }
-            XmlEvent::EndElement { name, .. } => {
-                if name.local_name == "data" {
-                    return Ok(Vec::new());
-                }
+            XmlEvent::EndElement { name, .. } if name.local_name == "data" => {
+                return Ok(Vec::new());
             }
             _ => {}
         }
@@ -132,14 +80,11 @@ fn decode_csv(
     Err(TiledError::PrematureEnd("Ran out of XML data".to_owned()))
 }
 
-fn convert_to_tiles(all: &Vec<u8>, tilesets: &[MapTilesetGid]) -> Vec<Option<LayerTileData>> {
-    let mut data = Vec::new();
-    for chunk in all.chunks_exact(4) {
-        let n = chunk[0] as u32
-            + ((chunk[1] as u32) << 8)
-            + ((chunk[2] as u32) << 16)
-            + ((chunk[3] as u32) << 24);
-        data.push(LayerTileData::from_bits(n, tilesets));
-    }
-    data
+fn convert_to_tiles(data: &[u8], tilesets: &[MapTilesetGid]) -> Vec<Option<LayerTileData>> {
+    data.chunks_exact(4)
+        .map(|chunk| {
+            let bits = u32::from_le_bytes(chunk.try_into().unwrap());
+            LayerTileData::from_bits(bits, tilesets)
+        })
+        .collect()
 }
diff --git a/src/objects.rs b/src/objects.rs
index 5c4e1fb92366be7163a2069a6240850f3d678ebf..07d6c34621d76e46e79949cd5d8dd9407f9915e7 100644
--- a/src/objects.rs
+++ b/src/objects.rs
@@ -42,11 +42,12 @@ impl ObjectData {
         attrs: Vec<OwnedAttribute>,
         tilesets: Option<&[MapTilesetGid]>,
     ) -> Result<ObjectData, TiledError> {
-        let ((id, bits, n, t, w, h, v, r), (x, y)) = get_attrs!(
+        let ((id, tile, n, t, w, h, v, r), (x, y)) = get_attrs!(
             attrs,
             optionals: [
                 ("id", id, |v:String| v.parse().ok()),
-                ("gid", gid, |v:String| v.parse().ok()),
+                ("gid", tile, |v:String| v.parse().ok()
+                                            .and_then(|bits| LayerTileData::from_bits(bits, tilesets?))),
                 ("name", name, |v:String| v.parse().ok()),
                 ("type", obj_type, |v:String| v.parse().ok()),
                 ("width", width, |v:String| v.parse().ok()),
@@ -60,22 +61,21 @@ impl ObjectData {
             ],
             TiledError::MalformedAttributes("objects must have an x and a y number".to_string())
         );
-        let v = v.unwrap_or(true);
-        let w = w.unwrap_or(0f32);
-        let h = h.unwrap_or(0f32);
-        let r = r.unwrap_or(0f32);
+        let visible = v.unwrap_or(true);
+        let width = w.unwrap_or(0f32);
+        let height = h.unwrap_or(0f32);
+        let rotation = r.unwrap_or(0f32);
         let id = id.unwrap_or(0u32);
-        let tile = bits.and_then(|bits| LayerTileData::from_bits(bits, tilesets?));
-        let n = n.unwrap_or(String::new());
-        let t = t.unwrap_or(String::new());
+        let name = n.unwrap_or_else(|| String::new());
+        let obj_type = t.unwrap_or_else(|| String::new());
         let mut shape = None;
         let mut properties = HashMap::new();
 
         parse_tag!(parser, "object", {
             "ellipse" => |_| {
                 shape = Some(ObjectShape::Ellipse {
-                    width: w,
-                    height: h,
+                    width,
+                    height,
                 });
                 Ok(())
             },
@@ -88,7 +88,7 @@ impl ObjectData {
                 Ok(())
             },
             "point" => |_| {
-                shape = Some(ObjectData::new_point(x, y)?);
+                shape = Some(ObjectShape::Point(x, y));
                 Ok(())
             },
             "properties" => |_| {
@@ -97,22 +97,19 @@ impl ObjectData {
             },
         });
 
-        let shape = shape.unwrap_or(ObjectShape::Rect {
-            width: w,
-            height: h,
-        });
+        let shape = shape.unwrap_or(ObjectShape::Rect { width, height });
 
         Ok(ObjectData {
             id,
             tile,
-            name: n.clone(),
-            obj_type: t.clone(),
-            width: w,
-            height: h,
+            name,
+            obj_type,
+            width,
+            height,
             x,
             y,
-            rotation: r,
-            visible: v,
+            rotation,
+            visible,
             shape,
             properties,
         })
@@ -130,7 +127,7 @@ impl ObjectData {
             TiledError::MalformedAttributes("A polyline must have points".to_string())
         );
         let points = ObjectData::parse_points(s)?;
-        Ok(ObjectShape::Polyline { points: points })
+        Ok(ObjectShape::Polyline { points })
     }
 
     fn new_polygon(attrs: Vec<OwnedAttribute>) -> Result<ObjectShape, TiledError> {
@@ -146,29 +143,27 @@ impl ObjectData {
         Ok(ObjectShape::Polygon { points: points })
     }
 
-    fn new_point(x: f32, y: f32) -> Result<ObjectShape, TiledError> {
-        Ok(ObjectShape::Point(x, y))
-    }
-
     fn parse_points(s: String) -> Result<Vec<(f32, f32)>, TiledError> {
         let pairs = s.split(' ');
-        let mut points = Vec::new();
-        for v in pairs.map(|p| p.split(',')) {
-            let v: Vec<&str> = v.collect();
-            if v.len() != 2 {
-                return Err(TiledError::MalformedAttributes(
-                    "one of a polyline's points does not have an x and y coordinate".to_string(),
-                ));
-            }
-            let (x, y) = (v[0].parse().ok(), v[1].parse().ok());
-            if x.is_none() || y.is_none() {
-                return Err(TiledError::MalformedAttributes(
-                    "one of polyline's points does not have i32eger coordinates".to_string(),
-                ));
-            }
-            points.push((x.unwrap(), y.unwrap()));
-        }
-        Ok(points)
+        pairs
+            .map(|point| point.split(','))
+            .map(|components| {
+                let v: Vec<&str> = components.collect();
+                if v.len() != 2 {
+                    return Err(TiledError::MalformedAttributes(
+                        "one of a polyline's points does not have an x and y coordinate"
+                            .to_string(),
+                    ));
+                }
+                let (x, y) = (v[0].parse().ok(), v[1].parse().ok());
+                match (x, y) {
+                    (Some(x), Some(y)) => Ok((x, y)),
+                    _ => Err(TiledError::MalformedAttributes(
+                        "one of polyline's points does not have i32eger coordinates".to_string(),
+                    )),
+                }
+            })
+            .collect()
     }
 }
 
@@ -176,7 +171,7 @@ pub type Object<'map> = MapWrapper<'map, ObjectData>;
 
 impl<'map> Object<'map> {
     /// Returns the tile that the object is using as image, if any.
-    pub fn get_tile<'res: 'map>(&self) -> Option<LayerTile<'map>> {
+    pub fn get_tile(&self) -> Option<LayerTile<'map>> {
         self.data()
             .tile
             .map(|tile| LayerTile::from_data(&tile, self.map()))
diff --git a/src/tile.rs b/src/tile.rs
index 0493fb508c21eaae75f294ee7749f87fc4a31ddb..ffa1ef6b52454eeb765133ec105cee8c6eaf5478 100644
--- a/src/tile.rs
+++ b/src/tile.rs
@@ -3,12 +3,12 @@ use std::{collections::HashMap, path::Path};
 use xml::attribute::OwnedAttribute;
 
 use crate::{
-    animation::Frame,
+    animation::{Frame, parse_animation},
     error::TiledError,
     image::Image,
     layers::ObjectLayerData,
     properties::{parse_properties, Properties},
-    util::{get_attrs, parse_animation, parse_tag, XmlEventResult},
+    util::{get_attrs, parse_tag, XmlEventResult},
 };
 
 pub type TileId = u32;
diff --git a/src/tileset.rs b/src/tileset.rs
index c660333a97c72a96703f3e88ddce79035e3247f8..46c13e9577c1cf56e5cef98912fbb5f3bbaac4e1 100644
--- a/src/tileset.rs
+++ b/src/tileset.rs
@@ -93,14 +93,12 @@ impl Tileset {
             {
                 XmlEvent::StartElement {
                     name, attributes, ..
-                } => {
-                    if name.local_name == "tileset" {
-                        return Self::parse_external_tileset(
-                            &mut tileset_parser.into_iter(),
-                            &attributes,
-                            path,
-                        );
-                    }
+                } if name.local_name == "tileset" => {
+                    return Self::parse_external_tileset(
+                        &mut tileset_parser.into_iter(),
+                        &attributes,
+                        path,
+                    );
                 }
                 XmlEvent::EndDocument => {
                     return Err(TiledError::PrematureEnd(
diff --git a/src/util.rs b/src/util.rs
index 0eafe24679acfe2c7b8f421f52b3ab2c059dc274..e9d5127c327e0a62de37c8eab2bac3c8ac2b9537 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -55,21 +55,7 @@ macro_rules! parse_tag {
 pub(crate) use get_attrs;
 pub(crate) use parse_tag;
 
-use crate::{animation::Frame, error::TiledError, Gid, MapTilesetGid};
-
-// TODO: Move to animation module
-pub(crate) fn parse_animation(
-    parser: &mut impl Iterator<Item = XmlEventResult>,
-) -> Result<Vec<Frame>, TiledError> {
-    let mut animation = Vec::new();
-    parse_tag!(parser, "animation", {
-        "frame" => |attrs| {
-            animation.push(Frame::new(attrs)?);
-            Ok(())
-        },
-    });
-    Ok(animation)
-}
+use crate::{Gid, MapTilesetGid};
 
 pub(crate) type XmlEventResult = xml::reader::Result<xml::reader::XmlEvent>;