1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use crate::router::{Captures, Router, RouterError};

use std::collections::HashMap;

pub use http::Method;

#[derive(Debug, Default)]
pub struct HttpRouter<T> {
    method_map: HashMap<Method, Router<T>>,
}

impl<T> HttpRouter<T> {
    pub fn new() -> Self {
        Self {
            method_map: HashMap::new(),
        }
    }

    pub fn find<'p, 's: 'p>(
        &'s self,
        method: &Method,
        path: &'p str,
    ) -> Option<(&'s T, Captures<'p>)> {
        self.method_map.get(method)?.find(path)
    }

    pub fn find_mut<'p, 's: 'p>(
        &'s mut self,
        method: &Method,
        path: &'p str,
    ) -> Option<(&'s mut T, Captures<'p>)> {
        self.method_map.get_mut(method)?.find_mut(path)
    }

    pub fn insert(&mut self, method: Method, pattern: &str, data: T) -> &mut Self {
        self.access_router(method).insert(pattern, data);
        self
    }

    pub fn try_insert(
        &mut self,
        method: Method,
        pattern: &str,
        data: T,
    ) -> Result<&mut Self, RouterError> {
        self.access_router(method).try_insert(pattern, data)?;
        Ok(self)
    }

    pub fn nest(&mut self, prefix: &str, f: impl FnOnce(&mut HttpRouter<T>)) -> &mut Self {
        let mut sub_router = Self::new();
        f(&mut sub_router);
        self.insert_router(prefix, sub_router);
        self
    }

    pub fn try_nest(
        &mut self,
        prefix: &str,
        f: impl FnOnce(&mut HttpRouter<T>),
    ) -> Result<&mut Self, RouterError> {
        let mut sub_router = Self::new();
        f(&mut sub_router);
        self.try_insert_router(prefix, sub_router)?;
        Ok(self)
    }

    pub fn insert_router(&mut self, prefix: &str, router: HttpRouter<T>) {
        for (method, router) in router.method_map {
            self.access_router(method).insert_router(prefix, router);
        }
    }

    pub fn try_insert_router(
        &mut self,
        prefix: &str,
        router: HttpRouter<T>,
    ) -> Result<&mut Self, RouterError> {
        for (method, router) in router.method_map {
            self.access_router(method)
                .try_insert_router(prefix, router)?;
        }
        Ok(self)
    }
}

impl<T> HttpRouter<T> {
    fn access_router(&mut self, method: Method) -> &mut Router<T> {
        self.method_map.entry(method).or_insert_with(Router::new)
    }
}