[][src]Macro repr_offset::unsafe_struct_field_offsets

macro_rules! unsafe_struct_field_offsets {
    (
        $( Self = $Self:ty, )?
        alignment =  $alignment:ty,
        $( usize_offsets = $usize_offsets:ident,)?

        $(#[$impl_attr:meta])*
        impl[ $($impl_params:tt)* ] $self:ty
        $(where [ $($where:tt)* ])?
        {
            $(
                $(#[$const_attr:meta])*
                $vis:vis const $offset:ident : $field_ty:ty;
            )*
        }
    ) => { ... };
}

Declares a sequence of associated constants with the offsets of the listed fields.

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 is Unaligned if the struct is #[repr(C,packed)], and Aligned if it's not.

Parameters

Self

The optional Self parameter overrides which struct the FieldOffset constants (that this outputs) are an offset inside of.

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 are FieldOffsets.
  • true: The constants are usizes.

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,

    impl[T: Copy, U] Bar<T, U>
    where[ U: Clone ]
    {
        pub const OFFSET_0: T;
        pub const OFFSET_1: U;
    }
}

Unaligned struct example

This demonstrates how you can get a pointer to a field from a pointer to a packed struct (it's UB to use references to fields here), as well as a FieldOffset method to replace packed fields.

use repr_offset::{unsafe_struct_field_offsets, Unaligned};

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{
    let ptr = Bar::OFFSET_TABLE.get_mut_ptr(this);
    unsafe{
        let taken = ptr.read_unaligned();
        ptr.write_unaligned(replacement);
        taken
    }
}

fn replace_table_b(this: &mut Bar, replacement: String)-> String{
    Bar::OFFSET_TABLE.replace_mut(this, replacement)
}


#[repr(C,packed)]
struct Bar{
    mugs: u32,
    bottles: u16,
    table: String,
}

unsafe_struct_field_offsets!{
    alignment =  Unaligned,

    impl[] Bar {
        pub const OFFSET_MUGS: u32;
        pub const OFFSET_BOTTLES: u16;
        pub const OFFSET_TABLE: String;
    }
}