Attribute Macro medea_macro::dispatchable

source ·
#[dispatchable]
Expand description

Generates a *Handler trait and dispatching function for some event, represented as enum.

How to use

1. Declare enum for event variants and a struct to handle them.

use medea_macro::dispatchable;

#[dispatchable]
enum Event {
    Some { new_bar: i32 },
    Another,
    UnnamedVariant(i32, i32),
}

struct Foo {
    bar: i32,
    baz: i32,
}

2. Implement handler for your struct.

For the given enum macro generates a unique trait by adding Handler to the end of its name. Each method of trait is created by snake_case’ing enum variants and adding on_ prefix.

type Output is a type which will be returned from all functions of EventHandler trait.

impl EventHandler for Foo {
    type Output = i32;

    fn on_some(&mut self, new_bar: i32) -> Self::Output {
        self.bar = new_bar;
        self.bar
    }

    fn on_another(&mut self) -> Self::Output {
        self.bar = 2;
        self.bar
    }

    fn on_unnamed_variant(&mut self, data: (i32, i32)) -> Self::Output {
        self.bar = data.0;
        self.baz = data.1;
        self.bar
    }
}

3. Dispatch event with handler

For the given enum macro generates dispatch_with() method to dispatch enum with a given handler.

let mut foo = Foo { bar: 0, baz: 0 };

let bar = Event::Some { new_bar: 1 }.dispatch_with(&mut foo);
assert_eq!(foo.bar, 1);
assert_eq!(bar, 1);

let bar = Event::Another.dispatch_with(&mut foo);
assert_eq!(foo.bar, 2);
assert_eq!(bar, 2);

let bar = Event::UnnamedVariant(3, 3).dispatch_with(&mut foo);
assert_eq!(foo.bar, 3);
assert_eq!(foo.baz, 3);
assert_eq!(bar, 3);

Customize self type in handler functions (optional)

By default, all handler functions take &mut Self, if this doesn’t suit your case, then you can specify the method receiver manually: #[dispatchable(self: Rc<Self>)], #[dispatchable(self: &Self)].

You can use any type that is a valid self receiver, e.g. self, &self, &mut self, self: Box<Self>, self: Rc<Self>, self: Arc<Self>, or self: Pin<P> (where P is one of the previous, except Self).

use medea_macro::dispatchable;

#[dispatchable(self: Rc<Self>)]
enum Event {
    Variant,
}

struct Foo;
impl EventHandler for Foo {
   type Output = ();

   fn on_variant(self: Rc<Self>) {}
}

let foo = Rc::new(Foo);

Event::Variant.dispatch_with(foo);

Async handlers (optional)

It’s possible to make handler methods async. Rust doesn’t support async trait methods at the moment, that’s why async_trait is used.

use async_trait::async_trait;
use medea_macro::dispatchable;

#[dispatchable(async_trait(?Send))]
enum Event {
    Variant,
}

struct Foo;
#[async_trait(?Send)]
impl EventHandler for Foo {
   type Output = ();

   async fn on_variant(&mut self) {}
}

let mut foo = Foo;

Event::Variant.dispatch_with(&mut foo);