layer_client/macros.rs
1//! The [`dispatch!`] macro — ergonomic, pattern-matching update handler.
2//!
3//! Instead of writing giant `match` blocks, `dispatch!` lets you register
4//! named handlers with optional guard clauses:
5//!
6//! ```rust,no_run
7//! use layer_client::{Client, dispatch};
8//! use layer_client::update::Update;
9//!
10//! # async fn example(client: Client, update: Update) -> Result<(), Box<dyn std::error::Error>> {
11//! dispatch!(client, update,
12//! NewMessage(msg) if !msg.outgoing() => {
13//! println!("Got: {:?}", msg.text());
14//! },
15//! MessageEdited(msg) => {
16//! println!("Edited: {:?}", msg.text());
17//! },
18//! CallbackQuery(cb) => {
19//! client.answer_callback_query(cb.query_id, Some("✓"), false).await?;
20//! },
21//! _ => {} // catch-all for unhandled variants
22//! );
23//! # Ok(()) }
24//! ```
25//!
26//! Each arm is `VariantName(binding) [if guard] => { body }`.
27//! The macro expands to a plain `match` statement — zero overhead.
28
29/// Route a [`crate::update::Update`] to the first matching arm.
30///
31/// # Syntax
32/// ```text
33/// dispatch!(client, update,
34/// VariantName(binding) [if guard] => { body },
35/// ...
36/// [_ => { fallback }]
37/// );
38/// ```
39///
40/// - `client` — a `layer_client::Client` (available inside every arm body)
41/// - `update` — the `Update` value to dispatch
42/// - Each arm mirrors a variant of [`crate::update::Update`]
43/// - Guards (`if expr`) are optional
44/// - A catch-all `_ => {}` arm is optional but recommended to avoid warnings
45#[macro_export]
46macro_rules! dispatch {
47 // Entry point: client, update, then one or more arms
48 ($client:expr, $update:expr, $( $pattern:tt )+ ) => {
49 match $update {
50 $crate::__dispatch_arms!($client; $( $pattern )+ )
51 }
52 };
53}
54
55/// Internal helper — do not use directly.
56#[macro_export]
57#[doc(hidden)]
58macro_rules! __dispatch_arms {
59 // Catch-all arm
60 ($client:expr; _ => $body:block $( , $( $rest:tt )* )? ) => {
61 _ => $body
62 };
63
64 // Variant arm WITH guard
65 ($client:expr;
66 $variant:ident ( $binding:pat ) if $guard:expr => $body:block
67 $( , $( $rest:tt )* )?
68 ) => {
69 $crate::update::Update::$variant($binding) if $guard => $body,
70 $( $crate::__dispatch_arms!($client; $( $rest )* ) )?
71 };
72
73 // Variant arm WITHOUT guard
74 ($client:expr;
75 $variant:ident ( $binding:pat ) => $body:block
76 $( , $( $rest:tt )* )?
77 ) => {
78 $crate::update::Update::$variant($binding) => $body,
79 $( $crate::__dispatch_arms!($client; $( $rest )* ) )?
80 };
81
82 // Trailing comma / empty — emit wildcard to ensure exhaustiveness
83 ($client:expr; $(,)?) => {
84 _ => {}
85 };
86}