vyre-wgpu 0.1.0

wgpu backend for vyre IR — implements VyreBackend, owns GPU runtime, buffer pool, pipeline cache
Documentation
//! Safe bytemuck casting utilities for GPU buffer boundaries.

use core::fmt;

/// Error type for [`safe_cast_slice`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CastError {
    /// The byte slice length is not a multiple of the target type size.
    NotMultiple,
    /// The byte slice alignment does not match the target type alignment.
    Misaligned,
}

impl fmt::Display for CastError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::NotMultiple => write!(
                f,
                "byte slice length is not a multiple of the target type size. Fix: align the buffer size to the element size."
            ),
            Self::Misaligned => write!(
                f,
                "byte slice alignment does not match the target type alignment. Fix: use an aligned buffer or copy to an aligned Vec."
            ),
        }
    }
}

impl std::error::Error for CastError {}

/// Safely cast a byte slice to a slice of `T`.
pub fn safe_cast_slice<T: bytemuck::Pod>(bytes: &[u8]) -> Result<&[T], CastError> {
    let size = core::mem::size_of::<T>();
    if size == 0 {
        return Ok(bytemuck::cast_slice(bytes));
    }
    if bytes.len() % size != 0 {
        return Err(CastError::NotMultiple);
    }
    if bytes.as_ptr().align_offset(core::mem::align_of::<T>()) != 0 {
        return Err(CastError::Misaligned);
    }
    Ok(bytemuck::cast_slice(bytes))
}

/// Safely expose a typed Pod slice as bytes.
#[must_use]
pub fn safe_bytes_of_slice<T: bytemuck::Pod>(values: &[T]) -> &[u8] {
    bytemuck::cast_slice(values)
}