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#[derive(Clone, Default)]
11pub struct Tree(Vec<(Method, PathTree<BoxHandler>)>);
12
13impl Tree {
14 #[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 #[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}