mewgpu 3.7.3

Maybe Easier Wgpu (mew), a thin abstraction over wgpu's chaos
//! Vertex buffers are packed a lot more tightly than storage/uniform buffers,
//! requiring different alignment. The naming convention also follows that of
//! [`wgpu::VertexFormat`](https://docs.rs/wgpu/latest/wgpu/enum.VertexFormat.html)
//! rather than _wgsl_-looking types, because that's what
//! [`wgpu::vertex_attr_array!`](https://docs.rs/wgpu/latest/wgpu/macro.vertex_attr_array.html)
//! takes.
//!
//! All these types are internally represented by arrays. For example
//! [`Float32x3`] is just a unit struct over `[f32; 3]`, but a single `[Float32]`
//! is also an array of length 1 (`[f32; 1]`). Of course you can deref them into
//! regular arrays, but keep in mind that's not what they directly are.
//!
//! ```
//! // There shouldn't be a reason to construct these explicitly, just pass
//! // arrays into vertex struct constructors, but for the sake of the example
//! let mut float32_3: Float32x3 = [1.0, 2.0, 3.0].into();
//! *float32_3 = [3.0, 2.0, 1.0];
//! float32_3[2] = 0.0;
//! let bytes: &[u32] = float32_3.as_ref();
//! ```

use std::ops::{ Deref, DerefMut, };


macro_rules! vertex_format {
    { @if_not_u8 $name:ident u8 } => {
    };
    { @if_not_u8 $name:ident $ty:ident } => {
        impl From<[u8; Self::BYTES]> for $name {
            fn from(bytes: [u8; Self::BYTES]) -> Self {
                Self::from_bytes(bytes)
            }
        }
    };

    { $name:ident [ $ty:ident ; $len:literal ] } => {
        /// Auto-generated wrapper representing a
        /// [`wgpu::VertexFormat`](https://docs.rs/wgpu/latest/wgpu/enum.VertexFormat.html).
        #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
        //#[repr(align(1))]
        #[repr(transparent)]
        pub struct $name([$ty; $len]);

        impl $name {
            pub const BYTES: usize = size_of::<$ty>() * $len;
            //const PADDING: usize = Self::BYTES.next_multiple_of($crate::wgpu::VERTEX_STRIDE_ALIGNMENT as usize) - Self::BYTES;
        }

        impl $crate::vertexformat::MewVertexFormat for $name {
            type Bytes = [u8; Self::BYTES];
            type Inner = [$ty; $len];

            fn from_inner(inner: Self::Inner) -> Self {
                //value.iter_mut().for_each(|val| *val = ::std::mem::transmute(val.to_le_bytes()));
                Self(inner)
            }

            fn from_bytes(bytes: Self::Bytes) -> Self {
                #[allow(clippy::useless_transmute)]
                unsafe { Self(::std::mem::transmute::<[u8; Self::BYTES], [$ty; $len]>(bytes)) }
            }

            fn zeroed() -> Self {
                unsafe { Self(::std::mem::zeroed()) }
            }
        }

        impl From<[$ty; $len]> for $name {
            fn from(inner: [$ty; $len]) -> Self {
                Self::from_inner(inner)
            }
        }
        vertex_format! { @if_not_u8 $name $ty }

        impl Deref for $name {
            type Target = [$ty; $len];
            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }
        impl DerefMut for $name {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.0
            }
        }

        impl AsRef<[u8; Self::BYTES]> for $name {
            fn as_ref(&self) -> &[u8; Self::BYTES] {
                unsafe { &*(&raw const self.0).cast() }
            }
        }
        impl AsMut<[u8; Self::BYTES]> for $name {
            fn as_mut(&mut self) -> &mut [u8; Self::BYTES] {
                unsafe { &mut *(&raw mut self.0).cast() }
            }
        }

        impl Default for $name {
            fn default() -> Self {
                Self::zeroed()
            }
        }
    };
}

vertex_format! { Uint8 [u8; 1] }  // => 1 }
vertex_format! { Uint8x2 [u8; 2] }  // => 2 }
vertex_format! { Uint8x4 [u8; 4] }  // => 4 }
vertex_format! { Sint8 [i8; 1] }  // => 1 }
vertex_format! { Sint8x2 [i8; 2] }  // => 2 }
vertex_format! { Sint8x4 [i8; 4] }  // => 4 }

vertex_format! { Unorm8 [u8; 1] }  // => 1 }
vertex_format! { Unorm8x2 [u8; 2] }  // => 2 }
vertex_format! { Unorm8x4 [u8; 4] }  // => 4 }
vertex_format! { Snorm8 [i8; 1] }  // => 1 }
vertex_format! { Snorm8x2 [i8; 2] }  // => 2 }
vertex_format! { Snorm8x4 [i8; 4] }  // => 4 }


vertex_format! { Uint16 [u16; 1] }  // => 2 }
vertex_format! { Uint16x2 [u16; 2] }  // => 4 }
vertex_format! { Uint16x4 [u16; 4] }  // => 8 }
vertex_format! { Sint16 [i16; 1] }  // => 2 }
vertex_format! { Sint16x2 [i16; 2] }  // => 4 }
vertex_format! { Sint16x4 [i16; 4] }  // => 8 }

vertex_format! { Unorm16 [u16; 1] }  // => 2 }
vertex_format! { Unorm16x2 [u16; 2] }  // => 4 }
vertex_format! { Unorm16x4 [u16; 4] }  // => 8 }
vertex_format! { Snorm16 [i16; 1] }  // => 2 }
vertex_format! { Snorm16x2 [i16; 2] }  // => 4 }
vertex_format! { Snorm16x4 [i16; 4] }  // => 8 }

vertex_format! { Float16 [u16; 1] }  // => 2 }
vertex_format! { Float16x2 [u16; 2] }  // => 4 }
vertex_format! { Float16x4 [u16; 4] }  // => 8 }


vertex_format! { Uint32 [u32; 1] }  // => 4 }
vertex_format! { Uint32x2 [u32; 2] }  // => 8 }
vertex_format! { Uint32x3 [u32; 3] }  // => 16 }
vertex_format! { Uint32x4 [u32; 4] }  // => 16 }
vertex_format! { Sint32 [i32; 1] }  // => 4 }
vertex_format! { Sint32x2 [i32; 2] }  // => 8 }
vertex_format! { Sint32x3 [i32; 3] }  // => 16 }
vertex_format! { Sint32x4 [i32; 4] }  // => 16 }

vertex_format! { Float32 [f32; 1] }  // => 4 }
vertex_format! { Float32x2 [f32; 2] }  // => 4 }
vertex_format! { Float32x3 [f32; 3] }  // => 8 }
vertex_format! { Float32x4 [f32; 4] }  // => 8 }


vertex_format! { Float64 [f64; 1] }  // => 8 }
vertex_format! { Float64x2 [f64; 2] }  // => 16 }
vertex_format! { Float64x3 [f64; 3] }  // => 16 }
vertex_format! { Float64x4 [f64; 4] }  // => 16 }


pub type Unorm10_10_10_2 = Uint32;
pub type Unorm8x4Bgra = Unorm8x4;


pub trait MewVertexFormat {
    type Bytes;
    type Inner;
    fn from_inner(inner: Self::Inner) -> Self;
    fn from_bytes(bytes: Self::Bytes) -> Self;
    fn zeroed() -> Self;
}