repr_offset
allows computing and safely using field offsets from types with a stable layout.
Currently only #[repr(C)]
/#[repr(C,packed)]
/#[repr(C,align)]
structs are supported.
Features
These are some of the features this library provides:
-
The [
ReprOffset
] derive macro, which outputs associated constants with the offsets of fields. -
Using the [
FieldOffset
] type (how offsets are represented), with methods for operating on a field through a pointer to the struct, including getting a reference(or pointer) to the field. -
Use the [
unsafe_struct_field_offsets
] macro as an alternative to the [ReprOffset
] derive macro, most useful when the "derive" feature is disabled.
Dependencies
This library re-exports the [ReprOffset
] derive macro from the
repr_offset_derive
crate when the "derive" feature is enabled
(it's enabled is the default).
If you don't need the derive macro,
you can disable the default feature in the Cargo.toml file with
repr_offset = { version = "....", default_features = false }
,
making a clean compile of this crate take one to three seconds(depends on the machine).
Examples
Derivation
This example demonstrates:
-
Deriving the field offset constants with the [
ReprOffset
] derive macro. -
Moving out unaligned fields through a raw pointer.
use ManuallyDrop;
let mut this = new;
let ptr: *mut Packed = &mut *this;
unsafe
Initialization
This example demonstrates how you can:
-
Use the [
unsafe_struct_field_offsets
] macro to declare associated constants with the field offsets. -
Initialize an uninitialized struct by passing a pointer to it.
This example only compiles since Rust 1.36 because it uses MaybeUninit
.
use std::mem::MaybeUninit;
use repr_offset::{unsafe_struct_field_offsets, Aligned};
fn main(){ unsafe { let mut foo = MaybeUninit::uninit(); initialize_foo(foo.as_mut_ptr()); assert_eq!( foo.assume_init(), Foo{ name: "foo".to_string(), x: 13, y: 21 } ); } }
/// Initializes a Foo
through a raw pointer.
///
/// # Safety
///
/// Callers must pass a pointer to uninitialized memory with the
/// size and alignment of Foo
unsafe fn initialize_foo(this: *mut Foo){
Foo::OFFSET_NAME.raw_get_mut(this).write("foo".into());
Foo::OFFSET_X.raw_get_mut(this).write(13);
Foo::OFFSET_Y.raw_get_mut(this).write(21);
}
#[repr(C)] #[derive(Debug, PartialEq)] pub struct Foo{ pub name: String, pub x: u32, pub y: u32, }
// This macro is unsafe to invoke because you have to ensure that:
// - All field types are listed,in declaration order.
// - The alignment
parameter is Unaligned
if the struct is #[repr(C,packed)]
,
// and Aligned
if it's not.
unsafe_struct_field_offsets!{
alignment = Aligned,
impl[] Foo { pub const OFFSET_NAME:String; pub const OFFSET_X:u32; pub const OFFSET_Y:u32; } }
[`ReprOffset`]: ./docs/repr_offset_macro/index.html
[`unsafe_struct_field_offsets`]: ./macro.unsafe_struct_field_offsets.html
[`FieldOffset`]: ./struct.FieldOffset.html