From 4dcc2056705efb0df4e784007e133466f3695597 Mon Sep 17 00:00:00 2001 From: Aleksandr Date: Thu, 22 Aug 2024 18:41:22 +0300 Subject: [PATCH] feat: add `build.rs` for additional build-time checks of layout --- build.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 build.rs diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..cad26c0 --- /dev/null +++ b/build.rs @@ -0,0 +1,68 @@ +use std::ptr; + +#[allow(dead_code)] +struct Sample(usize); + +trait SomeTrait { + fn call_me(&self) -> bool { + true + } +} + +impl SomeTrait for Sample {} + +fn layout_broken(what: &str) { + panic!( + concat!( + "Assumptions on layout broken, this crate relies on ", + "`unsafe code guidelines` layout specification, ", + "now layout of {:?} is broken, report about it on github" + ), + what + ); +} + +fn test_ptr_layouts() { + // Test for dyn object + { + #[repr(C)] + struct DynObj { + data_ptr: *const u8, + vtable: *const u8, + } + + let sample = Box::new(Sample(100)); + let data_ptr = Box::into_raw(sample); + + let trait_obj: *const dyn SomeTrait = data_ptr; + let dyn_obj_repr: DynObj = unsafe { ptr::read(ptr::addr_of!(trait_obj) as *const DynObj) }; + + if dyn_obj_repr.data_ptr != data_ptr as *const u8 { + layout_broken("trait objects"); + } + let out = unsafe { Box::from_raw(data_ptr) }; + out.call_me(); + } + + // Test for slice object + { + let array = [1, 2, 3]; + let slice: &[u8] = &array; + + #[repr(C)] + struct Slice { + data_ptr: *const u8, + size: usize, + } + + let slice_repr: Slice = unsafe { ptr::read(ptr::addr_of!(slice) as *const Slice) }; + + if slice_repr.data_ptr != slice.as_ptr() || slice_repr.size != slice.len() { + layout_broken("slices"); + } + } +} + +fn main() { + test_ptr_layouts(); +}