Giter Club home page Giter Club logo

Comments (2)

DBLouis avatar DBLouis commented on July 28, 2024

Could I make this work quickly? I need this; Maybe with a more recent branch?

from safer_ffi.

danielhenrymantilla avatar danielhenrymantilla commented on July 28, 2024

@DBLouis you surely can do this, it'll be a matter of "copy-pasting" the struct derive logic and replacing the occurrences of struct with union:

  1. Copy-paste the proc-macro logic for the struct here:

    | Data::Struct(DataStruct {
    struct_token: ref struct_,
    ref fields,
    semi_token: ref maybe_semi_colon,
    }) => {
    let (params, bounds) = generics.my_split();
    quote! {
    ::safer_ffi::layout::#name! {
    #(#attrs)*
    #vis
    #struct_ #ident
    [#params]
    where {
    #(#bounds ,)*
    }
    #fields
    #maybe_semi_colon
    }
    }
    },
    | Data::Union(ref union_) => {
    Error::new_spanned(
    union_.union_token,
    "`union`s are not supported yet."
    ).to_compile_error()
    },

    and replace the union compile_error with that, replacing struct_ with union_.

  2. Copy-paste (and add to the macro) the whole macro_rules! rule at

    macro_rules! CType {(
    $(
    @doc_meta( $($doc_meta:tt)* )
    )?
    #[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
    ),+ $(,)?
    }
    ) => (
    #[repr(C)]
    $(#[$($meta)*])*
    $pub
    struct $StructName
    $(<$($lt ,)* $($($generics),+)?> $(where $($bounds)* )?)?
    {
    $(
    $(#[$($field_meta)*])*
    $field_pub
    $field_name : $field_ty,
    )*
    }
    unsafe // Safety: struct is `#[repr(C)]` and contains `CType` fields
    impl $(<$($lt ,)* $($($generics),+)?>)? $crate::layout::CType
    for $StructName$(<$($lt ,)* $($($generics),+)?>)?
    where
    $(
    $field_ty : $crate::layout::CType,
    )*
    $(
    $($(
    $generics : $crate::layout::ReprC,
    )+)?
    $($($bounds)*)?
    )?
    { $crate::__cfg_headers__! {
    fn c_short_name_fmt (fmt: &'_ mut $crate::core::fmt::Formatter<'_>)
    -> $crate::core::fmt::Result
    {
    fmt.write_str($crate::core::stringify!($StructName))?;
    $($(
    $(
    $crate::core::write!(fmt, "_{}",
    <
    <$generics as $crate::layout::ReprC>::CLayout
    as
    $crate::layout::CType
    >::c_short_name()
    )?;
    )+
    )?)?
    Ok(())
    }
    fn c_define_self (definer: &'_ mut dyn $crate::headers::Definer)
    -> $crate::std::io::Result<()>
    {
    assert_ne!(
    $crate::core::mem::size_of::<Self>(), 0,
    "C does not support zero-sized structs!",
    );
    let ref me =
    <Self as $crate::layout::CType>
    ::c_short_name().to_string()
    ;
    definer.define_once(
    me,
    &mut |definer| {
    $(
    <$field_ty as $crate::layout::CType>::c_define_self(definer)?;
    )*
    let out = definer.out();
    $(
    $crate::__output_docs__!(out, "", $($doc_meta)*);
    )?
    $crate::__output_docs__!(out, "", $(#[$($meta)*])*);
    $crate::core::writeln!(out, "typedef struct {{\n")?;

    Replacing, again, struct with union there input-of-the-macro-rule-wise, and also at the last line of the quoted snippet:

    $crate::core::writeln!(out, "typedef struct {{\n")?;

  3. Similarly, copy-paste

    (
    $( @[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
    ),+ $(,)?
    }
    ) => (
    $crate::__with_doc__! {
    #[doc = $crate::core::concat!(
    " - [`",
    $crate::core::stringify!($StructName),
    "_Layout`]"
    )]
    $(#[doc = $prev_doc])*
    #[repr(C)]
    $(#[doc = $doc])?
    $(#[$($meta)*])*
    /// # C Layout
    ///
    $pub
    struct $StructName $(
    <$($lt ,)* $($($generics),+)?> $(
    where $($bounds)*
    )?
    )?
    {
    $(
    $(#[$($field_meta)*])*
    $field_pub
    $field_name : $field_ty,
    )*
    }
    }
    $crate::paste::item! {
    #[allow(nonstandard_style)]
    $pub use
    [< __ $StructName _safer_ffi_mod >]::$StructName
    as
    [< $StructName _Layout >]
    ;
    }
    #[allow(trivial_bounds)]
    unsafe // Safety: struct is `#[repr(C)]` and contains `ReprC` fields
    impl $(<$($lt ,)* $($($generics),+)?>)? $crate::layout::ReprC
    for $StructName $(<$($lt ,)* $($($generics),+)?>)?
    where
    $(
    $field_ty : $crate::layout::ReprC,
    <$field_ty as $crate::layout::ReprC>::CLayout
    : $crate::layout::CType<
    OPAQUE_KIND = $crate::layout::OpaqueKind::Concrete,
    >,
    )*
    $(
    $($(
    $generics : $crate::layout::ReprC,
    )+)?
    $($($bounds)*)?
    )?
    {
    type CLayout = $crate::paste::__item__! {
    [<$StructName _Layout>]
    $(<$($lt ,)* $($($generics),+)?>)?
    };
    #[inline]
    fn is_valid (it: &'_ Self::CLayout)
    -> bool
    {
    let _ = it;
    true $(
    && (
    $crate::core::mem::size_of::<
    <$field_ty as $crate::layout::ReprC>::CLayout
    >() == 0
    ||
    <$field_ty as $crate::layout::ReprC>::is_valid(
    &it.$field_name
    )
    )
    )*
    }
    }
    $crate::paste::item! {
    #[allow(nonstandard_style, trivial_bounds)]
    mod [< __ $StructName _safer_ffi_mod >] {
    #[allow(unused_imports)]
    use super::*;
    $crate::layout::CType! {
    @doc_meta(
    $(#[doc = $prev_doc])*
    $(#[$($meta)*])*
    )
    #[repr(C)]
    #[allow(missing_debug_implementations)]
    // $(#[$meta])*
    pub
    struct $StructName
    [$($($lt ,)* $($($generics),+)?)?]
    where {
    $(
    $field_ty : $crate::layout::ReprC,
    )*
    $(
    $($(
    $generics : $crate::layout::ReprC,
    )+)?
    $($($bounds)*)?
    )?
    } {
    $(
    $(#[$($field_meta)*])*
    pub
    $field_name :
    <$field_ty as $crate::layout::ReprC>::CLayout
    ,
    )*
    }
    }
    }
    }
    const _: () = {
    $crate::paste::item! {
    use [< __ $StructName _safer_ffi_mod >]::*;
    }
    impl $(<$($lt ,)* $($($generics),+)?>)? $crate::core::marker::Copy
    for $StructName $(<$($lt ,)* $($($generics),+)?>)?
    where
    $(
    $field_ty : $crate::layout::ReprC,
    )*
    $(
    $($(
    $generics : $crate::layout::ReprC,
    )+)?
    $($($bounds)*)?
    )?
    {}
    impl $(<$($lt ,)* $($($generics),+)?>)? $crate::core::clone::Clone
    for $StructName $(<$($lt ,)* $($($generics),+)?>)?
    where
    $(
    $field_ty : $crate::layout::ReprC,
    )*
    $(
    $($(
    $generics : $crate::layout::ReprC,
    )+)?
    $($($bounds)*)?
    )?
    {
    #[inline]
    fn clone (self: &'_ Self)
    -> Self
    {
    *self
    }
    }
    };
    );
    replacing struct with enum in the input part of the macro rule, and then you'll just have to change the definition of fn is_valid inside it to true (remove the "each field needs to be valid" logic that follows, since for a union safer-ffi cannot know which variant is active (if you want to push it further, you can actually leave that logic be, but replacing true with false and the && with ||)).

from safer_ffi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.