5
5
macro_rules! define_extern_type {
6
6
( $target: ident) => ( $crate:: define_extern_type!( $target => $target) ; ) ;
7
7
( $target: ty => $defined_path: path) => {
8
- unsafe impl :: static_reflect :: StaticReflect for $target {
8
+ unsafe impl $crate :: StaticReflect for $target {
9
9
const TYPE_INFO : $crate:: TypeInfo <' static > = $crate:: TypeInfo :: Extern {
10
10
name: stringify!( $defined_path)
11
11
} ;
@@ -14,13 +14,55 @@ macro_rules! define_extern_type {
14
14
}
15
15
16
16
/// Get the integer offset of the specified field
17
+ ///
18
+ /// This is only well defined for `#[repr(C)]` types,
19
+ /// since `#[repr(Rust)]` types don't have a well-defined layout.
20
+ ///
21
+ /// ## Examples
22
+ /// ````
23
+ /// # use static_reflect::field_offset;
24
+ /// # #[repr(C)]
25
+ /// # struct Nested {
26
+ /// # nested: u32
27
+ /// # }
28
+ /// #[repr(C)]
29
+ /// struct Example {
30
+ /// first: u32,
31
+ /// second: u8,
32
+ /// third: Nested,
33
+ /// }
34
+ /// assert_eq!(field_offset!(Example, first), 0);
35
+ /// // You may specify the expected type by suffixing with `as $expected_type`
36
+ /// assert_eq!(field_offset!(Example, second as u8), 4);
37
+ /// // Fields can be arbitrarily nested
38
+ /// assert_eq!(field_offset!(Example, third.nested as u32), 8);
39
+ /// ````
40
+ ///
41
+ /// ## Const eval
42
+ /// Assuming you specify the appropriate feature flags,
43
+ /// this macro can also be used in a const-eval context.
44
+ /// ````
45
+ /// #![feature(const_raw_ptr_deref, const_maybe_uninit_as_ptr, const_ptr_offset_from)]
46
+ /// # #![deny(unused_features, stable_features)]
47
+ /// # use static_reflect::field_offset;
48
+ /// struct Example {
49
+ /// first: u32,
50
+ /// second: u8,
51
+ /// }
52
+ /// const FIRST_OFFSET: usize = field_offset!(Example, first as u32);
53
+ /// assert_eq!(FIRST_OFFSET, 0);
54
+ /// const SECOND_OFFSET: usize = field_offset!(Example, second as u8);
55
+ /// assert_eq!(SECOND_OFFSET, 4);
56
+ /// ````
17
57
#[ macro_export]
18
58
macro_rules! field_offset {
19
- ( $target: path, $( $field: ident) ,+) => {
59
+ ( $target: path, $( $field: ident) .* ) => ( field_offset!( $target, $( $field) .* as _) ) ;
60
+ ( $target: path, $( $field: ident) .+ as $expected_type: ty) => {
20
61
unsafe {
21
62
let uninit = core:: mem:: MaybeUninit :: <$target>:: uninit( ) ;
22
63
let base = uninit. as_ptr( ) ;
23
- ( core:: ptr:: addr_of!( ( * base) $( . $field) * ) . cast:: <u8 >( ) . offset_from( base as * const u8 ) as usize )
64
+ let ptr: * const $expected_type = core:: ptr:: addr_of!( ( * base) $( . $field) * ) ;
65
+ ptr. cast:: <u8 >( ) . offset_from( base as * const u8 ) as usize
24
66
}
25
67
}
26
68
}
0 commit comments