diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 3ed0b83da387d855ef7d0ad7fc7db40cc85ee3b2..648b8583b1d40182b13d4664ef0aad14bebd2bdd 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -14,8 +14,11 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-    - uses: actions/checkout@v2
-    - uses: Swatinem/rust-cache@v1
+    - name: Checkout
+      uses: actions/checkout@v2
+
+    - name: Setup rust-cache
+      uses: Swatinem/rust-cache@v1
 
     - name: Update package manager
       run: sudo apt-get update
@@ -28,3 +31,37 @@ jobs:
 
     - name: Run tests
       run: cargo test --verbose
+  
+  rustfmt:
+    runs-on: ubuntu-latest
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v2
+
+    - name: Get nightly Rust toolchain with rustfmt
+      uses: actions-rs/toolchain@v1
+      with:
+        profile: minimal
+        toolchain: nightly
+        override: true
+        components: rustfmt
+
+    - name: Run cargo fmt --all -- --check
+      run: cargo fmt --all -- --check
+
+  clippy:
+    runs-on: ubuntu-latest
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v2
+
+    - name: Get stable Rust toolchain with clippy
+      uses: actions-rs/toolchain@v1
+      with:
+        profile: minimal
+        toolchain: stable
+        override: true
+        components: clippy
+
+    - name: Run cargo clippy --all-targets --package tiled
+      run: cargo clippy --all-targets --package tiled
\ No newline at end of file
diff --git a/examples/sfml/main.rs b/examples/sfml/main.rs
index 1b6c7201a397edab054f3c80863adfa3e74dfb8c..65e571b1a249a0dde3a737ec7940e504ce3afa20 100644
--- a/examples/sfml/main.rs
+++ b/examples/sfml/main.rs
@@ -17,7 +17,7 @@ use tiled::{FiniteTileLayer, Loader, Map};
 use tilesheet::Tilesheet;
 
 /// A path to the map to display.
-const MAP_PATH: &'static str = "assets/tiled_base64_external.tmx";
+const MAP_PATH: &str = "assets/tiled_base64_external.tmx";
 
 /// A [Map] wrapper which also contains graphical information such as the tileset texture or the layer meshes.
 ///
