macro_rules! unsafe_struct_field_offsets {
(
$( Self = $Self:ty, )?
alignment = $alignment:ty,
$( usize_offsets = $usize_offsets:ident,)?
$( impl_GetFieldOffset = $impl_gfo:ident,)?
$(#[$impl_attr:meta])*
impl[ $($impl_params:tt)* ] $self:ty
$(where [ $($where:tt)* ])?
{
$(
$(#[$const_attr:meta])*
$( pub $(($($inn:tt)*))? )?
const $offset:ident, $field_ident:tt: $field_ty:ty;
)*
}
) => { ... };
}Expand description
Declares a sequence of associated constants with the offsets of the listed fields,
and implements the GetFieldOffset trait.
§Safety
Callers must ensure that:
-
The type that the offsets are for is a
#[repr(C)]struct. -
All field types are listed,in declaration order.
-
The
alignmentparameter isUnalignedif the struct is#[repr(C,packed)], andAlignedif it’s not.
§Parameters
§Self
The optional Self parameter overrides which struct the FieldOffset constants
(that this outputs) are an offset inside of.
Note that passing the this parameter unconditionally causes the type
not to implement GetFieldOffset.
§alignment
The alignment parameter can be either Aligned or Unaligned,
and describes whether the fields are aligned or potentially unaligned,
changing how fields are accessed in FieldOffset methods.
§usize_offsets
The optional usize_offsets parameter determines whether type of the
generated constants is FieldOffset or usize.
The valid values for this parameter are:
- (not passing this parameter): The constants are
FieldOffsets. false: The constants areFieldOffsets.true: The constants areusizes.
§impl_GetFieldOffset
The optional impl_GetFieldOffset parameter determines whether $self
implements the GetFieldOffset trait,
which allows getting the FieldOffset for each field using the
OFF,
off,
PUB_OFF, and
pub_off macros.
The valid values for this parameter are:
- (not passing this parameter): Implements
GetFieldOffset. false: Does not implementGetFieldOffset.true: ImplementsGetFieldOffset.
Note that passing the Self parameter unconditionally causes the type
not to implement GetFieldOffset.
§Examples
§Syntax example
This demonstrates the macro being used with all of the syntax.
use repr_offset::{unsafe_struct_field_offsets, Aligned};
#[repr(C)]
struct Bar<T: Copy, U>(T,U)
where U: Clone;
unsafe_struct_field_offsets!{
// Optional parameter.
// Generic parameters from the impl block can be used here.
Self = Bar<T, U>,
alignment = Aligned,
// Optional parameter.
usize_offsets = false,
// Optional parameter.
impl_GetFieldOffset = false,
impl[T: Copy, U] Bar<T, U>
where[ U: Clone ]
{
pub const OFFSET_0, 0: T;
pub const OFFSET_1, 1: U;
}
}
§Unaligned struct example
This example demonstrates how you can replace fields in a packed struct,
as well as getting a raw pointer to a field,
using both FieldOffset methods, and extension traits from the ext module
use repr_offset::{
unsafe_struct_field_offsets,
off,
ROExtAcc, ROExtOps, Unaligned,
};
// Replacing the table field
{
let mut bar = Bar{ mugs: 3, bottles: 5, table: "wooden".to_string() };
assert_eq!( replace_table_a(&mut bar, "metallic".to_string()), "wooden".to_string());
assert_eq!( replace_table_b(&mut bar, "granite".to_string()), "metallic".to_string());
assert_eq!( replace_table_b(&mut bar, "carbonite".to_string()), "granite".to_string());
fn replace_table_a(this: &mut Bar, replacement: String)-> String{
Bar::OFFSET_TABLE.replace_mut(this, replacement)
}
fn replace_table_b(this: &mut Bar, replacement: String)-> String{
this.f_replace(off!(table), replacement)
}
}
// Getting raw pointers to fields
unsafe {
let bar = Bar{ mugs: 3, bottles: 5, table: "wooden".to_string() };
assert_eq!(get_mugs_ptr(&bar).read_unaligned(), 3);
assert_eq!(get_bottles_ptr(&bar).read_unaligned(), 5);
fn get_mugs_ptr(this: &Bar) -> *const u32 {
Bar::OFFSET_MUGS.get_ptr(this)
}
fn get_bottles_ptr(this: &Bar) -> *const u16 {
this.f_get_ptr(off!(bottles))
}
}
#[repr(C,packed)]
struct Bar{
mugs: u32,
bottles: u16,
table: String,
}
unsafe_struct_field_offsets!{
alignment = Unaligned,
impl[] Bar {
pub const OFFSET_MUGS, mugs: u32;
pub const OFFSET_BOTTLES, bottles: u16;
pub const OFFSET_TABLE, table: String;
}
}