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

Download history 3328/week @ 2024-04-04 2058/week @ 2024-04-11 1526/week @ 2024-04-18 1416/week @ 2024-04-25 2259/week @ 2024-05-02 1491/week @ 2024-05-09 1505/week @ 2024-05-16 1555/week @ 2024-05-23 1984/week @ 2024-05-30 2087/week @ 2024-06-06 2124/week @ 2024-06-13 1713/week @ 2024-06-20 864/week @ 2024-06-27 1261/week @ 2024-07-04 1152/week @ 2024-07-11 1540/week @ 2024-07-18

4,900 每月下载量
用于 50 个crate(直接使用 7 个)

MIT/Apache 许可

36KB
793

欢迎来到 trillium-macros crate!

此crate提供了为HandlerAsyncReadAsyncWriteTransport提供的 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_NAMErunbefore_sendnamehas_upgradeupgrade 之一,并在 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 以推导 AsyncReadAsyncWrite 并将其委托给类型的字段。

要将所有 AsyncReadAsyncWrite 方法委托到相应字段的相应方法,请在该字段上标记 #[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,
}

要将 AsyncReadAsyncWrite 委托到不同的字段,分别使用 #[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