Skip to main content

layer_client/
macros.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4// NOTE:
5// The "Layer" project is no longer maintained or supported.
6// Its original purpose for personal SDK/APK experimentation and learning
7// has been fulfilled.
8//
9// Please use Ferogram instead:
10// https://github.com/ankit-chaubey/ferogram
11// Ferogram will receive future updates and development, although progress
12// may be slower.
13//
14// Ferogram is an async Telegram MTProto client library written in Rust.
15// Its implementation follows the behaviour of the official Telegram clients,
16// particularly Telegram Desktop and TDLib, and aims to provide a clean and
17// modern async interface for building Telegram clients and tools.
18
19//! The [`dispatch!`] macro for pattern-matching over updates.
20//!
21//! Instead of writing giant `match` blocks, `dispatch!` lets you register
22//! named handlers with optional guard clauses:
23//!
24//! ```rust,no_run
25//! use layer_client::{Client, dispatch};
26//! use layer_client::update::Update;
27//!
28//! # async fn example(client: Client, update: Update) -> Result<(), Box<dyn std::error::Error>> {
29//! dispatch!(client, update,
30//! NewMessage(msg) if !msg.outgoing() => {
31//!     println!("Got: {:?}", msg.text());
32//! },
33//! MessageEdited(msg) => {
34//!     println!("Edited: {:?}", msg.text());
35//! },
36//! CallbackQuery(cb) => {
37//!     client.answer_callback_query(cb.query_id, Some("✓"), false).await?;
38//! },
39//! _ => {} // catch-all for unhandled variants
40//! );
41//! # Ok(()) }
42//! ```
43//!
44//! Each arm is `VariantName(binding) [if guard] => { body }`.
45//! The macro expands to a plain `match` statement: zero overhead.
46
47/// Route a [`crate::update::Update`] to the first matching arm.
48///
49/// # Syntax
50/// ```text
51/// dispatch!(client, update,
52/// VariantName(binding) [if guard] => { body },
53/// ...
54/// [_ => { fallback }]
55/// );
56/// ```
57///
58/// - `client` : a `layer_client::Client` (available inside every arm body)
59/// - `update` : the `Update` value to dispatch
60/// - Each arm mirrors a variant of [`crate::update::Update`]
61/// - Guards (`if expr`) are optional
62/// - A catch-all `_ => {}` arm is optional but recommended to avoid warnings
63#[macro_export]
64macro_rules! dispatch {
65    // Entry point: client, update, then one or more arms
66    ($client:expr, $update:expr, $( $pattern:tt )+ ) => {
67        match $update {
68            $crate::__dispatch_arms!($client; $( $pattern )+ )
69        }
70    };
71}
72
73/// Internal helper: do not use directly.
74#[macro_export]
75#[doc(hidden)]
76macro_rules! __dispatch_arms {
77    // Catch-all arm
78    ($client:expr; _ => $body:block $( , $( $rest:tt )* )? ) => {
79        _ => $body
80    };
81
82    // Variant arm WITH guard
83    ($client:expr;
84        $variant:ident ( $binding:pat ) if $guard:expr => $body:block
85        $( , $( $rest:tt )* )?
86    ) => {
87        $crate::update::Update::$variant($binding) if $guard => $body,
88        $( $crate::__dispatch_arms!($client; $( $rest )* ) )?
89    };
90
91    // Variant arm WITHOUT guard
92    ($client:expr;
93        $variant:ident ( $binding:pat ) => $body:block
94        $( , $( $rest:tt )* )?
95    ) => {
96        $crate::update::Update::$variant($binding) => $body,
97        $( $crate::__dispatch_arms!($client; $( $rest )* ) )?
98    };
99
100    // Trailing comma / empty: emit wildcard to ensure exhaustiveness
101    ($client:expr; $(,)?) => {
102        _ => {}
103    };
104}