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}