use bytemuck::Pod;
pub trait Transparent: Pod {
type Wrapped: Pod;
#[inline(always)]
fn wrap(x: Self::Wrapped) -> Self {
bytemuck::must_cast(x)
}
fn peel(x: Self) -> Self::Wrapped {
bytemuck::must_cast(x)
}
fn peel_copy(x: &Self) -> Self::Wrapped {
bytemuck::must_cast(*x)
}
}
pub fn wrap<T: Transparent>(a: T::Wrapped) -> T {
Transparent::wrap(a)
}
pub fn peel<T: Transparent>(a: T) -> T::Wrapped {
Transparent::peel(a)
}
pub fn peel_copy<T: Transparent>(a: &T) -> T::Wrapped {
Transparent::peel_copy(a)
}
pub fn rewrap<A: Transparent, B: Transparent<Wrapped = A::Wrapped>>(a: A) -> B {
wrap(peel(a))
}
#[cfg(test)]
mod tests {
use super::*;
use bytemuck::Zeroable;
#[derive(Clone, Copy)]
#[repr(C)]
struct Bigger {
a: u32,
b: u32,
c: u32,
d: u32,
}
unsafe impl Zeroable for Bigger {}
unsafe impl Pod for Bigger {}
impl Transparent for Bigger {
type Wrapped = Overaligned;
}
#[derive(Clone, Copy)]
#[repr(C, align(16))]
struct Overaligned {
a: u32,
b: u32,
c: u32,
d: u32,
}
unsafe impl Zeroable for Overaligned {}
unsafe impl Pod for Overaligned {}
impl Transparent for Overaligned {
type Wrapped = Bigger;
}
#[test]
fn invalid_cast() {
assert_eq!(align_of::<Bigger>(), 4);
assert_eq!(align_of::<Overaligned>(), 16);
let bigger = Bigger {
a: 1,
b: 2,
c: 3,
d: 4,
};
let overaligned: Overaligned = Transparent::peel(bigger);
assert_eq!(bigger.a, 1);
assert_eq!(overaligned.a, 1);
let _bigger: Bigger = Transparent::peel_copy(&overaligned);
}
}