From 2e0b8fd7d6bc1a620da73d9d6e88c6bee1c9c820 Mon Sep 17 00:00:00 2001 From: bendn Date: Tue, 26 Sep 2023 06:05:17 +0700 Subject: [PATCH] make functions more generic --- src/affine.rs | 66 ++++++++++++++++----------------------------- src/builder.rs | 5 +++- src/drawing/box.rs | 4 +-- src/drawing/line.rs | 15 ++++++----- src/drawing/tri.rs | 4 ++- src/lib.rs | 3 ++- src/overlay.rs | 35 +++++++++++++++--------- src/scale.rs | 1 + 8 files changed, 66 insertions(+), 67 deletions(-) diff --git a/src/affine.rs b/src/affine.rs index acab7cc..15e25f6 100644 --- a/src/affine.rs +++ b/src/affine.rs @@ -1,16 +1,8 @@ //! Manages the affine image transformations. +use std::ops::{Deref, DerefMut}; + use crate::{cloner::ImageCloner, Image}; -impl Image, CHANNELS> { - /// Flip an image horizontally. - pub fn flip_h(&mut self) { - self.as_mut().flip_h(); - } - /// Flip an image vertically. - pub fn flip_v(&mut self) { - self.as_mut().flip_v(); - } -} impl ImageCloner<'_, CHANNELS> { /// Flip an image vertically. /// ``` @@ -53,7 +45,7 @@ impl ImageCloner<'_, CHANNELS> { } } -impl Image<&mut [u8], CHANNELS> { +impl + DerefMut> Image { /// Flip an image vertically. pub fn flip_v(&mut self) { for y in 0..self.height() / 2 { @@ -89,31 +81,6 @@ impl Image<&mut [u8], CHANNELS> { } } -impl Image, CHANNELS> { - /// Rotate an image 180 degrees clockwise. - pub fn rot_180(&mut self) { - self.as_mut().rot_180(); - } - - /// Rotate an image 90 degrees clockwise. - /// # Safety - /// - /// UB if the image is not square - pub unsafe fn rot_90(&mut self) { - // SAFETY: make sure to keep the safety docs linked - unsafe { self.as_mut().rot_90() } - } - - /// Rotate an image 270 degrees clockwise, or 90 degrees anti clockwise. - /// # Safety - /// - /// UB if the image is not square - pub unsafe fn rot_270(&mut self) { - // SAFETY: idk this is just a convenience impl - unsafe { self.as_mut().rot_270() } - } -} - impl ImageCloner<'_, CHANNELS> { /// Rotate an image 180 degrees clockwise. /// @@ -164,7 +131,7 @@ impl ImageCloner<'_, CHANNELS> { } } -impl Image<&mut [u8], CHANNELS> { +impl + DerefMut> Image { /// Rotate an image 180 degrees clockwise. pub fn rot_180(&mut self) { self.flatten_mut().reverse(); @@ -199,7 +166,9 @@ impl Image<&mut [u8], CHANNELS> { /// # Safety /// /// UB if supplied image rectangular -unsafe fn transpose(img: &mut Image<&mut [u8], CHANNELS>) { +unsafe fn transpose + DerefMut>( + img: &mut Image, +) { debug_assert_eq!(img.width(), img.height()); if img.width().is_power_of_two() { // SAFETY: caller gurantees @@ -215,7 +184,12 @@ unsafe fn transpose(img: &mut Image<&mut [u8], CHANNELS>) /// # Safety /// /// UB if image not square -unsafe fn transpose_non_power_of_two(img: &mut Image<&mut [u8], CHANNELS>) { +unsafe fn transpose_non_power_of_two< + const CHANNELS: usize, + T: Deref + DerefMut, +>( + img: &mut Image, +) { debug_assert_eq!(img.width(), img.height()); let size = img.width() as usize; let b = img.flatten_mut(); @@ -234,8 +208,11 @@ const TILE: usize = 4; /// # Safety /// /// be careful -unsafe fn transpose_tile( - img: &mut Image<&mut [u8], CHANNELS>, +unsafe fn transpose_tile< + const CHANNELS: usize, + T: Deref + DerefMut, +>( + img: &mut Image, row: usize, col: usize, size: usize, @@ -270,8 +247,11 @@ unsafe fn transpose_tile( /// # Safety /// /// be careful -unsafe fn transpose_diag( - img: &mut Image<&mut [u8], CHANNELS>, +unsafe fn transpose_diag< + const CHANNELS: usize, + T: Deref + DerefMut, +>( + img: &mut Image, pos: usize, size: usize, ) { diff --git a/src/builder.rs b/src/builder.rs index be5a837..9133e36 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -12,7 +12,8 @@ impl Image { } } -/// Safe [Image] builder. +/// Safe [`Image`] builder. +#[must_use = "builder must be consumed"] pub struct Builder { /// the width in a zeroable type. zeroable so as to make the check in [`buf`] easier. width: u32, @@ -33,6 +34,7 @@ impl Builder { /// apply a buffer, and build #[track_caller] + #[must_use = "what is it going to do?"] pub fn buf(self, buffer: B) -> Image { let len = C as u32 * self.width * self.height; assert!( @@ -53,6 +55,7 @@ impl Builder { impl Builder, C> { /// allocate this image + #[must_use = "what is it going to do?"] pub fn alloc(self) -> Image, C> { Image::alloc(self.width, self.height) } diff --git a/src/drawing/box.rs b/src/drawing/box.rs index dd46efc..4893bae 100644 --- a/src/drawing/box.rs +++ b/src/drawing/box.rs @@ -1,9 +1,9 @@ //! `Box` -use std::ops::Range; +use std::ops::{Deref, DerefMut, Range}; use crate::Image; -impl Image<&mut [u8], CHANNELS> { +impl + DerefMut, const CHANNELS: usize> Image { /// Draw a bordered box /// ``` /// # use fimg::Image; diff --git a/src/drawing/line.rs b/src/drawing/line.rs index c48f923..81fe162 100644 --- a/src/drawing/line.rs +++ b/src/drawing/line.rs @@ -1,9 +1,12 @@ //! adds a `line` function to Image #![allow(clippy::missing_docs_in_private_items)] use crate::Image; -use std::iter::Iterator; +use std::{ + iter::Iterator, + ops::{Deref, DerefMut}, +}; -/// taken from https://github.com/mbr/bresenham-rs/ +/// taken from [bresenham-rs](https://github.com/mbr/bresenham-rs) pub struct Bresenham { x: i32, y: i32, @@ -19,7 +22,7 @@ struct Octant(u8); impl Octant { #[inline] - const fn from_points(start: (i32, i32), end: (i32, i32)) -> Octant { + const fn from_points(start: (i32, i32), end: (i32, i32)) -> Self { let mut dx = end.0 - start.0; let mut dy = end.1 - start.1; @@ -35,11 +38,11 @@ impl Octant { let tmp = dx; dx = dy; dy = -tmp; - octant += 2 + octant += 2; } if dx < dy { - octant += 1 + octant += 1; } Octant(octant) @@ -127,7 +130,7 @@ impl Iterator for Bresenham { } } -impl Image<&mut [u8], CHANNELS> { +impl + DerefMut, const CHANNELS: usize> Image { /// Draw a line from point a to point b /// /// Points not in bounds will not be included. diff --git a/src/drawing/tri.rs b/src/drawing/tri.rs index 7aa3493..c4d2d6c 100644 --- a/src/drawing/tri.rs +++ b/src/drawing/tri.rs @@ -1,7 +1,9 @@ //! trongle drawing +use std::ops::{Deref, DerefMut}; + use crate::Image; -impl Image<&mut [u8], CHANNELS> { +impl + DerefMut, const CHANNELS: usize> Image { /// Draw a (filled) triangle /// ``` /// # use fimg::*; diff --git a/src/lib.rs b/src/lib.rs index 8243b46..3b62765 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -60,6 +60,7 @@ impl Image<&[u8], 3> { /// # Safety /// /// UB if self's width is not a multiple of x, or self's height is not a multiple of y + #[must_use = "function does not modify the original image"] pub unsafe fn repeated(&self, x: u32, y: u32) -> Image, 3> { let mut img = Image::alloc(x, y); // could probably optimize this a ton but eh for x in 0..(x / self.width()) { @@ -448,6 +449,6 @@ mod tests { #[test] fn repeat() { let x: Image<&[u8], 3> = Image::build(8, 8).buf(include_bytes!("../benches/3_8x8.imgbuf")); - unsafe { x.repeated(128, 128) }; // repeat 16 times + let _ = unsafe { x.repeated(128, 128) }; // repeat 16 times } } diff --git a/src/overlay.rs b/src/overlay.rs index ba63b74..4165399 100644 --- a/src/overlay.rs +++ b/src/overlay.rs @@ -2,9 +2,8 @@ use crate::cloner::ImageCloner; use super::{assert_unchecked, really_unsafe_index, Image}; -use std::simd::SimdInt; -use std::simd::SimdPartialOrd; -use std::simd::{simd_swizzle, Simd}; +use std::ops::{Deref, DerefMut}; +use std::simd::{simd_swizzle, Simd, SimdInt, SimdPartialOrd}; /// Trait for layering a image ontop of another, with a offset to the second image. pub trait OverlayAt { @@ -101,9 +100,11 @@ unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) { } } -impl Overlay> for Image<&mut [u8], 4> { +impl + DerefMut, U: Deref> + Overlay> for Image +{ #[inline] - unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { + unsafe fn overlay(&mut self, with: &Image) -> &mut Self { debug_assert!(self.width() == with.width()); debug_assert!(self.height() == with.height()); for (i, other_pixels) in with.chunked().enumerate() { @@ -128,9 +129,11 @@ impl ClonerOverlay<4, 4> for ImageCloner<'_, 4> { } } -impl OverlayAt> for Image<&mut [u8], 3> { +impl + DerefMut, U: Deref> + OverlayAt> for Image +{ #[inline] - unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self { + unsafe fn overlay_at(&mut self, with: &Image, x: u32, y: u32) -> &mut Self { // SAFETY: caller upholds this unsafe { assert_unchecked!(x + with.width() <= self.width()) }; debug_assert!(y + with.height() <= self.height()); @@ -164,7 +167,9 @@ impl ClonerOverlayAt<4, 3> for ImageCloner<'_, 3> { } } -impl OverlayAt> for Image<&mut [u8], 3> { +impl + DerefMut, U: Deref> + OverlayAt> for Image +{ /// Overlay a RGB image(with) => self at coordinates x, y. /// As this is a `RGBxRGB` operation, blending is unnecessary, /// and this is simply a copy. @@ -173,7 +178,7 @@ impl OverlayAt> for Image<&mut [u8], 3> { /// /// UB if x, y is out of bounds #[inline] - unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self { + unsafe fn overlay_at(&mut self, with: &Image, x: u32, y: u32) -> &mut Self { /// helper macro for defining rgb=>rgb overlays. allows unrolling macro_rules! o3x3 { ($n:expr) => {{ @@ -203,9 +208,11 @@ impl OverlayAt> for Image<&mut [u8], 3> { } } -impl Overlay> for Image<&mut [u8], 3> { +impl + DerefMut, U: Deref> + Overlay> for Image +{ #[inline] - unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self { + unsafe fn overlay(&mut self, with: &Image) -> &mut Self { debug_assert!(self.width() == with.width()); debug_assert!(self.height() == with.height()); for (i, chunk) in with @@ -237,7 +244,9 @@ impl ClonerOverlay<4, 3> for ImageCloner<'_, 3> { } } -impl OverlayAt> for Image<&mut [u8], 4> { +impl + DerefMut, U: Deref> + OverlayAt> for Image +{ #[inline] /// Overlay with => self at coordinates x, y, without blending /// @@ -245,7 +254,7 @@ impl OverlayAt> for Image<&mut [u8], 4> { /// - UB if x, y is out of bounds /// - UB if x + with.width() > [`u32::MAX`] /// - UB if y + with.height() > [`u32::MAX`] - unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self { + unsafe fn overlay_at(&mut self, with: &Image, x: u32, y: u32) -> &mut Self { for j in 0..with.height() { for i in 0..with.width() { // SAFETY: i, j is in bounds. diff --git a/src/scale.rs b/src/scale.rs index 09fdf20..36165f7 100644 --- a/src/scale.rs +++ b/src/scale.rs @@ -9,6 +9,7 @@ impl Nearest { /// # Safety /// /// `image` must be as big or bigger than `width`, `height. + #[must_use = "function does not modify the original image"] pub unsafe fn scale( image: Image<&[u8], N>, width: u32,