fast image operations
Diffstat (limited to 'src/builder.rs')
-rw-r--r--src/builder.rs80
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())
}
}