ffizz_macros/
lib.rs

1mod headeritem;
2mod item;
3mod snippet;
4
5use proc_macro::TokenStream;
6use proc_macro2::TokenStream as TokenStream2;
7
8/// Generate C header content from the included docstring.
9///
10/// This macro operates much like `#[ffizz_header::item]`, but can be applied when there is no Rust
11/// item to document.  The `#[ffizz(name="..")]` attribute must always be supplied, and order is
12/// usually supplied as well.
13///
14/// # Example
15///
16/// ```text
17/// # ignored because ffizz_header isn't available in doctests
18/// ffizz_header::snippet! {
19///     #[ffizz(name="invariants", order=10)]
20///     /// LIBRARY INVARIANTS
21///     ///
22///     /// This library maintains the following invariants:
23///     ///  * what goes up, must come down
24/// }
25/// ```
26///
27/// produces
28///
29/// ```text
30/// // LIBRARY INVARIANTS
31/// //
32/// // This library maintains the following invariants:
33/// //  * what goes up, must come down
34/// ```
35#[proc_macro]
36pub fn snippet(item: TokenStream) -> TokenStream {
37    let snip = syn::parse_macro_input!(item as snippet::Snippet);
38    let mut tokens = TokenStream2::new();
39    snip.to_tokens(&mut tokens);
40    tokens.into()
41}
42
43/// Generate C header content from the docstring on this item.
44///
45/// # Docstring Parsing
46///
47/// The generated C header content contains C-style comments with the content of the Rust
48/// docstring.
49///
50/// Any blocks delimited by triple-backticks with the `c` type will be included in the header as C
51/// code.  This should give the C declaration for the Rust item.
52///
53/// # Ordering
54///
55/// The header file is generated by concatenating the content supplied by this macro any by
56/// `ffizz_header::snippet!`.  Each piece of content has "order" and "name" properties, and these
57/// are used to sort the content in the header file.  The name must also be unique within the
58/// resulting library.  The "order" property defaults to `100` and "name" defaults to the name of
59/// the Rust item.  Both can be overridden with a `ffizz` attribute:
60///
61/// ```text
62/// #[ffizz(name="FOO_free")]
63/// #[ffizz(order=200)]
64/// #[ffizz(name="FOO_free", order=200)]
65/// ```
66///
67/// # Example
68///
69/// ```text
70/// #[ffizz_header::item]
71/// /// Free a foo_t.  The given foo_t must not be used after this
72/// /// call.
73/// ///
74/// /// ```c
75/// /// void foo_free(*foo_t);
76/// /// ```
77/// pub unsafe extern "C" fn foo_free(*mut foo_t) { .. }
78/// ```
79///
80/// produces
81///
82/// ```text
83/// // Free a foo_t.  The given foo_t must not be used after this
84/// // call.
85/// void foo_free(*foo_t);
86/// ```
87#[proc_macro_attribute]
88pub fn item(_attr: TokenStream, item: TokenStream) -> TokenStream {
89    let docitem = syn::parse_macro_input!(item as item::DocItem);
90    let mut tokens = TokenStream2::new();
91    docitem.to_tokens(&mut tokens);
92    tokens.into()
93}