[][src]Macro safer_ffi::ReprC

macro_rules! ReprC {
    (
        $( @[doc = $doc:expr] )?
        $(#[doc = $prev_doc:tt])* // support doc comments _before_ `#[repr(C)]`
        #[repr(C)]
        $(#[$($meta:tt)*])*
        $pub:vis
        struct $StructName:ident $(
            [
                $($lt:lifetime ,)*
                $($($generics:ident),+ $(,)?)?
            ]
                $(where { $($bounds:tt)* })?
        )?
        {
            $(
                $(#[$($field_meta:tt)*])*
                $field_pub:vis
                $field_name:ident : $field_ty:ty
            ),+ $(,)?
        }
    ) => { ... };
    (
        $( @[doc = $doc:expr] )?
        $(#[doc = $prev_doc:tt])*
        #[repr(transparent)]
        $(#[$meta:meta])*
        $pub:vis
        struct $StructName:ident $(
            [$($generics:tt)*] $(
                where { $($bounds:tt)* }
            )?
        )?
        (
            $(#[$field_meta:meta])*
            $field_pub:vis
            $field_ty:ty $(,
            $($rest:tt)* )?
        );
    ) => { ... };
    (
        $(#[doc = $prev_doc:tt])*
        #[repr($Int:ident)]
        $(#[$($meta:tt)*])*
        $pub:vis
        enum $EnumName:ident {
            $(
                $($(#[doc = $variant_doc:expr])+)?
                // $(#[$variant_meta:meta])*
                $Variant:ident $(= $discriminant:expr)?
            ),+ $(,)?
        }
    ) => { ... };
    (
        $(#[doc = $prev_doc:tt])*
        #[repr(C $(, $Int:ident)?)]
        $(#[$meta:meta])*
        $pub:vis
        enum $EnumName:ident {
            $($variants:tt)*
        }
    ) => { ... };
    (
        $(#[doc = $prev_doc:tt])*
        #[
            ReprC
            ::
            opaque
            $(
                ( $($c_name:expr)? )
            )?
        ]
        $(#[$meta:meta])*
        $pub:vis
        struct $StructName:ident $(
            [
                $($lt:lifetime ,)*
                $($($generics:ident),+ $(,)?)?
            ]
                $(where { $($bounds:tt)* })?
        )?
        { $($opaque:tt)* }
    ) => { ... };
    (@validate_int_repr u8) => { ... };
    (@validate_int_repr u16) => { ... };
    (@validate_int_repr u32) => { ... };
    (@validate_int_repr u64) => { ... };
    (@validate_int_repr u128) => { ... };
    (@validate_int_repr i8) => { ... };
    (@validate_int_repr i16) => { ... };
    (@validate_int_repr i32) => { ... };
    (@validate_int_repr i64) => { ... };
    (@validate_int_repr i128) => { ... };
    (@deny_C C) => { ... };
    (@deny_C c_int) => { ... };
    (@deny_C c_uint) => { ... };
    (@deny_C $otherwise:tt) => { ... };
    (@first ($($fst:tt)*) $($ignored:tt)?) => { ... };
}

Safely implement ReprC for a #[repr(C)] struct when all its fields are ReprC.

Syntax

Note: given that this macro is implemented as a macro_rules! macro for the sake of compilation speed, it cannot parse arbitrary generic parameters and where clauses.

Instead, it expects a special syntax whereby the generic parameters are written between square brackets, and only introduce lifetime parameters and type parameters, with no bounds whatsoever (and a necessary trailing comma for the lifetime parameters); the bounds must all be added to the optional following where { <where clauses here> } (note the necessary braces):

  • Instead of:

    This example deliberately fails to compile
    use ::safer_ffi::layout::ReprC;
    
    ReprC! {
        #[repr(C)]
        struct GenericStruct<'lifetime, T : 'lifetime>
        where
            T : ReprC,
        {
            inner: &'lifetime T,
        }
    }
  • You need to write:

    use ::safer_ffi::layout::ReprC;
    
    ReprC! {
        #[repr(C)]
        struct GenericStruct['lifetime, T]
        where {
            T : 'lifetime + ReprC,
        }
        {
            inner: &'lifetime T,
        }
    }

#[derive_ReprC]

If all this looks cumbersome to you, and if you don't care about the compilation-from-scratch time, then it is highly advised you enable the proc_macros feature:

[dependencies]
safer-ffi = { version = "...", features = ["proc_macros"] }

and use the #[derive_ReprC] attribute macro instead, which will do the rewriting for you.