I didn't notice anything along the lines of this in your listed attempts. I'm not sure if this is a 100% guarantee, but it may serve as a starting point (this is simple enough to wrap with macro_rules!
):
(edit: incorporated @cuviper's slick suggestion)
// This struct is generic in Bytes to admit unsizing coercions.
#[repr(C)] // guarantee 'bytes' comes after '_align'
struct AlignedTo<Align, Bytes: ?Sized> {
_align: [Align; 0],
bytes: Bytes,
}
// dummy static used to create aligned data
static ALIGNED: &'static AlignedTo<f32, [u8]> = &AlignedTo {
_align: [],
bytes: *include_bytes!("data.dat"),
};
static ALIGNED_BYTES: &'static [u8] = &ALIGNED.bytes;
Addendum 2020-03-06
Since this has been receiving more attention, here's a macro so that you don't have to manually construct the dummy static:
#[macro_use]
mod macros {
#[repr(C)] // guarantee 'bytes' comes after '_align'
pub struct AlignedAs<Align, Bytes: ?Sized> {
pub _align: [Align; 0],
pub bytes: Bytes,
}
macro_rules! include_bytes_align_as {
($align_ty:ty, $path:literal) => {
{ // const block expression to encapsulate the static
use $crate::macros::AlignedAs;
// this assignment is made possible by CoerceUnsized
static ALIGNED: &AlignedAs::<$align_ty, [u8]> = &AlignedAs {
_align: [],
bytes: *include_bytes!($path),
};
&ALIGNED.bytes
}
};
}
}
#[repr(align(4096))]
struct Align4096;
static A: &'static [u8] = include_bytes!("boxed.rs");
static B: &'static [u8] = include_bytes_align_as!(f64, "boxed.rs");
static C: &'static [u8] = include_bytes_align_as!(Align4096, "boxed.rs");