stdx/
macros.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#[macro_export]
macro_rules! cfg_group {
    ($($item:item)*) => {
        $($item)*
    }
}

/// Calculates the offset of the specified field from the start of the named struct.
#[macro_export]
macro_rules! offset_of {
    ($ty: path, $field: tt) => {{
        use ::core::mem::MaybeUninit;
        use ::core::primitive::{u8, usize};
        use ::core::ptr;

        #[allow(
            unused_unsafe,
            clippy::as_conversions,
            clippy::unneeded_field_pattern,
            clippy::undocumented_unsafe_blocks
        )]
        const OFFSET: usize = unsafe {
            // ensure the type is a named struct
            // ensure the field exists and is accessible
            let $ty { $field: _, .. };

            // const since 1.36
            let uninit: MaybeUninit<$ty> = MaybeUninit::uninit();

            // const since 1.59
            // UnsafeCell needs feature(const_refs_to_cell)
            let base_ptr: *const $ty = uninit.as_ptr();

            // stable since 1.51
            let field_ptr: *const _ = ptr::addr_of!((*base_ptr).$field);

            // const since 1.38
            let base_addr = base_ptr.cast::<u8>();
            let field_addr = field_ptr.cast::<u8>();

            // const since 1.65
            field_addr.offset_from(base_addr) as usize
        };
        OFFSET
    }};
}