https://github.com/yamadapc/actix-handler-macro
Procedural macros for Actix Handler trait impl generation.
https://github.com/yamadapc/actix-handler-macro
actix rust
Last synced: 10 days ago
JSON representation
Procedural macros for Actix Handler trait impl generation.
- Host: GitHub
- URL: https://github.com/yamadapc/actix-handler-macro
- Owner: yamadapc
- License: mit
- Created: 2021-02-05T10:09:17.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2021-02-05T18:50:20.000Z (over 4 years ago)
- Last Synced: 2025-04-28T03:36:15.670Z (27 days ago)
- Topics: actix, rust
- Language: Rust
- Homepage: https://docs.rs/actix-handler-macro
- Size: 18.6 KB
- Stars: 0
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# actix_handler_macro

[](https://docs.rs/actix-handler-macro)
- - -Helper macros for using Actix.
```rust
use actix::Message;
use actix_handler_macro::{actix_handler, Actor};#[derive(Actor)]
struct Example;
type ExampleContext = actix::Context;#[derive(Message)]
#[rtype(result = "String")]
struct Greeting {
name: String,
}#[actix_handler]
impl Example {
fn greet(&self, message: Greeting, _ctx: &ExampleContext) -> String {
format!("Hello {}", message.name).to_string()
}
}
```
actor_derive;
expand_addr;
expand_impl_handlers;
expand_method_handlers;
options;
utils;expand_impl_handlers::expand_item_impl;
options::{parse_options, Options};
proc_macro::TokenStream;
quote::quote;
syn::{parse_macro_input, AttributeArgs, DeriveInput, Item};
utils::compilation_error;Allows writing Actix actors with impl blocks.
## Motivation
Actix can be quite verbose when declaring handlers:```rust
use actix::Actor;
use actix::Context;
use actix::Handler;
use actix::Message;struct Example;
impl Actor for Example {
type Context = Context;
}#[derive(Message)]
#[rtype(result = "String")]
struct Greeting { name: String }impl Handler for Example {
type Result = String;fn handle(&mut self, msg: Greeting, ctx: &mut Context) -> Self::Result {
unimplemented!()
}
}
````actix_derive_macro` reads an `impl` block and generates a bit of this code for each method.
## Usage
```rust
use actix_handler_macro::{Actor, actix_handler};
use actix::{Actor, Addr, Context, Message, System};#[derive(Actor)]
struct Example;type ExampleContext = Context;
#[derive(Clone, Message)]
#[rtype(result = "String")]
struct Greeting { name: String }#[actix_handler]
impl Example {
fn greet(&self, message: Greeting, _ctx: &ExampleContext) -> String {
format!("Hello {}", message.name).to_string()
}
}fn example_usage() {
let mut sys = System::new("actix-test-runtime");
let addr: Addr = Example {}.start();sys.block_on(async move {
let greeting = Greeting { name: "you".to_string() };
// `Example` has its handler impl block
let result = addr.send(greeting.clone()).await.ok().unwrap();
assert_eq!(result, "Hello you");// An Addr trait is also expanded:
let result = addr.greet(greeting.clone()).await.ok().unwrap();
assert_eq!(result, "Hello you")
});
}
```This will expand a `Handler` impl for each method in Example.
## Actor `...Addr` trait
It'll also output a trait `GreetingAddr` and its implementation for `Addr` with
convenience methods:```ignore
// Example output
trait GreetingAddr {
fn greet(self: &Self, msg: Greeting) -> actix::prelude::Request;
}
```## RecipientRequest
Optionally, the trait can use a `actix::Recipient` and return a `actix::RecipientRequest`.
```rust
use actix::{Message};
use actix_handler_macro::{actix_handler, Actor};#[derive(Actor)]
struct Example;
type ExampleContext = actix::Context;
#[derive(Message)]
#[rtype(result = "String")]
struct Greeting { name: String }#[actix_handler(use_recipient)]
impl Example {
fn greet(&self, message: Greeting, _ctx: &ExampleContext) -> String {
format!("Hello {}", message.name).to_string()
}
}
````#[actix_handler(use_recipient)]` will expand the `GreetingAddr` trait as:
```skip
// Example output
trait GreetingAddr {
fn greet(self: &Self, msg: Greeting) -> actix::RecipientRequest;
}
```A mock of the actor could be implemented as:
```skip
use actix::Message;
use actix_handler_macro::Actor;#[derive(Actor)]
struct Example;#[derive(Message)]
#[rtype(result = "String")]
struct Greeting;#[derive(Actor)]
struct ExampleMock {
mocker: actix::Addr>,
}impl GreetingAddr for ExampleMock {
fn greet(self: &Self, msg: Greeting) -> actix::prelude::RecipientRequest {
self.mocker.clone().recipient().send(msg)
}
}
```