@@ -85,8 +85,8 @@ impl Drawable for Level {
         target: &mut dyn RenderTarget,
         states: &sfml::graphics::RenderStates<'texture, 'shader, 'shader_texture>,
     ) {
-        let mut states = states.clone();
-        states.set_texture(Some(&self.tilesheet.texture()));
+        let mut states = *states;
+        states.set_texture(Some(self.tilesheet.texture()));
         for mesh in self.layers.iter() {
             target.draw_with_renderstates(mesh, &states);
         }
@@ -114,9 +114,8 @@ fn main() {
     loop {
         while let Some(event) = window.poll_event() {
             use sfml::window::Event;
-            match event {
-                Event::Closed => return,
-                _ => (),
+            if event == Event::Closed {
+                return;
             }
         }
 
diff --git a/examples/sfml/tilesheet.rs b/examples/sfml/tilesheet.rs
index d3530f24f917567105ddb3e6daf1abb7b75edaab..1526617d404678bc0656b74bb9bbcaaf6d35ddac 100644
--- a/examples/sfml/tilesheet.rs
+++ b/examples/sfml/tilesheet.rs
@@ -14,7 +14,7 @@ pub struct Tilesheet {
 
 impl Tilesheet {
     /// Create a tilesheet from a Tiled tileset, loading its texture along the way.
-    pub fn from_tileset<'p>(tileset: Arc<Tileset>) -> Self {
+    pub fn from_tileset(tileset: Arc<Tileset>) -> Self {
         let tileset_image = tileset.image.as_ref().unwrap();
 
         let texture = {
diff --git a/src/animation.rs b/src/animation.rs
index a1956ab37f88e904d5b458b3e8c49260d80c20d9..a7bb686795ac6171e5af02b149f416661e91925a 100644
--- a/src/animation.rs
+++ b/src/animation.rs
@@ -29,10 +29,7 @@ impl Frame {
             ],
             Error::MalformedAttributes("A frame must have tileid and duration".to_string())
         );
-        Ok(Frame {
-            tile_id: tile_id,
-            duration: duration,
-        })
+        Ok(Frame { tile_id, duration })
     }
 }
 
diff --git a/src/error.rs b/src/error.rs
index d83d4922d1ba235a93c3db241f39d7dfce3587f2..32b06fab212fd26064df5f3273e70d181a58cff5 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -35,19 +35,19 @@ pub enum Error {
         compression: Option<String>,
     },
     /// There was an error parsing the value of a [`PropertyValue`].
-    /// 
+    ///
     /// [`PropertyValue`]: crate::PropertyValue
     InvalidPropertyValue {
         /// A description of the error that occured.
-        description: String
+        description: String,
     },
     /// Found an unknown property value type while parsing a [`PropertyValue`].
-    /// 
+    ///
     /// [`PropertyValue`]: crate::PropertyValue
     UnknownPropertyType {
         /// The name of the type that isn't recognized by the crate.
         /// Supported types are `string`, `int`, `float`, `bool`, `color`, `file` and `object`.
-        type_name: String
+        type_name: String,
     },
 }
 
@@ -77,12 +77,12 @@ impl fmt::Display for Error {
                 )
             }
             Error::InvalidTileFound => write!(fmt, "Invalid tile found in map being parsed"),
-            Error::InvalidEncodingFormat { encoding: None, compression: None } => 
+            Error::InvalidEncodingFormat { encoding: None, compression: None } =>
                 write!(
                     fmt,
                     "Deprecated combination of encoding and compression"
                 ),
-            Error::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",
diff --git a/src/image.rs b/src/image.rs
index fd2e3ffaff4ecc570ecbc52e14b41b19deb7fa0e..33014290eb252ccb95b15c7f7fa3d149d3a3d999 100644
--- a/src/image.rs
+++ b/src/image.rs
@@ -89,7 +89,7 @@ impl Image {
                 ("trans", trans, |v:String| v.parse().ok()),
             ],
             required: [
-                ("source", source, |v| Some(v)),
+                ("source", source, Some),
                 ("width", width, |v:String| v.parse().ok()),
                 ("height", height, |v:String| v.parse().ok()),
             ],
diff --git a/src/layers/group.rs b/src/layers/group.rs
index f13de1dc21666ef0eba064db987b3ed708f2a233..55bf145969b7cf9ed36e810124ebca2bc3dcb653 100644
--- a/src/layers/group.rs
+++ b/src/layers/group.rs
@@ -33,7 +33,7 @@ impl GroupLayerData {
                     LayerTag::TileLayer,
                     infinite,
                     map_path,
-                    &tilesets,
+                    tilesets,
                 )?);
                 Ok(())
             },
@@ -44,7 +44,7 @@ impl GroupLayerData {
                     LayerTag::ImageLayer,
                     infinite,
                     map_path,
-                    &tilesets,
+                    tilesets,
                 )?);
                 Ok(())
             },
@@ -55,7 +55,7 @@ impl GroupLayerData {
                     LayerTag::ObjectLayer,
                     infinite,
                     map_path,
-                    &tilesets,
+                    tilesets,
                 )?);
                 Ok(())
             },
@@ -66,7 +66,7 @@ impl GroupLayerData {
                     LayerTag::GroupLayer,
                     infinite,
                     map_path,
-                    &tilesets,
+                    tilesets,
                 )?);
                 Ok(())
             },
diff --git a/src/layers/mod.rs b/src/layers/mod.rs
index 726630e68a5b65055dd9952c0fec4cf01f3eaef8..1272cf4043bc1e948deee64738f6b3a5c2902cf9 100644
--- a/src/layers/mod.rs
+++ b/src/layers/mod.rs
@@ -2,12 +2,7 @@ use std::path::Path;
 
 use xml::attribute::OwnedAttribute;
 
