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) =
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}