ombre 0.6.7

Shadowy game and graphics library for Rust
Documentation
//! Byte slices.
use std::{any, mem, slice};

/// Used when an empty [`AsBytes`] instance is needed.
#[derive(Debug, Clone, Copy, Default)]
pub struct Empty;

/// Marker trait for types that are packed and can be safely
/// converted to a byte slice.
///
/// # Safety
///
/// Types which derive `repr(C)` can safely implement this trait.
pub unsafe trait Packed {}

/// Types that can be represented as a `u8` slice.
///
/// # Safety
///
/// This trait should only be implemented if the type can be safely
/// converted to a slice.
pub trait AsBytes {
    /// Return a byte slice representation.
    fn as_bytes(&self) -> &[u8];
}

impl AsBytes for () {
    fn as_bytes(&self) -> &[u8] {
        &[]
    }
}

impl AsBytes for Empty {
    fn as_bytes(&self) -> &[u8] {
        &[]
    }
}

impl<T> AsBytes for &[T] {
    fn as_bytes(&self) -> &[u8] {
        let (head, aligned, tail) = unsafe { self.align_to::<u8>() };

        assert!(head.is_empty());
        assert!(tail.is_empty());

        aligned
    }
}

impl<T> AsBytes for T
where
    T: Packed,
{
    fn as_bytes(&self) -> &[u8] {
        unsafe { slice::from_raw_parts(self as *const Self as *const u8, mem::size_of::<Self>()) }
    }
}

/// Types that can be represented as a mutable `u8` slice.
pub trait AsBytesMut {
    /// Return a mutable byte slice representation.
    fn as_bytes_mut(&mut self) -> &mut [u8];
}

impl<T> AsBytesMut for &mut [T] {
    fn as_bytes_mut(&mut self) -> &mut [u8] {
        let (head, aligned, tail) = unsafe { self.align_to_mut::<u8>() };

        assert!(head.is_empty());
        assert!(tail.is_empty());

        aligned
    }
}

/// Align a byte slice to any slice type.
///
/// # Panics
///
/// If the byte slice length is not a multiple of the size of a `T`.
pub fn align_to<T>(bytes: &[u8]) -> &[T] {
    if bytes.len() % mem::size_of::<T>() != 0 {
        panic!(
            "{}::align_to: byte slice length {} is not a multiple of the size of a {}",
            module_path!(),
            bytes.len(),
            any::type_name::<T>()
        );
    }
    let ptr = bytes.as_ptr() as *const T;
    let len = bytes.len() / mem::size_of::<T>();

    unsafe { slice::from_raw_parts(ptr, len) }
}