Expand description
Procedural macro implementation for asyncapi-rust
This crate provides the procedural macros that power asyncapi-rust, enabling
compile-time generation of AsyncAPI 3.0 specifications from Rust code.
§Overview
Two derive macros are provided:
§#[derive(ToAsyncApiMessage)]
Generates message metadata and JSON schemas from Rust types (structs or enums).
- Works with
serdefor serialization patterns - Uses
schemarsfor JSON Schema generation - Supports
#[asyncapi(...)]helper attributes for documentation - Generates methods:
asyncapi_message_names(),asyncapi_messages(), etc.
Example:
use asyncapi_rust::{ToAsyncApiMessage, schemars::JsonSchema};
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, JsonSchema, ToAsyncApiMessage)]
#[serde(tag = "type")]
pub enum ChatMessage {
#[serde(rename = "user.join")]
#[asyncapi(
summary = "User joins",
description = "Sent when a user enters a room"
)]
UserJoin { username: String, room: String },
#[serde(rename = "chat.message")]
#[asyncapi(summary = "Chat message")]
Chat { username: String, room: String, text: String },
}
// Generated methods available:
let names = ChatMessage::asyncapi_message_names();
let messages = ChatMessage::asyncapi_messages(); // Requires JsonSchema§#[derive(AsyncApi)]
Generates complete AsyncAPI 3.0 specifications with servers, channels, and operations.
- Requires
titleandversionattributes - Supports optional
descriptionattribute - Use
#[asyncapi_server(...)]to define servers - Use
#[asyncapi_channel(...)]to define channels - Use
#[asyncapi_operation(...)]to define operations - Can use multiple of each attribute type
Example:
use asyncapi_rust::AsyncApi;
#[derive(AsyncApi)]
#[asyncapi(
title = "Chat API",
version = "1.0.0",
description = "Real-time chat application"
)]
#[asyncapi_server(
name = "production",
host = "chat.example.com",
protocol = "wss",
description = "Production WebSocket server"
)]
#[asyncapi_channel(
name = "chat",
address = "/ws/chat"
)]
#[asyncapi_operation(
name = "sendMessage",
action = "send",
channel = "chat"
)]
#[asyncapi_operation(
name = "receiveMessage",
action = "receive",
channel = "chat"
)]
struct ChatApi;
// Generated method:
let spec = ChatApi::asyncapi_spec();§Supported Attributes
§#[asyncapi(...)] on message types
Helper attributes for documenting messages (used with ToAsyncApiMessage):
summary = "..."- Short summary of the messagedescription = "..."- Detailed descriptiontitle = "..."- Human-readable title (defaults to message name)content_type = "..."- Content type (defaults to “application/json”)triggers_binary- Flag for binary messages (sets content_type to “application/octet-stream”)
§#[asyncapi(...)] on API specs
Required attributes for complete specifications (used with AsyncApi):
title = "..."- API title (required)version = "..."- API version (required)description = "..."- API description (optional)
§#[asyncapi_server(...)]
Define server connection information:
name = "..."- Server identifier (required)host = "..."- Server host/URL (required)protocol = "..."- Protocol (e.g., “wss”, “ws”, “grpc”) (required)description = "..."- Server description (optional)
§#[asyncapi_channel(...)]
Define communication channels:
name = "..."- Channel identifier (required)address = "..."- Channel path/address (optional)
§#[asyncapi_operation(...)]
Define send/receive operations:
name = "..."- Operation identifier (required)action = "send"|"receive"- Operation type (required)channel = "..."- Channel reference (required)
§Integration with serde
The macros respect serde attributes for naming and structure:
#[serde(rename = "...")]- Use custom name in AsyncAPI spec#[serde(tag = "...")]- Tagged enum with discriminator field#[serde(skip)]- Exclude fields from schema#[serde(skip_serializing_if = "...")]- Optional fields
§Integration with schemars
JSON schemas are generated automatically using schemars:
- Requires
JsonSchemaderive on message types - Generates complete JSON Schema from Rust type definitions
- Supports nested types, generics, and references
- Schemas include validation rules from type constraints
§Generated Code
The macros generate implementations with these methods:
From ToAsyncApiMessage:
asyncapi_message_names() -> Vec<&'static str>- Get all message namesasyncapi_message_count() -> usize- Number of messagesasyncapi_tag_field() -> Option<&'static str>- Serde tag field if presentasyncapi_messages() -> Vec<Message>- Generate messages with schemas
From AsyncApi:
asyncapi_spec() -> AsyncApiSpec- Generate complete specification
§Implementation Notes
- All code generation happens at compile time (proc macros)
- Zero runtime cost - generates plain Rust code
- Compile errors if documentation drifts from code
- Type-safe - uses Rust’s type system for validation
Derive Macros§
- Async
Api - Derive macro for generating complete AsyncAPI specification
- ToAsync
ApiMessage - Derive macro for generating AsyncAPI message metadata