Skip to content

Commit 8631e5b

Browse files
committed
Add an offset_of macro
We can't yet use the standard library's macro since it isn't in our MSRV, but there are a couple of applicatons for having `offset_of` available. Add a polyfill for now. (backport <#4792>) (cherry picked from commit 1808393)
1 parent e460ad1 commit 8631e5b

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/macros.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,23 @@ macro_rules! deprecated_mach {
427427
}
428428
}
429429

430+
/// Polyfill for std's `offset_of`.
431+
// FIXME(msrv): stabilized in std in 1.77
432+
macro_rules! offset_of {
433+
($Ty:path, $field:ident) => {{
434+
// Taken from bytemuck, avoids accidentally calling on deref
435+
#[allow(clippy::unneeded_field_pattern)]
436+
let $Ty { $field: _, .. };
437+
let data = core::mem::MaybeUninit::<$Ty>::uninit();
438+
let ptr = data.as_ptr();
439+
// SAFETY: computed address is inbounds since we have a stack alloc for T
440+
let fptr = unsafe { core::ptr::addr_of!((*ptr).$field) };
441+
let off = (fptr as usize).checked_sub(ptr as usize).unwrap();
442+
assert!(off <= core::mem::size_of::<$Ty>());
443+
off
444+
}};
445+
}
446+
430447
#[cfg(test)]
431448
mod tests {
432449
use core::any::TypeId;
@@ -528,6 +545,26 @@ mod tests {
528545
fn type_id_of_val<T: 'static>(_: &T) -> TypeId {
529546
TypeId::of::<T>()
530547
}
548+
549+
#[test]
550+
fn test_offset_of() {
551+
#[repr(C)]
552+
struct Off1 {
553+
a: u8,
554+
b: u32,
555+
c: Off2,
556+
d: u64,
557+
}
558+
559+
#[repr(C)]
560+
#[repr(align(128))]
561+
struct Off2 {}
562+
563+
assert_eq!(core::mem::offset_of!(Off1, a), offset_of!(Off1, a));
564+
assert_eq!(core::mem::offset_of!(Off1, b), offset_of!(Off1, b));
565+
assert_eq!(core::mem::offset_of!(Off1, c), offset_of!(Off1, c));
566+
assert_eq!(core::mem::offset_of!(Off1, d), offset_of!(Off1, d));
567+
}
531568
}
532569

533570
#[cfg(test)]

0 commit comments

Comments
 (0)