tactix_macros/lib.rs
1//! Derive macro for the `Message` trait.
2//!
3//! # Usage
4//!
5//! ```rust,ignore
6//! use macros::Message;
7//!
8//! // Fire-and-forget message (Response = ())
9//! #[derive(Message)]
10//! struct Increment;
11//!
12//! // Message with a response
13//! #[derive(Message)]
14//! #[response(u64)]
15//! struct GetCount;
16//! ```
17
18use proc_macro::TokenStream;
19use quote::quote;
20use syn::{parse_macro_input, parse_quote, DeriveInput, Type};
21
22/// Derives the [`Message`] trait for a struct or enum.
23///
24/// The response type defaults to `()` and can be overridden with the
25/// `#[response(Type)]` attribute.
26///
27/// # Example
28///
29/// ```rust,ignore
30/// #[derive(Message)]
31/// #[response(String)]
32/// struct Greet(String);
33/// ```
34#[proc_macro_derive(Message, attributes(response))]
35pub fn derive_message(input: TokenStream) -> TokenStream {
36 let input = parse_macro_input!(input as DeriveInput);
37 let name = &input.ident;
38
39 let response_type = input
40 .attrs
41 .iter()
42 .find(|attr| attr.path().is_ident("response"))
43 .map(|attr| {
44 attr.parse_args::<Type>()
45 .expect("Expected #[response(Type)]")
46 })
47 .unwrap_or_else(|| parse_quote!(()));
48
49 quote! {
50 impl Message for #name {
51 type Response = #response_type;
52 }
53 }
54 .into()
55}