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    /// The generated `ffi_enum` type by default implements `Copy`, `Clone`, `PartialEq`, `Eq`, based on which
29    /// essential implementations could be derived.
30    ///
31    /// ## For Derive Macros
32    ///
33    /// There are 3 positions to place derive macros:
34    ///
35    /// 1. **(Preferred)** `#[derive(...)]` attached above `ffi_enum` would **see the original `enum` definition**
36    /// and **`impl`s for the generated `ffi_enum` type**. Note that helper attributes attached below this
37    /// `ffi_enum` attribute would also be seen by such derive macros.
38    ///
39    /// 2. `#[ffi_enum(derive(...))]` passed within this attribute would **both** see the definition of and takes
40    /// all effects on **the generated `ffi_enum` type**. All helper attributes passed within this attribute
41    /// would **only** be been by the derive macros passed in this way.
42    ///
43    /// 3. `#[derive(...)]` attached below `ffi_enum` would **both** see the definition of and takes
44    /// all effects on the **the original `enum` definition**.
45    ///
46    /// Derive macros that works on regular `enum`s may simply works fine at Position `1` described above,
47    /// unless the expanded code `match`es the value of the generated `ffi_enum` type **without a
48    /// `_` wildcard pattern** that covers other unknown values that would potentially come from ffi.
49    ///
50    /// As for the derive macros that does not care the variant details, or normally logically works fine for a
51    /// struct that contaions a single field,  attach the derive macros along with
52    /// their helper attributes at Position `2`. Derive macros passed in this way would see a `ffi_enum_origin`
53    /// helper attribute with the original enum definition passed as the arguments. If you are authoring a derive
54    /// macro that may need to see both the original and generated definitions, this way is preferred.
55    ///
56    /// As for the derive macros that generate `match`ing code without wildcards, or the implemention of which is
57    /// logically insufficient for the generated `ffi_enum` type that covers all binary patterns. The only
58    /// way of automatic deriving is to `derive` at Position `3` described above, which implements for the original
59    /// `enum` definition, and then delegate the implementations from the original `enum` definition which could
60    /// accessed as `<TypeName as ffi_enum::FfiEnum>::Enum`.
61    ///
62    /// This attribute macro would automatically delegate implementations for the generated `ffi_enum` type
63    /// for supported traits. The currently supported derives are:
64    ///
65    /// + `core::fmt::Debug`
66    /// + `core::fmt::Display` (The derive macro for the original `enum` is not hereby specified, user may use any
67    /// one that implements it for the original type)
68    /// + `core::hash::Hash`
69    /// + `core::str::FromStr` (The derive macro for the original `enum` is not hereby specified, user may use any
70    /// one that implements it for the original type)
71    /// + `thiserror::Error` implementing `core::error::Error` and `core::fmt::Display`
72    /// + `serde::Serialize`
73    /// + `serde::Deserialize`
74    ///
75    /// For more automatically delegatings, contributions are welcomed.
76    ffi_enum
77);
78
79#[doc(hidden)]
80#[proc_macro_derive(NoDerive, attributes(ffi_enum_origin))]
81pub fn no_derive(_: TokenStream) -> TokenStream {
82    TokenStream::new()
83}