kstool_helper_generator/lib.rs
1mod basic;
2mod bit;
3mod enchanted;
4
5/// Derive macro that generates an MPSC channel helper struct for an enum.
6///
7/// The enum name must contain "Event" (e.g., `MyEvent`). The macro generates:
8/// - A helper struct named `{Prefix}Helper` (e.g., `MyHelper` from `MyEvent`)
9/// - A receiver type alias named `{EnumName}Receiver`
10/// - Async send methods for each enum variant (names converted to snake_case)
11/// - A `new(size)` constructor returning `(Helper, Receiver)` tuple
12/// - A `From<mpsc::Sender>` impl for the helper struct
13///
14/// # Attributes
15///
16/// - `#[helper(block)]` on the enum or variant: also generate blocking send methods (suffixed with `_b`)
17/// - `#[helper(no_async)]` on the enum or variant: generate only blocking send methods (no async)
18///
19/// # Example
20///
21/// ```rust,ignore
22/// #[derive(Helper)]
23/// enum MyEvent {
24/// UserLogin { username: String },
25/// UserLogout,
26/// DataUpdate(Vec<u8>),
27/// }
28/// // Generates: MyHelper with async methods user_login(), user_logout(), data_update()
29/// ```
30#[proc_macro_derive(Helper, attributes(helper))]
31pub fn enum_helper_generator(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
32 let st = syn::parse_macro_input!(input as syn::DeriveInput);
33 //eprintln!("{:#?}", st.attrs);
34 //eprintln!("{st:#?}");
35
36 if let Err(e) = crate::basic::early_check(&st) {
37 return e.into_compile_error().into();
38 }
39
40 basic::do_expand(&st, None)
41 .unwrap_or_else(syn::Error::into_compile_error)
42 .into()
43}
44
45/// Procedural macro that generates a bit flag enum with checker methods.
46///
47/// Each variant is assigned a unique power-of-two value (`1 << index`), and a
48/// corresponding `is_{snake_case_name}()` method is generated on the enum.
49///
50/// The macro also derives `Clone`, `Copy`, and `Debug` for the generated enum.
51///
52/// # Example
53///
54/// ```rust,ignore
55/// bit_helper! {
56/// enum Features {
57/// Analytics, // = 1
58/// Notifications, // = 2
59/// DarkMode, // = 4
60/// }
61/// }
62/// // Generates: Features with methods is_analytics(), is_notifications(), is_dark_mode()
63/// ```
64#[proc_macro]
65pub fn bit_helper(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
66 let st = syn::parse_macro_input!(input as syn::DeriveInput);
67 //eprintln!("{:#?}", st.attrs);
68
69 bit::parse_bit(st)
70 .unwrap_or_else(|x| x.into_compile_error())
71 .into()
72}
73
74/// Procedural macro that generates an MPSC helper with request-response support
75/// via oneshot channels.
76///
77/// Similar to `#[derive(Helper)]`, but variants annotated with `#[ret(Type)]` will
78/// have their generated methods return `Option<Type>` instead of `Option<()>`. The
79/// macro automatically injects a `tokio::sync::oneshot::Sender` field into each
80/// annotated variant and manages the oneshot channel lifecycle.
81///
82/// Variants without `#[ret(...)]` behave identically to the basic `Helper` derive.
83///
84/// The enum is re-emitted with the additional sender fields, so it must be used
85/// as `oneshot_helper! { ... }` rather than as a derive macro.
86///
87/// # Example
88///
89/// ```rust,ignore
90/// oneshot_helper! {
91/// enum QueryEvent {
92/// #[ret(String)]
93/// GetConfig { key: String },
94/// #[ret(bool)]
95/// IsEnabled { feature: &'static str },
96/// Shutdown,
97/// }
98/// }
99/// // Generates: QueryHelper with methods:
100/// // async fn get_config(&self, key: String) -> Option<String>
101/// // async fn is_enabled(&self, feature: &'static str) -> Option<bool>
102/// // async fn shutdown(&self) -> Option<()>
103/// ```
104#[proc_macro]
105pub fn oneshot_helper(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
106 let early_st = syn::parse_macro_input!(input as syn::DeriveInput);
107 enchanted::handle_new(early_st)
108 .unwrap_or_else(syn::Error::into_compile_error)
109 .into()
110}