2个不稳定版本
0.2.0 | 2021年2月5日 |
---|---|
0.1.0 | 2021年2月5日 |
#629 in 过程宏
27KB
504 行
actix_handler_macro
Actix使用的辅助宏。
use actix::Message;
use actix_handler_macro::{actix_handler, Actor};
#[derive(Actor)]
struct Example;
type ExampleContext = actix::Context<Example>;
#[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;
允许使用impl块编写Actix actor。
动机
当声明处理器时,Actix可能相当冗长
use actix::Actor;
use actix::Context;
use actix::Handler;
use actix::Message;
struct Example;
impl Actor for Example {
type Context = Context<Example>;
}
#[derive(Message)]
#[rtype(result = "String")]
struct Greeting { name: String }
impl Handler<Greeting> for Example {
type Result = String;
fn handle(&mut self, msg: Greeting, ctx: &mut Context<Self>) -> Self::Result {
unimplemented!()
}
}
actix_derive_macro
读取一个impl
块并为每个方法生成一些代码。
用法
use actix_handler_macro::{Actor, actix_handler};
use actix::{Actor, Addr, Context, Message, System};
#[derive(Actor)]
struct Example;
type ExampleContext = Context<Example>;
#[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> = 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")
});
}
这将为Example中的每个方法扩展一个Handler<Greeting>
实现。
Actor ...Addr
特质
它还将输出一个名为GreetingAddr
的特质及其实现,用于Addr<Example>
的便捷方法
// Example output
trait GreetingAddr {
fn greet(self: &Self, msg: Greeting) -> actix::prelude::Request<Example, Greeting>;
}
RecipientRequest
可选地,该特质可以使用actix::Recipient
并返回一个actix::RecipientRequest
。
use actix::{Message};
use actix_handler_macro::{actix_handler, Actor};
#[derive(Actor)]
struct Example;
type ExampleContext = actix::Context<Example>;
#[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)]
将扩展GreetingAddr
特质为
// Example output
trait GreetingAddr {
fn greet(self: &Self, msg: Greeting) -> actix::RecipientRequest<Greeting>;
}
actor的模拟可以实现为
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<actix::actors::mocker::Mocker<Example>>,
}
impl GreetingAddr for ExampleMock {
fn greet(self: &Self, msg: Greeting) -> actix::prelude::RecipientRequest<Greeting> {
self.mocker.clone().recipient().send(msg)
}
}
依赖项
~1.5MB
~35K SLoC