use co3::{ExternC, ReprC, transmute::CheckedTransmute};
use rust_spec::RustSpec;
use static_assertions::{assert_impl_all, assert_not_impl_any};
#[derive(RustSpec, ReprC)]
#[repr(C, align(16))]
struct AlignedStruct(u8);
#[derive(ReprC)]
#[repr(C)]
#[repr(align(16))]
struct SeparatelyAlignedStruct(u8);
#[derive(RustSpec, ReprC)]
#[repr(u8, align(16))]
enum AlignedFieldlessEnum {
First,
Second,
}
#[derive(RustSpec, ReprC)]
#[repr(u8, align(16))]
enum AlignedDataEnum {
First(u32),
Second,
}
#[derive(RustSpec, ReprC)]
#[repr(C, u8, align(32))]
enum ExplicitCAlignedDataEnum {
First(u32),
Second,
}
#[derive(RustSpec, ReprC)]
#[repr(align(32))]
struct RustLayoutAligned(u8, u32);
fn assert_same_layout<T: ExternC<CType: Sized>>() {
assert_eq!(core::mem::size_of::<T>(), core::mem::size_of::<T::CType>());
assert_eq!(
core::mem::align_of::<T>(),
core::mem::align_of::<T::CType>()
);
}
fn assert_nontrivial_alignment<T: RustSpec<Alignment = rust_spec::Gt<rust_spec::One>>>() {}
#[test]
fn explicit_repr_alignment_is_preserved_by_companion_types() {
assert_same_layout::<AlignedStruct>();
assert_same_layout::<SeparatelyAlignedStruct>();
assert_same_layout::<AlignedFieldlessEnum>();
assert_same_layout::<AlignedDataEnum>();
assert_same_layout::<ExplicitCAlignedDataEnum>();
assert_nontrivial_alignment::<<AlignedStruct as ExternC>::CType>();
assert_nontrivial_alignment::<<SeparatelyAlignedStruct as ExternC>::CType>();
assert_nontrivial_alignment::<<AlignedFieldlessEnum as ExternC>::CType>();
assert_nontrivial_alignment::<<AlignedDataEnum as ExternC>::CType>();
assert_nontrivial_alignment::<<ExplicitCAlignedDataEnum as ExternC>::CType>();
assert_impl_all!(AlignedStruct: CheckedTransmute);
assert_impl_all!(SeparatelyAlignedStruct: CheckedTransmute);
assert_impl_all!(AlignedFieldlessEnum: CheckedTransmute);
assert_impl_all!(AlignedDataEnum: CheckedTransmute);
assert_impl_all!(ExplicitCAlignedDataEnum: CheckedTransmute);
}
#[test]
fn alignment_without_a_stable_layout_is_preserved_without_transmute() {
assert_eq!(core::mem::align_of::<RustLayoutAligned>(), 32);
assert_eq!(
core::mem::align_of::<<RustLayoutAligned as ExternC>::CType>(),
32
);
assert_nontrivial_alignment::<<RustLayoutAligned as ExternC>::CType>();
assert_not_impl_any!(RustLayoutAligned: CheckedTransmute);
}