I'm trying to read bytes from a binary file and cast the pointer to the slice to &[u32]. It works at runtime using the fs module:
let mut buf = Vec::new();
let file = File::open("slang.spv").unwrap();
let mut reader = BufReader::new(file);
reader.read_to_end(&mut buf).
let code = std::slice::from_raw_parts(buf.as_ptr() as *const u32, buf.len() / 4);
However at compile time:
let buf = include_bytes!("../../slang.spv");
let code = std::slice::from_raw_parts(buf.as_ptr() as *const u32, buf.len() / 4);
It panics with unsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed isize::MAX
There is no guarantee that include_bytes gives you something 4-aligned, so this is to be expected.
Put it in a static that you manually align (perhaps via a wrapper type with #[repr(align(4))]) if you want to use it in a type with a validity invariant of being 4-aligned.
There's also no guarantee that your buf will be either, so that's also technically unsound, though assuming your spv file isn't tiny most allocators will probably happen to give you something 4-aligned. To do it properly, you'd be better off making a Vec<u32>, then writing the file into that -- &mut [u32] -> &mut [u8] can be done infallibly -- so that you have the allocation aligned as you apparently need.
3 Likes
there's simple trick to align the included data, see
5 Likes