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) =
55                        tree.as_mut().iter_mut().find_map(
56                            |(m, t)| {
57                                if *m == method {
58                                    Some(t)
59                                } else {
60                                    None
61                                }
62                            },
63                        )
64                    {
65                        let _ = t.insert(&path, handler);
66                    } else {
67                        let mut t = PathTree::new();
68                        let _ = t.insert(&path, handler);
69                        tree.as_mut().push((method, t));
70                    }
71                }
72            }
73        }
74        tree
75    }
76}
77
78impl Debug for Tree {
79    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
80        self.as_ref()
81            .iter()
82            .fold(f.debug_struct("Tree"), |mut d, (m, t)| {
83                d.field("method", m).field("paths", &t.node);
84                d
85            })
86            .finish()
87    }
88}