safer_ffi_gen_macro/
lib.rs1use quote::ToTokens;
2use syn::{parse_macro_input, punctuated::Punctuated, Item, Meta, Token};
3
4mod enum_to_error_code;
5mod error;
6mod ffi_module;
7mod ffi_signature;
8mod ffi_type;
9mod specialization;
10#[cfg(test)]
11mod test_utils;
12mod utils;
13
14use enum_to_error_code::impl_enum_to_error_code;
15use error::{Error, ErrorReason};
16use ffi_module::{FfiModule, ImplSpecialization};
17use ffi_signature::{FfiSignature, FfiSignatureOptions, FunctionSpecialization};
18use ffi_type::process_ffi_type;
19use specialization::Specialization;
20
21#[proc_macro_attribute]
22pub fn safer_ffi_gen(
23 attr: proc_macro::TokenStream,
24 mut item: proc_macro::TokenStream,
25) -> proc_macro::TokenStream {
26 let input = {
27 let item = item.clone();
28 parse_macro_input!(item as Item)
29 };
30
31 let output = match input {
32 Item::Fn(f) => {
33 let options = parse_macro_input!(attr as FfiSignatureOptions);
34 FfiSignature::new(options, f).map(ToTokens::into_token_stream)
35 }
36 Item::Impl(impl_block) => FfiModule::new(impl_block).map(ToTokens::into_token_stream),
37 _ => Err(ErrorReason::UnsupportedItemType.spanned(input)),
38 };
39
40 let output = output
41 .map_err(Into::into)
42 .unwrap_or_else(syn::Error::into_compile_error);
43
44 item.extend([proc_macro::TokenStream::from(output)]);
45 item
46}
47
48#[proc_macro_attribute]
50pub fn safer_ffi_gen_ignore(
51 _: proc_macro::TokenStream,
52 item: proc_macro::TokenStream,
53) -> proc_macro::TokenStream {
54 item
55}
56
57#[proc_macro_attribute]
58pub fn ffi_type(
59 args: proc_macro::TokenStream,
60 input: proc_macro::TokenStream,
61) -> proc_macro::TokenStream {
62 let args = parse_macro_input!(args with Punctuated::<Meta, Token![,]>::parse_terminated);
63 let ty_def = parse_macro_input!(input as syn::Item);
64
65 process_ffi_type(args, ty_def)
66 .map(ToTokens::into_token_stream)
67 .map_err(Into::into)
68 .unwrap_or_else(syn::Error::into_compile_error)
69 .into()
70}
71
72#[proc_macro_attribute]
73pub fn enum_to_error_code(
74 _: proc_macro::TokenStream,
75 item: proc_macro::TokenStream,
76) -> proc_macro::TokenStream {
77 let mut input = item.clone();
78 let enum_def = parse_macro_input!(item as syn::ItemEnum);
79 let generated = impl_enum_to_error_code(enum_def)
80 .map_err(Into::into)
81 .unwrap_or_else(syn::Error::into_compile_error);
82 input.extend(proc_macro::TokenStream::from(generated));
83 input
84}
85
86#[proc_macro]
87pub fn specialize(args: proc_macro::TokenStream) -> proc_macro::TokenStream {
88 let decl = parse_macro_input!(args as Specialization);
89 decl.to_token_stream().into()
90}
91
92#[doc(hidden)]
93#[proc_macro]
94pub fn __specialize_impl(args: proc_macro::TokenStream) -> proc_macro::TokenStream {
95 let specialization = parse_macro_input!(args as ImplSpecialization);
96 specialization.to_token_stream().into()
97}
98
99#[doc(hidden)]
100#[proc_macro]
101pub fn __specialize_function(args: proc_macro::TokenStream) -> proc_macro::TokenStream {
102 let specialization = parse_macro_input!(args as FunctionSpecialization);
103 specialization.to_token_stream().into()
104}