ffi_enum_macros/
lib.rs

1use proc_macro::TokenStream;
2use syn::{parse_macro_input, Error};
3
4mod delegate;
5mod ffi_enum;
6mod utils;
7
8macro_rules! export_attribute {
9    ($($(#[$attr:meta])* $i:ident),*$(,)?) => {$(
10        $(#[$attr])*
11        #[proc_macro_attribute]
12        pub fn $i(args: TokenStream, item: TokenStream) -> TokenStream {
13            $i::handle(parse_macro_input!(args), parse_macro_input!(item))
14                .unwrap_or_else(Error::into_compile_error)
15                .into()
16        }
17    )*};
18}
19
20export_attribute!(
21    /// Converts the enum into ffi-safe `enum`s that could be safely sent through ffi Metadata, separated with
22    /// `,`, passed as arguments of this attribute call would be transformed into raw attributes attached on
23    /// the generated `ffi_enum`.
24    ///
25    /// The generated `ffi_enum` type implements `::ffi_enum::FfiEnum` that provides with essential type and constant
26    /// informations of the generated details.
27    ///
28    /// ## For Derive Macros
29    ///
30    /// There are 3 positions to place derive macros:
31    ///
32    /// 1. **(Preferred)** `#[derive(...)]` attached above `ffi_enum` would **see the original `enum` definition**
33    /// and **`impl`s for the generated `ffi_enum` type**. Note that helper attributes attached below this
34    /// `ffi_enum` attribute would also be seen by such derive macros.
35    ///
36    /// 2. `#[ffi_enum(derive(...))]` passed within this attribute would **both** see the definition of and takes
37    /// all effects on **the generated `ffi_enum` type**. All helper attributes passed within this attribute
38    /// would **only** be been by the derive macros passed in this way.
39    ///
40    /// 3. `#[derive(...)]` attached below `ffi_enum` would **both** see the definition of and takes
41    /// all effects on the **the original `enum` definition**.
42    ///
43    /// Derive macros that works on regular `enum`s may simply works fine at Position `1` described above,
44    /// unless the expanded code `match`es the value of the generated `ffi_enum` type **without a
45    /// `_` wildcard pattern** that covers other unknown values that would potentially come from ffi.
46    ///
47    /// As for the derive macros that does not care the variant details, or normally logically works fine for a
48    /// struct that contaions a single field, such as `PartialOrd` or `Ord`, attach the derive macros along with
49    /// their helper attributes at Position `2`. Derive macros passed in this way would see a `ffi_enum_origin`
50    /// helper attribute with the original enum definition passed as the arguments. If you are authoring a derive
51    /// macro that may need to see both the original and generated definitions, this way is preferred.
52    ///
53    /// As for the derive macros that generate `match`ing code without wildcards, or the implemention of which is
54    /// logically insufficient for the generated `ffi_enum` type that covers all binary patterns. The only
55    /// way of automatic deriving is to `derive` at Position `3` described above, which implements for the original
56    /// `enum` definition, and then delegate the implementations from the original `enum` definition which could
57    /// accessed as `<TypeName as ffi_enum::FfiEnum>::Enum`.
58    ///
59    /// This attribute macro would automatically delegate implementations for the generated `ffi_enum` type
60    /// for supported traits. The currently supported derives are:
61    ///
62    /// + `core::fmt::Debug`
63    /// + `serde::Serialize`
64    /// + `serde::Deserialize`
65    ///
66    /// For more automatically delegatings, contributions are welcomed.
67    ffi_enum
68);
69
70#[doc(hidden)]
71#[proc_macro_derive(NoDerive, attributes(ffi_enum_origin))]
72pub fn no_derive(_: TokenStream) -> TokenStream {
73    TokenStream::new()
74}