Skip to main content

telegram_webapp_sdk/
router.rs

1// SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
2// SPDX-License-Identifier: MIT
3
4//! Simple in-memory page router.
5//!
6//! Collects page definitions and executes their handlers in registration
7//! order. Used by the `telegram_router!` macro by default.
8//!
9//! # Examples
10//!
11//! ```no_run
12//! use telegram_webapp_sdk::router::Router;
13//!
14//! fn index() {}
15//!
16//! Router::new().register("/", index).start();
17//! ```
18
19#[cfg(feature = "macros")]
20use crate::pages::Page;
21#[cfg(not(feature = "macros"))]
22#[derive(Copy, Clone)]
23struct Page {
24    #[allow(dead_code)]
25    path:    &'static str,
26    handler: fn()
27}
28
29/// Sequential router executing registered page handlers.
30#[derive(Default)]
31pub struct Router {
32    pages: Vec<Page>
33}
34
35impl Router {
36    /// Creates an empty router.
37    pub fn new() -> Self {
38        Self::default()
39    }
40
41    /// Adds a page handler associated with `path` and returns the updated
42    /// router.
43    pub fn register(mut self, path: &'static str, handler: fn()) -> Self {
44        self.pages.push(Page {
45            path,
46            handler
47        });
48        self
49    }
50
51    /// Starts the router, invoking handlers in order of registration.
52    pub fn start(self) {
53        for page in self.pages {
54            (page.handler)();
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use std::sync::atomic::{AtomicUsize, Ordering};
62
63    use super::*;
64
65    fn noop() {}
66
67    #[test]
68    fn registers_pages() {
69        let router = Router::new().register("/", noop);
70        assert_eq!(router.pages.len(), 1);
71    }
72
73    static COUNT: AtomicUsize = AtomicUsize::new(0);
74
75    fn handler() {
76        COUNT.fetch_add(1, Ordering::SeqCst);
77    }
78
79    #[test]
80    fn starts_registered_pages() {
81        COUNT.store(0, Ordering::SeqCst);
82        Router::new().register("/", handler).start();
83        assert_eq!(COUNT.load(Ordering::SeqCst), 1);
84    }
85}