2 releases
0.3.1 | Dec 6, 2024 |
---|---|
0.3.0 | Dec 6, 2024 |
#401 in Procedural macros
292 downloads per month
11KB
113 lines
event_bridge
A procedural macro that generates asynchronous event handlers from enum definitions, automatically dispatching enum variants to associated trait methods. This reduces boilerplate and simplifies the integration between synchronous UI events and asynchronous backend logic.
Motivation
In many applications, especially those with graphical user interfaces (GUIs),
input from the UI thread must be forwarded to asynchronous backend services or
controllers. Writing repetitive match
expressions to route each event to its
corresponding async API method can be tedious and error-prone.
event_bridge
streamlines this process. By annotating your event enum
with a
custom procedural macro, you automatically get an async event handler method
that matches each variant and calls the appropriately named method on your
specified API trait.
How It Works
When you apply the #[derive(EventBridge)]
macro to your event enum,
it generates a forward_to
method that:
- Consumes your event (the enum variant).
- Matches the event variant to the corresponding async trait method based on variant naming.
- Calls the trait method with the extracted fields from the enum variant.
- Returns the specified return type of the trait methods.
This significantly reduces the boilerplate involved in writing match
arms and
manually forwarding arguments for each new event added to your application.
Installation
Add event_bridge
and async-trait
to your Cargo.toml
:
[dependencies]
event_bridge = "0.1.0"
async-trait = "0.1"
Quick Start
use async_trait::async_trait;
use event_bridge::EventBridge;
use std::sync::Arc;
use tokio::sync::Mutex;
// Define a custom error type for demonstration
type MyReturnType = Result<(), String>;
// Define an event enum and associate it with a trait and error type
#[derive(EventBridge)]
#[forward_to_trait(MyApiTrait)]
#[trait_returned_type(MyReturnType)]
pub enum Event {
SetValue(i32),
SetName(String),
Initialize,
}
// Define the API trait that corresponds to the event variants
#[async_trait]
pub trait MyApiTrait {
async fn set_value(&mut self, value: i32) -> MyReturnType;
async fn set_name(&mut self, name: String) -> MyReturnType;
async fn initialize(&mut self) -> MyReturnType;
}
// Example usage
#[tokio::main]
async fn main() {
// Assume `MyApiImpl` implements `MyApiTrait`
let mut api_impl = MyApiImpl::new();
// Example event to dispatch to the API implementation
let some_event = Event::SetValue(42);
// Dispatching an event becomes straightforward:
let result = some_event.forward_to(&mut api_impl).await;
}
Configuration
The macro supports two attributes on the enum:
-
#[forward_to_trait(TraitName)]
(required)Specifies the trait that defines the async methods corresponding to each enum variant.
-
#[trait_returned_type(ReturnType)]
(optional)Specifies the return type returned by the generated event handler. If omitted, the handler defaults to
()
.
Supported Variants
The macro handles various enum variants:
#[derive(EventBridge)]
#[forward_to_trait(Handler)]
enum Event {
NoArgs, // Unit variant
SingleArg(String), // Single argument
MultipleArgs(i32, String), // Multiple arguments
NamedFields { id: i32 }, // Named fields
}
Each variant must correspond to a method in the specified trait. The method name
is derived from the variant name converted to snake_case
, and the method
arguments match the variant’s fields in order and type.
Error Handling
Ensure that your trait methods return the appropriate type to maintain consistency.
License
This project is licensed under the MIT license.
Contributing
Contributions, issues, and pull requests are welcome. Feel free to open a discussion on GitHub if you have any questions or suggestions.
Dependencies
~225–670KB
~16K SLoC