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
alignment
parameter isUnaligned
if the struct is#[repr(C,packed)]
, andAligned
if 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
FieldOffset
s. false
: The constants areFieldOffset
s.true
: The constants areusize
s.
§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;
}
}