fast image operations
Diffstat (limited to 'src/builder.rs')
| -rw-r--r-- | src/builder.rs | 80 |
1 files changed, 37 insertions, 43 deletions
diff --git a/src/builder.rs b/src/builder.rs index be5a837..ec0e518 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -5,14 +5,18 @@ use std::marker::PhantomData; use crate::Image; -impl<B: buf::Buffer, const C: usize> Image<B, C> { +impl<B, const C: usize> Image<B, C> { /// creates a builder - pub const fn build(w: u32, h: u32) -> Builder<B, C> { + pub const fn build<I>(w: u32, h: u32) -> Builder<B, C> + where + B: AsRef<[I]>, + { Builder::new(w, h) } } -/// Safe [Image] builder. +/// Safe [`Image`] builder. +#[must_use = "builder must be consumed"] pub struct Builder<B, const C: usize> { /// the width in a zeroable type. zeroable so as to make the check in [`buf`] easier. width: u32, @@ -21,7 +25,7 @@ pub struct Builder<B, const C: usize> { #[allow(clippy::missing_docs_in_private_items)] _buffer: PhantomData<B>, } -impl<B: buf::Buffer, const C: usize> Builder<B, C> { +impl<B, const C: usize> Builder<B, C> { /// create new builder pub const fn new(w: u32, h: u32) -> Self { Self { @@ -33,13 +37,27 @@ impl<B: buf::Buffer, const C: usize> Builder<B, C> { /// apply a buffer, and build #[track_caller] - pub fn buf(self, buffer: B) -> Image<B, C> { + #[must_use = "what is it going to do?"] + pub fn buf<I>(self, buffer: B) -> Image<B, C> + where + B: AsRef<[I]>, + { let len = C as u32 * self.width * self.height; assert!( - buffer.len() as u32 == len, + buffer.as_ref().len() as u32 == len, "invalid buffer size (expected {len}, got {})", - buffer.len() + buffer.as_ref().len() ); + // SAFETY: checked! + unsafe { self.buf_unchecked(buffer) } + } + /// apply a buffer, and build (length unchecked) + #[track_caller] + #[must_use = "what is it going to do?"] + pub unsafe fn buf_unchecked<I>(self, buffer: B) -> Image<B, C> + where + B: AsRef<[I]>, + { Image { buffer, width: self.width.try_into().expect("passed zero width to builder"), @@ -53,46 +71,22 @@ impl<B: buf::Buffer, const C: usize> Builder<B, C> { impl<const C: usize> Builder<Vec<u8>, C> { /// allocate this image + #[must_use = "what is it going to do?"] pub fn alloc(self) -> Image<Vec<u8>, C> { Image::alloc(self.width, self.height) } } -/// seals the [`Buffer`] trait -mod buf { - /// A valid buffer for use in the builder - pub trait Buffer { - #[doc(hidden)] - fn len(&self) -> usize; - } - impl<T> Buffer for Vec<T> { - fn len(&self) -> usize { - self.len() - } - } - impl<T> Buffer for &[T] { - fn len(&self) -> usize { - <[T]>::len(self) - } - } - impl<T> Buffer for &mut [T] { - fn len(&self) -> usize { - <[T]>::len(self) - } - } - impl<T, const N: usize> Buffer for [T; N] { - fn len(&self) -> usize { - N - } - } - impl<T, const N: usize> Buffer for &[T; N] { - fn len(&self) -> usize { - N - } - } - impl<T, const N: usize> Buffer for &mut [T; N] { - fn len(&self) -> usize { - N - } +impl<T: Copy, const C: usize> Builder<Box<[T]>, C> { + /// Fill this image with a certain pixel. + /// ``` + /// # use fimg::Image; + /// + /// // fill black + /// Image::build(50, 50).fill([0, 0, 0, 255]); + /// ``` + pub fn fill(self, with: [T; C]) -> Image<Box<[T]>, C> { + Image::build(self.width, self.height) + .buf((0..self.width * self.height).flat_map(|_| with).collect()) } } |