Paolo Bonzini <[email protected]> writes:
> offset_of! was stabilized in Rust 1.77.0. Use an alternative implemenation
> that was found on the Rust forums, and whose author agreed to license as
> MIT for use in QEMU.
>
> The alternative allows only one level of field access, but apart
> from this can be used just by replacing core::mem::offset_of! with
> qemu_api::offset_of!.
How about a macro like this (which essentially comes from memoffset
crate [1])? It has the same use as core::mem::offset_of! (except the
same single-level limitation) and does not need wrapping structures with
with_offsets!.
macro_rules! offset_of {
($parent:ty, $field:tt) => {{
let uninit = std::mem::MaybeUninit::<$parent>::uninit();
let base = uninit.as_ptr();
// SAFETY:
//
// MaybeUninit<$parent> has the same size and alignment as $parent, so
// projection to $field is in bound.
//
// addr_of! does not create intermediate references to the uninitialized
// memory, thus no UB is involved.
let field = unsafe { std::ptr::addr_of!((*base).$field) };
// SAFETY:
//
// Both base and field point to the MaybeUninit<$parent> and are casted
// to u8 for calculating their distance.
unsafe { field.cast::<u8>().offset_from(base.cast::<u8>()) as usize }
}};
}
[1] https://docs.rs/memoffset/latest/memoffset/
--
Best Regards
Junjie Mao