Attribute Macro ark_api_macros::ffi_union

source · []
#[ffi_union]
Expand description

Performs modification necessary to make a union ffi-safe.

Ultimately this checks for invariants and implements bytemuck::NoUninit and bytemuck::AnyBitPattern. It is technically possible to make the bytemuck::NoUninit implementation invalid with sound code, but only through using unsafe code that writes uninit memory into the union. Therefore you have to promise not to do this… which ultimately shouldn’t be an issue as this isn’t really something that should be a want to do.

This macro wraps each field in a union into an ark_api_ffi::TransparentPad<T, N> such that the total size of the new type is equal to the size specified in the ffi_union macro. The size is specified in bytes.

This macro automatically derives bytemuck::NoUninit and bytemuck::AnyBitPattern for the union it is applied to, which is necessary so that those derives use the modified version of the union definition.

Expected form

#[ark_api_macros::ffi_union(size = <size>, <pod_accessors | checked_accessors>)]

Example

#[ark_api_macros::ffi_union(size = 8, pod_accessors)]
union AutoPadExample {
    field1: u64,
    field2: u32,
}

Usually, this would result in a union of size 8 but with padding for bytes 4-8 when the used field is field2. This macro will expand this to (basically):

#[derive(NoUninit, AnyBitPattern)]
union AutoPadExample {
    field1: TransparentPad<u64, 0>,
    field2: TransparentPad<u32, 4>,
}

which adds “explicit”/“manual” padding bytes to the end of field2 – making the compiler not treat them as real padding.

This macro will also derive accessor methods on the union for each field in the form as_{field_name} (and try_as_{field_name}, if using checked_accessors) that return references to the field as the field’s original type rather than as the wrapped TransparentPad.

These accessors will either use bytemuck’s raw or checked casting functions based on the second argument to the proc macro, which can be either pod_accessors or checked_accessors.

All fields must implement Pod for pod_accessors, while all fields must implement CheckedBitPattern for checked_accessors.