6 个版本
0.0.6 | 2024 年 4 月 7 日 |
---|---|
0.0.5 | 2024 年 1 月 2 日 |
0.0.4 | 2023 年 4 月 21 日 |
0.0.2 | 2023 年 3 月 17 日 |
#37 在 #trillium 中
4,900 每月下载量
用于 50 个crate(直接使用 7 个)
36KB
793 行
欢迎来到 trillium-macros
crate!
此crate提供了为Handler
、AsyncRead
、AsyncWrite
和Transport
提供的 derive 宏。
derive(Handler)
此crate目前提供了一种 derive 宏,可用于将 Handler 行为委托给包含的 Handler 类型。目前它仅适用于结构体,但最终也将支持枚举。请注意,它只能委托给单个内部 Handler 类型。
对于新类型结构体或只有一个字段的命名结构体,只需要在结构体上使用#[derive(Handler)]
即可。如果结构体中有多个字段,请注释其中一个字段为#[handler]
。
截至 v0.0.2,使用 Handler derive 会尝试为#[handler]
类型中的泛型添加 Handler 约束。它可能会过于热情地添加这些约束,在这种情况下,您需要自己实现 Handler。
// for these examples, we are using a `&'static str` as the handler type.
use trillium_macros::Handler;
# fn assert_handler(_h: impl trillium::Handler) {}
#[derive(Handler)]
struct NewType(&'static str);
assert_handler(NewType("yep"));
#[derive(Handler)]
struct TwoTypes(usize, #[handler] &'static str);
assert_handler(TwoTypes(2, "yep"));
#[derive(Handler)]
struct NamedSingleField {
this_is_the_handler: &'static str,
}
assert_handler(NamedSingleField { this_is_the_handler: "yep" });
#[derive(Handler)]
struct NamedMultiField {
not_handler: usize,
#[handler]
inner_handler: &'static str,
also_not_handler: usize,
}
assert_handler(NamedMultiField {
not_handler: 1,
inner_handler: "yep",
also_not_handler: 3,
});
#[derive(Handler)]
struct Generic<G>(G);
assert_handler(Generic("hi"));
assert_handler(Generic(trillium::Status::Ok));
#[derive(Handler)]
struct ContainsHandler<A, B> {
the_handler: (A, B)
}
assert_handler(ContainsHandler {
the_handler: ("hi", trillium::Status::Ok)
});
重写单个 trait 函数
使用 trillium::Handler
函数名注释处理器,形式为 #[handler(overrride = FN_NAME)]
,其中 FN_NAME
是 run
、before_send
、name
、has_upgrade
或 upgrade
之一,并在 Self 上实现相同的签名。Handler 接口的其他部分将委托给内部 Handler,但将调用指定的函数的自定义实现。
use trillium_macros::Handler;
# fn assert_handler(_h: impl trillium::Handler) {}
#[derive(Handler)]
struct CustomName {
#[handler(except = name)]
inner: &'static str
}
impl CustomName { // note that this is not a trait impl
fn name(&self) -> std::borrow::Cow<'static, str> {
format!("custom name ({})", &self.inner).into()
}
}
let handler = CustomName { inner: "handler" };
assert_eq!(trillium::Handler::name(&handler), "custom name (handler)");
assert_handler(handler);
覆盖多个 trait 函数
使用任何数量的 trillium::Handler
函数名注释处理器,形式为 #[handler(except = [run, before_send, name, has_upgrade, upgrade])]
并在 Self 上实现该名称的 trillium Handler 签名。
use trillium_macros::Handler;
use trillium::Handler;
# fn assert_handler(_h: impl trillium::Handler) {}
#[derive(Handler)]
struct CustomName {
#[handler(except = [run, before_send])]
inner: &'static str
}
impl CustomName { // note that this is not a trait impl
async fn run(&self, conn: trillium::Conn) -> trillium::Conn {
// this is an uninspired example but we might do something
// before or after running the inner handler here
self.inner.run(conn).await
}
async fn before_send(&self, conn: trillium::Conn) -> trillium::Conn {
// this is an uninspired example but we might do something
// before or after running the inner handler here
self.inner.before_send(conn).await
}
}
let handler = CustomName { inner: "handler" };
assert_handler(handler);
derive(AsyncRead)
和 derive(AsyncWrite)
为了简化 Transport
类型的开发,此包提供 proc macros 以推导 AsyncRead
和 AsyncWrite
并将其委托给类型的字段。
要将所有 AsyncRead
和 AsyncWrite
方法委托到相应字段的相应方法,请在该字段上标记 #[async_io]
。
use trillium_http::transport::BoxedTransport;
use trillium_macros::{AsyncRead, AsyncWrite};
use trillium_server_common::{AsyncRead, AsyncWrite};
#[derive(Debug, AsyncRead, AsyncWrite)]
struct TransportWrapper {
#[async_io]
inner: BoxedTransport,
another_field: u32,
}
要将 AsyncRead
和 AsyncWrite
委托到不同的字段,分别使用 #[async_read]
和 #[async_write]
标记这些字段。
对于只有一个字段的 struct,这些注释是可选的。
derive(Transport)
此包提供了一个 proc macro 来推导 Transport
类型并将其委托到类型的字段
use trillium_http::transport::BoxedTransport;
use trillium_macros::{AsyncRead, AsyncWrite, Transport};
use trillium_server_common::{AsyncRead, AsyncWrite, Transport};
#[derive(Debug, AsyncRead, AsyncWrite, Transport)]
struct TransportWrapper {
#[transport] #[async_io]
inner: BoxedTransport,
another_field: u32,
}
这支持与 derive(Handler)
相同的机制,用于覆盖单个方法
use trillium_http::transport::BoxedTransport;
use trillium_macros::{AsyncRead, AsyncWrite, Transport};
use trillium_server_common::{AsyncRead, AsyncWrite, Transport};
#[derive(Debug, AsyncRead, AsyncWrite, Transport)]
struct TransportWrapper {
#[transport(except = peer_addr)] #[async_io]
inner: BoxedTransport,
another_field: u32,
}
impl TransportWrapper { // note that this is not a trait impl
fn peer_addr(&self) -> std::io::Result<Option<std::net::SocketAddr>> {
Ok(None)
}
}
依赖项
~260–710KB
~17K SLoC