thruster_core/route_tree/
mod.rs

1mod node;
2
3use std::collections::HashMap;
4
5pub use self::node::Node;
6use crate::context::Context;
7use thruster_core_async_await::{MiddlewareChain};
8
9pub enum Method {
10  DELETE,
11  GET,
12  OPTIONS,
13  POST,
14  PUT,
15  UPDATE
16}
17
18pub struct RouteTree<T: 'static + Context + Send> {
19  pub root_node: Node<T>,
20  pub generic_root_node: Node<T>,
21  pub specific_root_node: Node<T>
22}
23
24fn method_to_prefix<'a>(method: &Method) -> &'a str {
25  match method {
26    Method::DELETE => "__DELETE__",
27    Method::GET => "__GET__",
28    Method::OPTIONS => "__OPTIONS__",
29    Method::POST => "__POST__",
30    Method::PUT => "__PUT__",
31    Method::UPDATE => "__UPDATE__"
32  }
33}
34
35impl<T: 'static + Context + Send> RouteTree<T> {
36  pub fn new() -> RouteTree<T> {
37    RouteTree {
38      root_node: Node::new(""),
39      generic_root_node: Node::new(""),
40      specific_root_node: Node::new("")
41    }
42  }
43
44  ///
45  /// Updates the `root_node` of the tree by merging the generic tree into the specific tree. This
46  /// is necessary after adding any routes to ensure that the matching functions of the tree are
47  /// up to date.
48  ///
49  pub fn update_root_node(&mut self) {
50    let mut root_node = self.specific_root_node.clone();
51
52    root_node.push_middleware_to_populated_nodes(&self.generic_root_node, &MiddlewareChain::new());
53
54    self.root_node = root_node;
55  }
56
57  pub fn add_use_node(&mut self, route: &str, middleware: MiddlewareChain<T>) {
58    self.generic_root_node.add_route(route, middleware);
59    self.update_root_node();
60  }
61
62  pub fn add_route_with_method(&mut self, method: &Method, route: &str, middleware: MiddlewareChain<T>) {
63    let prefix = method_to_prefix(&method);
64
65    let full_route = format!("{}{}", prefix, route);
66
67    self.specific_root_node.add_route(&full_route, middleware);
68    self.update_root_node();
69  }
70
71  pub fn add_route(&mut self, route: &str, middleware: MiddlewareChain<T>) {
72    self.specific_root_node.add_route(route, middleware);
73    self.update_root_node();
74  }
75
76  fn _adopt_sub_app_method_to_self(&mut self, route: &str, mut route_tree: RouteTree<T>, method: &Method) -> RouteTree<T> {
77    let method_prefix = method_to_prefix(&method);
78
79    let mut self_routes = self.specific_root_node.children.remove(method_prefix)
80      .unwrap_or_else(|| Node::new(method_prefix));
81
82    if let Some(tree_routes) = route_tree.root_node.children.remove(method_prefix) {
83      self_routes.add_subtree(route, tree_routes);
84    }
85
86    self.specific_root_node.children.insert(method_prefix.to_owned(), self_routes);
87
88    // Return ownership
89    route_tree
90  }
91
92  pub fn add_route_tree(&mut self, route: &str, mut route_tree: RouteTree<T>) {
93    route_tree = self._adopt_sub_app_method_to_self(route, route_tree, &Method::DELETE);
94    route_tree = self._adopt_sub_app_method_to_self(route, route_tree, &Method::GET);
95    route_tree = self._adopt_sub_app_method_to_self(route, route_tree, &Method::OPTIONS);
96    route_tree = self._adopt_sub_app_method_to_self(route, route_tree, &Method::POST);
97    route_tree = self._adopt_sub_app_method_to_self(route, route_tree, &Method::PUT);
98    self._adopt_sub_app_method_to_self(route, route_tree, &Method::UPDATE);
99    self.update_root_node();
100  }
101
102  pub fn match_route(&self, route: &str) -> (HashMap<String, String>, &MiddlewareChain<T>) {
103    let results = self.root_node.match_route(route.split('/'));
104
105    (results.0, results.2)
106  }
107
108  pub fn match_route_with_params(&self, route: &str, params: HashMap<String, String>) -> (HashMap<String, String>, &MiddlewareChain<T>) {
109    let results = self.root_node.match_route_with_params(route.split('/'), params);
110
111    (results.0, results.2)
112  }
113}
114
115impl<T: 'static + Context + Send> Default for RouteTree<T> {
116  fn default() -> RouteTree<T> {
117    RouteTree::new()
118  }
119}