//! safe builder for the image //! //! does not let you do funny things use std::marker::PhantomData; use crate::Image; impl Image { /// creates a builder pub const fn build(w: u32, h: u32) -> Builder { Builder::new(w, h) } } /// Safe [Image] builder. pub struct Builder { /// the width in a zeroable type. zeroable so as to make the check in [`buf`] easier. width: u32, /// the height in a zeroable type. height: u32, #[allow(clippy::missing_docs_in_private_items)] _buffer: PhantomData, } impl Builder { /// create new builder pub const fn new(w: u32, h: u32) -> Self { Self { width: w, height: h, _buffer: PhantomData, } } /// apply a buffer, and build #[track_caller] pub fn buf(self, buffer: B) -> Image { let len = C as u32 * self.width * self.height; assert!( buffer.len() as u32 == len, "invalid buffer size (expected {len}, got {})", buffer.len() ); Image { buffer, width: self.width.try_into().expect("passed zero width to builder"), height: self .height .try_into() .expect("passed zero height to builder"), } } } impl Builder, C> { /// allocate this image pub fn alloc(self) -> Image, 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 Buffer for Vec { fn len(&self) -> usize { self.len() } } impl Buffer for &[T] { fn len(&self) -> usize { <[T]>::len(self) } } impl Buffer for &mut [T] { fn len(&self) -> usize { <[T]>::len(self) } } impl Buffer for [T; N] { fn len(&self) -> usize { N } } impl Buffer for &[T; N] { fn len(&self) -> usize { N } } impl Buffer for &mut [T; N] { fn len(&self) -> usize { N } } }