logo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use crate::Error;
use macaw::{ColorRgba8, Vec2};

// TODO: Move transmute_slice elsewhere?

/// Convert e.g. &[Vec2] to twice as long slice of &[f32], or the inverse.
/// You can ONLY use this safely on types where all bit patterns are a valid value of the [`Target`] type.
/// This means it is NOT safe to use with e.g. an `enum`.
#[allow(clippy::integer_division)]
pub(crate) unsafe fn transmute_slice<Target: Copy, Source>(
    source: &[Source],
) -> Result<&[Target], Error> {
    use std::mem::size_of;

    let target_len = source.len() * size_of::<Source>() / size_of::<Target>();

    if target_len * size_of::<Target>() == source.len() * size_of::<Source>() {
        Ok(unsafe { std::slice::from_raw_parts(source.as_ptr().cast::<Target>(), target_len) })
    } else {
        // Source slice length is not an even multiple of the target
        Err(Error::InvalidArguments)
    }
}

pub(crate) fn f32_slice_from_vec2(source: &[Vec2]) -> &[f32] {
    static_assertions::assert_eq_size!(Vec2, [f32; 2]);
    unsafe { transmute_slice(source) }.unwrap()
}

pub(crate) fn u8_slice_from_srgba(source: &[ColorRgba8]) -> &[u8] {
    static_assertions::assert_eq_size!(ColorRgba8, [u8; 4]);
    unsafe { transmute_slice(source) }.unwrap()
}

pub(crate) fn u32_slice_from_triangle_index(source: &[[u32; 3]]) -> &[u32] {
    unsafe { transmute_slice(source) }.unwrap()
}