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);