-use crate::{
-    error::{Result},
-    properties::Properties,
-    util::*,
-    Color, Map, MapTilesetGid,
-};
+use crate::{error::Result, properties::Properties, util::*, Color, Map, MapTilesetGid};
 
 mod image;
 pub use image::*;
@@ -85,7 +80,7 @@ impl LayerData {
                 ("offsety", offset_y, |v:String| v.parse().ok()),
                 ("parallaxx", parallax_x, |v:String| v.parse().ok()),
                 ("parallaxy", parallax_y, |v:String| v.parse().ok()),
-                ("name", name, |v| Some(v)),
+                ("name", name, Some),
                 ("id", id, |v:String| v.parse().ok()),
             ]
         );
diff --git a/src/layers/object.rs b/src/layers/object.rs
index 391d7d48f71cf2e3fc30fc95560c6cf9f51546e9..45c08d8928c4d5d9b1f0ce945407709497d7d349 100644
--- a/src/layers/object.rs
+++ b/src/layers/object.rs
@@ -68,7 +68,7 @@ impl<'map> ObjectLayer<'map> {
 
     /// Returns an iterator over the objects present in this layer, in the order they were declared
     /// in in the TMX file.
-    /// 
+    ///
     /// ## Example
     /// ```
     /// # use tiled::Loader;
@@ -78,7 +78,7 @@ impl<'map> ObjectLayer<'map> {
     /// # let map = Loader::new()
     /// #     .load_tmx_map("assets/tiled_group_layers.tmx")
     /// #     .unwrap();
-    /// # 
+    /// #
     /// let spawnpoints: Vec<Object> = map
     ///     .layers()
     ///     .filter_map(|layer| match layer.layer_type() {
diff --git a/src/layers/tile/finite.rs b/src/layers/tile/finite.rs
index 87e6773e0c7b14fbd4f23f6fc1d049f56681e7a3..0e018fcbf74cd1567d497d5ad9282a2bdda2d9ef 100644
--- a/src/layers/tile/finite.rs
+++ b/src/layers/tile/finite.rs
@@ -48,8 +48,8 @@ impl FiniteTileLayerData {
         let (e, c) = get_attrs!(
             attrs,
             optionals: [
-                ("encoding", encoding, |v| Some(v)),
-                ("compression", compression, |v| Some(v)),
+                ("encoding", encoding, Some),
+                ("compression", compression, Some),
             ]
         );
 
@@ -88,6 +88,6 @@ impl<'map> FiniteTileLayer<'map> {
     pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> {
         self.data
             .get_tile_data(x, y)
-            .and_then(|data| Some(LayerTile::new(self.map(), data)))
+            .map(|data| LayerTile::new(self.map(), data))
     }
 }
diff --git a/src/layers/tile/infinite.rs b/src/layers/tile/infinite.rs
index c6e188621e05baf84f901cf1811da3206e30fa67..01b5bb816effdde80d705e6bb53f2de7bcf91207 100644
--- a/src/layers/tile/infinite.rs
+++ b/src/layers/tile/infinite.rs
@@ -30,8 +30,8 @@ impl InfiniteTileLayerData {
         let (e, c) = get_attrs!(
             attrs,
             optionals: [
-                ("encoding", encoding, |v| Some(v)),
-                ("compression", compression, |v| Some(v)),
+                ("encoding", encoding, Some),
+                ("compression", compression, Some),
             ]
         );
 
@@ -165,6 +165,6 @@ impl<'map> InfiniteTileLayer<'map> {
     pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> {
         self.data
             .get_tile_data(x, y)
-            .and_then(|data| Some(LayerTile::new(self.map, data)))
+            .map(|data| LayerTile::new(self.map, data))
     }
 }
diff --git a/src/layers/tile/util.rs b/src/layers/tile/util.rs
index 88a44c01e59501f5faa619d68ad66a1a7715ab96..e1820f435bedabb409ea436344ed1ddd49752527 100644
--- a/src/layers/tile/util.rs
+++ b/src/layers/tile/util.rs
@@ -33,7 +33,7 @@ pub(crate) fn parse_data_line(
 }
 
 fn parse_base64(parser: &mut impl Iterator<Item = XmlEventResult>) -> Result<Vec<u8>> {
-    while let Some(next) = parser.next() {
+    for next in parser {
         match next.map_err(Error::XmlDecodingError)? {
             XmlEvent::Characters(s) => {
                 return base64::decode(s.trim().as_bytes()).map_err(Error::Base64DecodingError)
@@ -54,14 +54,14 @@ fn process_decoder(decoder: std::io::Result<impl Read>) -> Result<Vec<u8>> {
             decoder.read_to_end(&mut data)?;
             Ok(data)
         })
-        .map_err(|e| Error::DecompressingError(e))
+        .map_err(Error::DecompressingError)
 }
 
 fn decode_csv(
     parser: &mut impl Iterator<Item = XmlEventResult>,
     tilesets: &[MapTilesetGid],
 ) -> Result<Vec<Option<LayerTileData>>> {
-    while let Some(next) = parser.next() {
+    for next in parser {
         match next.map_err(Error::XmlDecodingError)? {
             XmlEvent::Characters(s) => {
                 let tiles = s
diff --git a/src/map.rs b/src/map.rs
index 2dba8fc1139101666f313ca364f0217c7e6ec52d..8871985422d954c99b034c06c99cb521825962eb 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -114,11 +114,11 @@ impl Map {
     }
 
     /// Get an iterator over all the layers in the map in ascending order of their layer index.
-    /// 
+    ///
     /// ## Example
     /// ```
     /// # use tiled::Loader;
-    /// # 
+    /// #
     /// # fn main() {
     /// # struct Renderer;
     /// # impl Renderer {
@@ -164,7 +164,7 @@ impl Map {
                 ("infinite", infinite, |v:String| Some(v == "1")),
             ],
             required: [
-                ("version", version, |v| Some(v)),
+                ("version", version, Some),
                 ("orientation", orientation, |v:String| v.parse().ok()),
                 ("width", width, |v:String| v.parse().ok()),
                 ("height", height, |v:String| v.parse().ok()),
diff --git a/src/objects.rs b/src/objects.rs
index b42a592742bee20ab55ef60c94992de3d02f15af..910d3352b5fba4aa191ca2e5a6a13bcdeb60cc70 100644
--- a/src/objects.rs
+++ b/src/objects.rs
@@ -105,8 +105,8 @@ impl ObjectData {
         let height = h.unwrap_or(0f32);
         let rotation = r.unwrap_or(0f32);
         let id = id.unwrap_or(0u32);
-        let name = n.unwrap_or_else(|| String::new());
-        let obj_type = t.unwrap_or_else(|| 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();
 
@@ -161,7 +161,7 @@ impl ObjectData {
         let s = get_attrs!(
             attrs,
             required: [
-                ("points", points, |v| Some(v)),
+                ("points", points, Some),
             ],
             Error::MalformedAttributes("A polyline must have points".to_string())
         );
@@ -173,12 +173,12 @@ impl ObjectData {
         let s = get_attrs!(
             attrs,
             required: [
-                ("points", points, |v| Some(v)),
+                ("points", points, Some),
             ],
             Error::MalformedAttributes("A polygon must have points".to_string())
         );
         let points = ObjectData::parse_points(s)?;
-        Ok(ObjectShape::Polygon { points: points })
+        Ok(ObjectShape::Polygon { points })
     }
 
     fn parse_points(s: String) -> Result<Vec<(f32, f32)>> {
diff --git a/src/parse/xml/map.rs b/src/parse/xml/map.rs
index 05ce67a6c72f485cf4a9434b72e1c73fc915829a..61f2290c78d7fce3b56e3e1e228ff322a0168a28 100644
--- a/src/parse/xml/map.rs
+++ b/src/parse/xml/map.rs
@@ -4,11 +4,7 @@ use xml::{reader::XmlEvent, EventReader};
 
 use crate::{Error, Map, ResourceCache, Result};
 
-pub fn parse_map(
-    reader: impl Read,
-    path: &Path,
-    cache: &mut impl ResourceCache,
-) -> Result<Map> {
+pub fn parse_map(reader: impl Read, path: &Path, cache: &mut impl ResourceCache) -> Result<Map> {
     let mut parser = EventReader::new(reader);
     loop {
         match parser.next().map_err(Error::XmlDecodingError)? {
@@ -16,12 +12,7 @@ pub fn parse_map(
                 name, attributes, ..
             } => {
                 if name.local_name == "map" {
-                    return Map::parse_xml(
-                        &mut parser.into_iter(),
-                        attributes,
-                        path,
-                        cache,
-                    );
+                    return Map::parse_xml(&mut parser.into_iter(), attributes, path, cache);
                 }
             }
             XmlEvent::EndDocument => {
diff --git a/src/properties.rs b/src/properties.rs
index a1e8bb0507c98728dd7406eb0af3362ecf7b02d4..63335eabaddc7a8b2876280b7c416b8700f34344 100644
--- a/src/properties.rs
+++ b/src/properties.rs
@@ -21,7 +21,11 @@ impl FromStr for Color {
     type Err = ();
 
     fn from_str(s: &str) -> std::result::Result<Color, Self::Err> {
-        let s = if s.starts_with("#") { &s[1..] } else { s };
+        let s = if let Some(stripped) = s.strip_prefix('#') {
+            stripped
+        } else {
+            s
+        };
         match s.len() {
             6 => {
                 let r = u8::from_str_radix(&s[0..2], 16);
@@ -103,7 +107,7 @@ impl PropertyValue {
                 }),
             },
             "color" if value.len() > 1 => Color::from_str(&value)
-                .map(|color| PropertyValue::ColorValue(color))
+                .map(PropertyValue::ColorValue)
                 .map_err(|_| Error::InvalidPropertyValue {
                     description: "Couldn't parse color".to_string(),
                 }),
@@ -134,15 +138,15 @@ pub(crate) fn parse_properties(
             let ((t, v_attr), k) = get_attrs!(
                 attrs,
                 optionals: [
-                    ("type", property_type, |v| Some(v)),
-                    ("value", value, |v| Some(v)),
+                    ("type", property_type, Some),
+                    ("value", value, Some),
                 ],
                 required: [
-                    ("name", key, |v| Some(v)),
+                    ("name", key, Some),
                 ],
                 Error::MalformedAttributes("property must have a name and a value".to_string())
             );
-            let t = t.unwrap_or("string".into());
+            let t = t.unwrap_or_else(|| "string".to_owned());
 
             let v: String = match v_attr {
                 Some(val) => val,
diff --git a/src/tileset.rs b/src/tileset.rs
index 41bbddd45619b85975250f27a9fb4c5cb0c505b4..d907aa7df66b1e04a718517f64b7394d0b0e34a8 100644
--- a/src/tileset.rs
+++ b/src/tileset.rs
@@ -134,7 +134,7 @@ impl Tileset {
 
     fn parse_xml_embedded(
         parser: &mut impl Iterator<Item = XmlEventResult>,
-        attrs: &Vec<OwnedAttribute>,
+        attrs: &[OwnedAttribute],
         map_path: &Path,
     ) -> Result<EmbeddedParseResult> {
         let ((spacing, margin, columns, name), (tilecount, first_gid, tile_width, tile_height)) = get_attrs!(
@@ -143,11 +143,11 @@ impl Tileset {
                 ("spacing", spacing, |v:String| v.parse().ok()),
                 ("margin", margin, |v:String| v.parse().ok()),
                 ("columns", columns, |v:String| v.parse().ok()),
-                ("name", name, |v| Some(v)),
+                ("name", name, Some),
             ],
            required: [
                 ("tilecount", tilecount, |v:String| v.parse().ok()),
-                ("firstgid", first_gid, |v:String| v.parse().ok().map(|n| Gid(n))),
+                ("firstgid", first_gid, |v:String| v.parse().ok().map(Gid)),
                 ("tilewidth", width, |v:String| v.parse().ok()),
                 ("tileheight", height, |v:String| v.parse().ok()),
             ],
@@ -176,14 +176,14 @@ impl Tileset {
     }
 
     fn parse_xml_reference(
-        attrs: &Vec<OwnedAttribute>,
+        attrs: &[OwnedAttribute],
         map_path: &Path,
     ) -> Result<EmbeddedParseResult> {
         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)),
+                ("firstgid", first_gid, |v:String| v.parse().ok().map(Gid)),
+                ("source", name, Some),
             ],
             Error::MalformedAttributes("Tileset reference must have a firstgid and source with correct types".to_string())
         );
@@ -198,7 +198,7 @@ impl Tileset {
 
     pub(crate) fn parse_external_tileset(
         parser: &mut impl Iterator<Item = XmlEventResult>,
-        attrs: &Vec<OwnedAttribute>,
+        attrs: &[OwnedAttribute],
         path: &Path,
     ) -> Result<Tileset> {
         let ((spacing, margin, columns, name), (tilecount, tile_width, tile_height)) = get_attrs!(
@@ -207,7 +207,7 @@ impl Tileset {
                 ("spacing", spacing, |v:String| v.parse().ok()),
                 ("margin", margin, |v:String| v.parse().ok()),
                 ("columns", columns, |v:String| v.parse().ok()),
-                ("name", name, |v| Some(v)),
+                ("name", name, Some),
             ],
             required: [
                 ("tilecount", tilecount, |v:String| v.parse().ok()),
@@ -296,9 +296,11 @@ impl Tileset {
     ) -> Result<u32> {
         image
             .as_ref()
-            .ok_or(Error::MalformedAttributes(
-                "No <image> nor columns attribute in <tileset>".to_string(),
-            ))
-            .and_then(|image| Ok((image.width as u32 - margin + spacing) / (tile_width + spacing)))
+            .map(|image| (image.width as u32 - margin + spacing) / (tile_width + spacing))
+            .ok_or_else(|| {
+                Error::MalformedAttributes(
+                    "No <image> nor columns attribute in <tileset>".to_string(),
+                )
+            })
     }
 }
diff --git a/tests/lib.rs b/tests/lib.rs
index 4698c00222546cfb0024bfe1bcd032b25774cb34..1ab44a8a6ecee15191f92bca1f02a7b48db3161f 100644
--- a/tests/lib.rs
+++ b/tests/lib.rs
@@ -127,7 +127,7 @@ fn test_infinite_tileset() {
         assert_eq!(inf.get_tile(5, 36).unwrap().id(), 73);
         assert_eq!(inf.get_tile(15, 15).unwrap().id(), 22);
     } else {
-        assert!(false, "It is wrongly recognised as a finite map");
+        panic!("It is wrongly recognised as a finite map");
     }
     if let TileLayer::Infinite(inf) = &as_tile_layer(r.get_layer(0).unwrap()) {
         // NW corner
@@ -150,7 +150,7 @@ fn test_infinite_tileset() {
         assert!(inf.get_tile(32, 47).is_none());
         assert!(inf.get_tile(31, 48).is_none());
     } else {
-        assert!(false, "It is wrongly recognised as a finite map");
+        panic!("It is wrongly recognised as a finite map");
     }
 }
 
@@ -183,7 +183,7 @@ fn test_image_layers() {
             .0
             .image
             .as_ref()
-            .expect(&format!("{}'s image shouldn't be None", second.1.name));
+            .unwrap_or_else(|| panic!("{}'s image shouldn't be None", second.1.name));
         assert_eq!(image.source, PathBuf::from("assets/tilesheet.png"));
         assert_eq!(image.width, 448);
         assert_eq!(image.height, 192);