diff --git a/src/lib.rs b/src/lib.rs index ab81fcd..4bf92f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,14 @@ //! } //! ``` +#![warn(clippy::pedantic)] +#![allow( + clippy::similar_names, + clippy::needless_doctest_main, + clippy::module_name_repetitions, + clippy::missing_errors_doc +)] + pub mod physics; pub mod vec2; @@ -100,7 +108,7 @@ use sdl2::{ render::{Canvas, TextureCreator, TextureValueError}, rwops::RWops, surface::Surface, - ttf::{FontError, Sdl2TtfContext}, + ttf::{FontError, InitError, Sdl2TtfContext}, video::{Window, WindowBuildError, WindowContext}, EventPump, IntegerOrSdlError, }; @@ -125,37 +133,33 @@ macro_rules! cloned { } } +macro_rules! error_from_format { + ($($t:ty),+) => { + $( + impl From<$t> for CatboxError { + fn from(e: $t) -> Self { + CatboxError(format!("{}", e)) + } + } + )+ + }; +} + #[derive(Debug)] pub struct CatboxError(String); -impl From for CatboxError { - fn from(e: WindowBuildError) -> Self { - CatboxError(format!("{}", e)) - } -} - impl From for CatboxError { fn from(e: String) -> Self { CatboxError(e) } } -impl From for CatboxError { - fn from(e: IntegerOrSdlError) -> Self { - CatboxError(format!("{}", e)) - } -} - -impl From for CatboxError { - fn from(e: TextureValueError) -> Self { - CatboxError(format!("{}", e)) - } -} - -impl From for CatboxError { - fn from(e: FontError) -> Self { - CatboxError(format!("{}", e)) - } +error_from_format! { + WindowBuildError, + IntegerOrSdlError, + TextureValueError, + FontError, + InitError } pub type Result = std::result::Result; @@ -301,6 +305,7 @@ impl Sprite { /// # let s = Sprite::new("duck.png", 500, 400).unwrap(); /// let angle = s.angle(); /// ``` + #[must_use] pub fn angle(&self) -> f64 { self.angle } @@ -312,6 +317,7 @@ impl Sprite { /// # let s = Sprite::new("duck.png", 500, 400).unwrap(); /// let (x, y) = s.position().into(); /// ``` + #[must_use] pub fn position(&self) -> Vec2Int { self.rect.center().into() } @@ -321,6 +327,7 @@ impl Sprite { /// /// Technically, this is a thin wrapper around a simple [`Vec`] of sprites, /// although with some convenience methods. +#[derive(Default)] pub struct SpriteCollection { v: Vec, } @@ -333,6 +340,7 @@ impl SpriteCollection { /// # use cat_box::*; /// let sprites = SpriteCollection::new(); /// ``` + #[must_use] pub fn new() -> Self { Self { v: Vec::new() } } @@ -344,6 +352,7 @@ impl SpriteCollection { /// # use cat_box::*; /// let sprites = SpriteCollection::with_capacity(10); /// ``` + #[must_use] pub fn with_capacity(cap: usize) -> Self { Self { v: Vec::with_capacity(cap), @@ -361,7 +370,7 @@ impl SpriteCollection { /// # }); /// ``` pub fn draw(&mut self, ctx: &mut Context) -> Result<()> { - for s in self.v.iter_mut() { + for s in &mut self.v { s.draw(ctx)?; } @@ -449,6 +458,7 @@ impl SpriteCollection { } /// Returns the length of this vector. + #[must_use] pub fn len(&self) -> usize { self.v.len() } @@ -461,14 +471,21 @@ impl SpriteCollection { /// # sprites.push(s); /// let s = sprites.get(0); /// ``` + #[must_use] pub fn get(&self, index: usize) -> Option<&Sprite> { self.v.get(index) } /// Return the inner Vec. Only use this method if you know what you're doing. + #[must_use] pub fn inner(&self) -> &Vec { &self.v } + + #[must_use] + pub fn is_empty(&self) -> bool { + self.v.is_empty() + } } impl Deref for SpriteCollection { @@ -550,6 +567,7 @@ impl Context { } /// Set the mode for drawing text. +#[derive(Clone, Copy, Debug)] pub enum TextMode { /// Render the text transparently. Transparent { colour: (u8, u8, u8) }, @@ -686,6 +704,7 @@ impl Game { /// Game::new("cool game", 1000, 1000); /// ``` /// + #[must_use] pub fn new(title: &str, width: u32, height: u32) -> Self { Self { title: title.to_string(), @@ -716,7 +735,7 @@ impl Game { .build()?; let canvas = window.into_canvas().build()?; - let s = sdl2::ttf::init().unwrap(); + let s = sdl2::ttf::init()?; let event_pump = sdl_context.event_pump()?; diff --git a/src/main.rs b/src/main.rs index 9759899..77599ea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![warn(clippy::pedantic)] + use cat_box::{draw_text, get_keyboard_state, get_mouse_state, Game, Sprite, SpriteCollection}; use sdl2::keyboard::Scancode; @@ -39,7 +41,7 @@ fn main() { let x_diff = m.x - start_x; let y_diff = m.y - start_y; - let angle = (y_diff as f64).atan2(x_diff as f64); + let angle = f64::from(y_diff).atan2(f64::from(x_diff)); s.set_angle(angle.to_degrees()); for spr in coll.iter() { @@ -48,7 +50,7 @@ fn main() { let x_diff = m.x - start_x; let y_diff = m.y - start_y; - let angle = (y_diff as f64).atan2(x_diff as f64); + let angle = f64::from(y_diff).atan2(f64::from(x_diff)); spr.set_angle(angle.to_degrees()); } diff --git a/src/physics.rs b/src/physics.rs index 0463ea9..853c369 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -2,6 +2,8 @@ //! //! Still ***very much work-in-progress*** +#![allow(clippy::cast_possible_wrap)] + use crate::{Sprite, SpriteCollection}; use std::cmp::max; @@ -28,16 +30,18 @@ fn collided(sprite1: &Sprite, sprite2: &Sprite) -> bool { return false; } - return sprite1.rect.has_intersection(sprite2.rect); + sprite1.rect.has_intersection(sprite2.rect) } /// Check if two sprites are touching or overlapping. +#[must_use] pub fn check_for_collision(sprite1: &Sprite, sprite2: &Sprite) -> bool { collided(sprite1, sprite2) } /// Check if the sprite is colliding with any sprite in the collection, and return a list of /// references to the sprites which are colliding +#[must_use] pub fn check_for_collision_with_collection<'a>( sprite: &Sprite, list: &'a SpriteCollection, diff --git a/src/vec2.rs b/src/vec2.rs index 7e1bee9..5b2366b 100644 --- a/src/vec2.rs +++ b/src/vec2.rs @@ -34,11 +34,13 @@ pub enum Direction { #[allow(clippy::enum_glob_use)] impl Direction { /// Flips this `Direction` around both the x- and y-axes. + #[must_use] pub fn flipped(self) -> Self { self.flip_x().flip_y() } /// Flips this `Direction` around the x-axis. + #[must_use] pub fn flip_x(self) -> Self { use Direction::*; match self { @@ -49,6 +51,7 @@ impl Direction { } /// Flips this `Direction` around the y-axis. + #[must_use] pub fn flip_y(self) -> Self { use Direction::*; match self { @@ -144,6 +147,7 @@ impl Vec2 { /// Creates a new `Vec2` with the given x- and y-values. /// /// It is often simpler, and preferred, to just write `(x, y).into()`. + #[must_use] pub const fn new(x: f32, y: f32) -> Vec2 { Self { x, y } } @@ -151,11 +155,13 @@ impl Vec2 { /// Gets the squared magnitude of the vector. /// /// Useful for comparisons as it is faster to calculate than `magnitude`. + #[must_use] pub fn sq_magnitude(self) -> f32 { self.x * self.x + self.y * self.y } /// Gets the magnitude of the vector. + #[must_use] pub fn magnitude(self) -> f32 { self.sq_magnitude().sqrt() } @@ -163,16 +169,19 @@ impl Vec2 { /// Gets the squared distance from this vector to `rhs`. /// /// Useful for comparisons as it is faster to calculate than `dist`. + #[must_use] pub fn sq_dist(self, rhs: Self) -> f32 { (self - rhs).sq_magnitude() } /// Gets the distance from this vector to `rhs`. + #[must_use] pub fn dist(self, rhs: Self) -> f32 { (self - rhs).magnitude() } /// Normalizes the vector, making its magnitude `1`. + #[must_use] pub fn normalized(self) -> Self { self / self.magnitude() } @@ -180,6 +189,7 @@ impl Vec2 { /// Rounds the vector to a [`Vec2Int`]. /// /// This uses `as i32` under the hood, and as such comes with all the same unfortunate edge cases. Beware. + #[must_use] pub fn rounded(self) -> Vec2Int { #[allow(clippy::cast_possible_truncation)] Vec2Int { @@ -333,6 +343,7 @@ impl Vec2Int { /// Creates a new `Vec2` with the given x- and y-values. /// /// It is often simpler, and preferred, to just write `(x, y).into()`. + #[must_use] pub const fn new(x: i32, y: i32) -> Vec2Int { Self { x, y } } @@ -340,11 +351,13 @@ impl Vec2Int { /// Gets the squared magnitude of the vector. /// /// Useful for comparisons as it is faster to calculate than `magnitude`. + #[must_use] pub fn sq_magnitude(self) -> i32 { self.x * self.x + self.y * self.y } /// Gets the magnitude of the vector. + #[must_use] pub fn magnitude(self) -> f32 { #[allow(clippy::cast_precision_loss)] (self.sq_magnitude() as f32).sqrt() @@ -353,11 +366,13 @@ impl Vec2Int { /// Gets the squared distance from this vector to `rhs`. /// /// Useful for comparisons as it is faster to calculate than `dist`. + #[must_use] pub fn sq_dist(self, rhs: Self) -> i32 { (self - rhs).sq_magnitude() } /// Gets the distance from this vector to `rhs`. + #[must_use] pub fn dist(self, rhs: Self) -> f32 { (self - rhs).magnitude() } @@ -365,6 +380,7 @@ impl Vec2Int { /// Casts this vector to a [`Vec2`]. /// /// This uses `as f32` under the hood, and as such comes with all the same unfortunate edge cases. Beware. + #[must_use] pub fn to_f32(self) -> Vec2 { #[allow(clippy::cast_precision_loss)] Vec2 {