On Thu, Oct 17, 2024 at 7:35 AM Junjie Mao <junjie....@hotmail.com> wrote:
> Paolo Bonzini <pbonz...@redhat.com> 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!.

Unfortunately offset_from is not available in const context, and
offset_of! is needed to fill in the Property and VMStateDescription
arrays.

That said, I noticed now that declare_properties! does not declare the
resulting array as const, so that would be possible. But if
declare_properties could use a non-mut static, that would be better.

Paolo

> 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
>


Reply via email to