1use darling::FromDeriveInput as _;
4use proc_macro::TokenStream;
5
6mod bind_callback;
7mod bind_push_child;
8mod bind_set_child;
9mod bind_text;
10mod container;
11mod subcontrol;
12mod widget;
13
14macro_rules! attribute_macro {
15 ($name:ident $ty:ty) => {
16 #[proc_macro_attribute]
17 pub fn $name(attr: TokenStream, item: TokenStream) -> TokenStream {
18 let attr = syn::parse_macro_input!(attr as syn::AttributeArgs);
19
20 $name::expand(
21 darling::FromMeta::from_list(&attr).unwrap(),
22 syn::parse_macro_input!(item as $ty),
23 )
24 }
25 };
26}
27
28macro_rules! derive_macro {
29 ($name:ident $mod:ident $trait:ident) => {
30 #[proc_macro_derive($trait, attributes($mod))]
31 pub fn $name(input: TokenStream) -> TokenStream {
32 let input = syn::parse_macro_input!(input as syn::DeriveInput);
33 let attr = $mod::Attr::from_derive_input(&input).unwrap();
34
35 $mod::expand(attr, input)
36 }
37 };
38}
39
40attribute_macro!(bind_callback syn::ItemFn);
41attribute_macro!(bind_push_child syn::ForeignItemFn);
42attribute_macro!(bind_set_child syn::ForeignItemFn);
43attribute_macro!(bind_text syn::ForeignItemFn);
44attribute_macro!(subcontrol syn::ItemStruct);
45
46derive_macro!(derive_container container Container);
47derive_macro!(derive_widget widget Widget);
48
49mod prelude {
50 pub fn collect_attrs(
51 attrs: impl IntoIterator<Item = syn::Attribute>,
52 ) -> quote::__private::TokenStream {
53 attrs.into_iter().map(quote::ToTokens::into_token_stream).collect()
57 }
58
59 pub fn extract_immut_recv(args: &mut impl Iterator<Item = syn::FnArg>) -> syn::Receiver {
60 args.next()
61 .and_then(|arg| match arg {
62 syn::FnArg::Receiver(it) => Some(it),
63 _ => None,
64 })
65 .filter(|arg| arg.mutability.is_none())
66 .expect("expected &self argument")
67 }
68
69 pub fn assert_no_extra_args(args: &mut impl Iterator<Item = syn::FnArg>) {
70 assert!(args.next().is_none(), "found extraneous arguments");
71 }
72
73 pub fn assert_ret_ty_is_inferred(ret_ty: &syn::ReturnType) {
74 let is_inferred = match ret_ty {
75 syn::ReturnType::Default => false,
76 syn::ReturnType::Type(_, ty) => matches!(**ty, syn::Type::Infer(_)),
77 };
78 assert!(is_inferred, "expected return type of _");
79 }
80
81 #[derive(darling::FromMeta)]
82 pub struct BindFnAttr {
83 #[darling(rename = "fn")]
84 pub libui_fn: syn::Ident,
85 }
86}