-
Notifications
You must be signed in to change notification settings - Fork 666
Description
When adding messages to an actor, I noticed that it very often follows some specific pattern, that involves a bit of boilerplate code:
- Create the method that does something on the
impl MyActor - Create a struct that represents the arguments of that method and derive
actix::Messagefor it - Implement
actix::Handler<SomeMessage> for MyActorby having thehandlemethod delegate to the associated method
I have the idea of reducing the boilerplate (and the number of structs) involved by having a proc-macro generate most of it. A first step towards this, which only automates the impl Handler, could look like this:
impl MyActor {
/* Simple case */
#[handler(SomeMessage)]
fn update_content(&mut self, event: SomeMessage, ctx: &mut Self::Context) { todo!() }
/* The macro needs to parse the return type from the method for the trait implementation */
#[handler(SomeMessage)]
fn update_content(&mut self, event: SomeMessage, ctx: &mut Self::Context) -> SomeResponse { todo!() }
/* Optional: if the function is `async`, automatically wrap `<MyActor as Handler<SomeMessage>>::Result` in a future */
#[handler(SomeMessage)]
async fn update_content(&mut self, event: SomeMessage, ctx: &mut Self::Context) -> SomeResponse { todo!() }
}A second step then would be to somehow extract the function arguments into their own struct. I am sorry that I cannot prototype this myself, as I don't have enough proc macro skills.
Motivation: I am working on a GTK application using woab. GTK uses a lot of signals and handlers, resulting in a lot of boilerplate code. Therefore, woab currently exposes all signals as variants of one message enum. But I think that having a proper message per signal type would be more idiomatic.