trillium-macros
crate!This crate currently offers a derive macro for Handler that can be used to delegate Handler behavior to a contained Handler type. Currently it only works for structs, but will eventually support enums as well. Note that it will only delegate to a single inner Handler type.
In the case of a newtype struct or named struct with only a single
field, #[derive(Handler)]
is all that's required. If there is more
than one field in the struct, annotate exactly one of them with
As of v0.0.2, deriving Handler makes an effort at adding Handler
bounds to generics contained within the #[handler]
type. It may be
overzealous in adding those bounds, in which case you'll need to
implement Handler yourself.
``rust
// for these examples, we are using a
&'static str` as the handler type.
use trillium_macros::Handler;
struct NewType(&'static str); assert_handler(NewType("yep"));
struct TwoTypes(usize, #[handler] &'static str); assert_handler(TwoTypes(2, "yep"));
struct NamedSingleField { thisisthehandler: &'static str, } asserthandler(NamedSingleField { thisisthe_handler: "yep" });
struct NamedMultiField { nothandler: usize, #[handler] innerhandler: &'static str, alsonothandler: usize, }
asserthandler(NamedMultiField { nothandler: 1, innerhandler: "yep", alsonot_handler: 3, });
struct Generic
struct ContainsHandler { thehandler: (A, B) } asserthandler(ContainsHandler { the_handler: ("hi", trillium::Status::Ok) });
```
Annotate the handler with a
trillium::Handler
function name #[handler(overrride = FN_NAME)]
where FN_NAME is one of
run
, before_send
, name
, has_upgrade
, or upgrade
, and
implement the same signature on Self. The rest of the Handler
interface will be delegated to the inner Handler, but your custom
implementation for the specified function will be called instead.
```rust use trillium_macros::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" }; asserteq!(trillium::Handler::name(&handler), "custom name (handler)"); asserthandler(handler); ```
Annotate the handler with any number of
trillium::Handler
function names #[handler(except = [run, before_send, name, has_upgrade,
upgrade])]
and implement the trillium Handler signature of that name
on Self.
```rust use trillium_macros::Handler; use trillium::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); ```