viz_router/
tree.rs

1use std::fmt::{Debug, Formatter, Result};
2
3use path_tree::{Path, PathTree};
4
5use viz_core::{BoxHandler, Method};
6
7use crate::{Route, Router};
8
9/// Store all final routes.
10#[derive(Clone, Default)]
11pub struct Tree(Vec<(Method, PathTree<BoxHandler>)>);
12
13impl Tree {
14    /// Find a handler by the HTTP method and the URI's path.
15    #[must_use]
16    pub fn find<'a, 'b>(
17        &'a self,
18        method: &'b Method,
19        path: &'b str,
20    ) -> Option<(&'a BoxHandler, Path<'a, 'b>)> {
21        self.0
22            .iter()
23            .find_map(|(m, t)| if m == method { t.find(path) } else { None })
24    }
25
26    /// Consumes the Tree, returning the wrapped value.
27    #[must_use]
28    pub fn into_inner(self) -> Vec<(Method, PathTree<BoxHandler>)> {
29        self.0
30    }
31}
32
33impl AsRef<Vec<(Method, PathTree<BoxHandler>)>> for Tree {
34    fn as_ref(&self) -> &Vec<(Method, PathTree<BoxHandler>)> {
35        &self.0
36    }
37}
38
39impl AsMut<Vec<(Method, PathTree<BoxHandler>)>> for Tree {
40    fn as_mut(&mut self) -> &mut Vec<(Method, PathTree<BoxHandler>)> {
41        &mut self.0
42    }
43}
44
45impl From<Router> for Tree {
46    fn from(router: Router) -> Self {
47        let mut tree = Self::default();
48        if let Some(routes) = router.routes {
49            for (mut path, Route { methods }) in routes {
50                if !path.starts_with('/') {
51                    path.insert(0, '/');
52                }
53                for (method, handler) in methods {
54                    if let Some(t) = tree
55                        .as_mut()
56                        .iter_mut()
57                        .find_map(|(m, t)| if *m == method { Some(t) } else { None })
58                    {
59                        let _ = t.insert(&path, handler);
60                    } else {
61                        let mut t = PathTree::new();
62                        let _ = t.insert(&path, handler);
63                        tree.as_mut().push((method, t));
64                    }
65                }
66            }
67        }
68        tree
69    }
70}
71
72impl Debug for Tree {
73    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
74        self.as_ref()
75            .iter()
76            .fold(f.debug_struct("Tree"), |mut d, (m, t)| {
77                d.field("method", m).field("paths", &t.node);
78                d
79            })
80            .finish()
81    }
82}