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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use super::Method;
use serde_json::Value;
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;

pub use matchit::{MatchError, Router};

type Handler = Box<
    dyn Fn(
        Vec<(String, String)>,
        String,
        HashMap<String, Value>,
        Vec<u8>,
    ) -> Pin<Box<dyn Future<Output = ()>>>,
>;

/// Helper for wrapping function to a Handler.
/// Then the Handler should be inserted into [Router].
pub fn new_handler<T>(
    f: fn(Vec<(String, String)>, String, HashMap<String, Value>, Vec<u8>) -> T,
) -> Handler
where
    T: Future<Output = ()> + 'static,
{
    Box::new(move |a, b, c, d| Box::pin(f(a, b, c, d)))
}

extern "C" {
    fn get_event_method_length() -> i32;
    fn get_event_method(p: *mut u8) -> i32;
    fn get_event_headers_length() -> i32;
    fn get_event_headers(p: *mut u8) -> i32;
    fn get_event_query_length() -> i32;
    fn get_event_query(p: *mut u8) -> i32;
    fn get_event_subpath_length() -> i32;
    fn get_event_subpath(p: *mut u8) -> i32;
    fn get_event_body_length() -> i32;
    fn get_event_body(p: *mut u8) -> i32;
}

fn get_request() -> (
    Method,
    Vec<(String, String)>,
    String,
    HashMap<String, Value>,
    Vec<u8>,
) {
    unsafe {
        let l = get_event_method_length();
        let mut event_method = Vec::<u8>::with_capacity(l as usize);
        let c = get_event_method(event_method.as_mut_ptr());
        assert!(c == l);
        event_method.set_len(c as usize);
        let event_method = Method::from_bytes(&event_method).unwrap();

        let l = get_event_headers_length();
        let mut event_headers = Vec::<u8>::with_capacity(l as usize);
        let c = get_event_headers(event_headers.as_mut_ptr());
        assert!(c == l);
        event_headers.set_len(c as usize);
        let event_headers = serde_json::from_slice(&event_headers).unwrap();

        let l = get_event_query_length();
        let mut event_query = Vec::<u8>::with_capacity(l as usize);
        let c = get_event_query(event_query.as_mut_ptr());
        assert!(c == l);
        event_query.set_len(c as usize);
        let event_query = serde_json::from_slice(&event_query).unwrap();

        let l = get_event_subpath_length();
        let mut event_subpath = Vec::<u8>::with_capacity(l as usize);
        let c = get_event_subpath(event_subpath.as_mut_ptr());
        assert!(c == l);
        event_subpath.set_len(c as usize);
        let event_subpath = String::from_utf8_lossy(&event_subpath).into_owned();

        let l = get_event_body_length();
        let mut event_body = Vec::<u8>::with_capacity(l as usize);
        let c = get_event_body(event_body.as_mut_ptr());
        assert!(c == l);
        event_body.set_len(c as usize);

        (
            event_method,
            event_headers,
            event_subpath,
            event_query,
            event_body,
        )
    }
}

/// Route path to handler.
/// For calling the exact handler, [construct the router](Router) then pass it to this function.
/// ```rust
/// let mut router = Router::new();
/// router
///     .insert("/options", (vec![Method::OPTIONS], new_handler(options)))
///     .unwrap();
/// router
///     .insert(
///         "/get/:city",
///         (vec![Method::GET], new_handler(handler)),
///     )
///     .unwrap();
/// if let Err(e) = route(router).await {
///     send_response(404, vec![], b"No route matched".to_vec())
/// }
/// ```
pub async fn route(router: Router<(Vec<Method>, Handler)>) -> Result<(), MatchError> {
    let (method, headers, subpath, mut qry, body) = get_request();
    let matched = router.at(subpath.as_str())?;
    for p in matched.params.iter() {
        qry.insert(String::from(p.0), Value::from(p.1));
    }
    let (mv, f) = matched.value;
    for m in mv.iter() {
        if m.eq(&method) {
            f(headers, subpath, qry, body).await;
            return Ok(());
        }
    }

    Err(MatchError::NotFound)
}