thruster_core/route_tree/
node.rs1use std::collections::HashMap;
2use smallvec::SmallVec;
3use std::str::Split;
4
5
6use crate::context::Context;
7use thruster_core_async_await::{MiddlewareChain};
8
9type RouteNodeWithParams<'a, T> = (HashMap<String, String>, bool, &'a MiddlewareChain<T>);
11type RouteNodeEnumeration<T> = SmallVec<[(String, MiddlewareChain<T>, bool); 8]>;
12
13pub struct Node<T: 'static + Context + Send> {
14 runnable: MiddlewareChain<T>,
15 pub children: HashMap<String, Node<T>>,
16 wildcard_node: Option<Box<Node<T>>>,
17 param_key: Option<String>,
18 pub value: String,
19 pub is_wildcard: bool,
20 pub is_terminal_node: bool
21}
22
23impl<T: Context + Send> Clone for Node<T> {
24 fn clone(&self) -> Self {
25 let runnable = self.runnable.clone();
26 let children = self.children.clone();
27
28 let wildcard = if self.is_wildcard {
29 None
30 } else {
31 Some(Box::new(match &self.wildcard_node {
32 Some(wildcard) => (**wildcard).clone(),
33 None => Node::new_wildcard(None)
34 }))
35 };
36
37 Node {
38 runnable,
39 children,
40 wildcard_node: wildcard,
41 value: self.value.clone(),
42 param_key: self.param_key.clone(),
43 is_wildcard: self.is_wildcard,
44 is_terminal_node: self.is_terminal_node
45 }
46 }
47}
48
49impl<T: 'static + Context + Send> Node<T> {
50
51 pub fn new(value: &str) -> Node<T> {
52 Node {
53 runnable: MiddlewareChain::new(),
54 children: HashMap::new(),
55 wildcard_node: Some(Box::new(Node::new_wildcard(None))),
56 value: value.to_owned(),
57 param_key: None,
58 is_wildcard: false,
59 is_terminal_node: false
60 }
61 }
62
63 pub fn new_wildcard(param_name: Option<String>) -> Node<T> {
64 Node {
65 runnable: MiddlewareChain::new(),
66 children: HashMap::new(),
67 wildcard_node: None,
68 value: "*".to_owned(),
69 param_key: param_name,
70 is_wildcard: true,
71 is_terminal_node: false
72 }
73 }
74
75 pub fn add_route(&mut self, route: &str, middleware: MiddlewareChain<T>) {
76 let mut split_iterator = match route.chars().next() {
78 Some('/') => &route[1..],
79 _ => route
80 }.split('/');
81
82 if let Some(piece) = split_iterator.next() {
83 if piece.is_empty() {
84 self.is_terminal_node = true;
85 self.runnable = middleware;
86 } else {
87 match piece.chars().next().unwrap() {
88 ':' => {
89 if !self.is_wildcard {
90 let mut wildcard = Node::new_wildcard(Some(piece[1..].to_owned()));
91 wildcard.is_terminal_node = false;
92
93 wildcard.add_route(&split_iterator.collect::<SmallVec<[&str; 8]>>().join("/"), middleware);
94
95 self.wildcard_node = Some(Box::new(wildcard));
96 }
97 },
98 '*' => {
99 if !self.is_wildcard {
100 let mut wildcard = Node::new_wildcard(None);
101 wildcard.is_terminal_node = true;
102
103 wildcard.add_route(&split_iterator.collect::<SmallVec<[&str; 8]>>().join("/"), middleware);
104
105 self.wildcard_node = Some(Box::new(wildcard));
106 }
107 },
108 _ => {
109 let mut child = self.children.remove(piece)
110 .unwrap_or_else(|| Node::new(piece));
111
112 child.add_route(&split_iterator.collect::<SmallVec<[&str; 8]>>().join("/"), middleware);
113
114 self.children.insert(piece.to_owned(), child);
115 }
116 };
117 }
118 }
119 }
120
121 pub fn add_subtree(&mut self, route: &str, mut subtree: Node<T>) {
122 let mut split_iterator = match route.chars().next() {
124 Some('/') => &route[1..],
125 _ => route
126 }.split('/');
127
128 if let Some(piece) = split_iterator.next() {
129 if piece.is_empty() {
130 if let Some(wildcard_node) = &subtree.wildcard_node {
131 if wildcard_node.param_key.is_some() {
132 if let Some(ref mut existing_wildcard) = self.wildcard_node {
133 for (key, child) in subtree.children.drain() {
134 existing_wildcard.children.insert(key, child);
135 }
136
137 existing_wildcard.param_key = wildcard_node.param_key.clone();
138 existing_wildcard.is_terminal_node = existing_wildcard.is_terminal_node || wildcard_node.is_terminal_node;
139 }
140 } else {
141 for (key, child) in subtree.children.drain() {
142 self.children.insert(key, child);
143 }
144 }
145 }
146
147 self.wildcard_node = subtree.wildcard_node;
148 self.is_terminal_node = subtree.is_terminal_node;
149 } else {
150 let mut child = self.children.remove(piece)
151 .unwrap_or_else(|| Node::new(piece));
152
153 if subtree.runnable.is_assigned() {
154 subtree.runnable.chain(child.runnable.clone());
155 child.runnable = subtree.runnable.clone();
156 }
157
158 child.add_subtree(&split_iterator.collect::<SmallVec<[&str; 8]>>().join("/"), subtree);
159
160 self.children.insert(piece.to_owned(), child);
161 }
162 }
163 }
164
165 pub fn match_route(&self, route: Split<char>) -> RouteNodeWithParams<T> {
166 self.match_route_with_params(route, HashMap::new())
167 }
168
169 pub fn match_route_with_params(&self, mut route: Split<char>, mut params: HashMap<String, String>) -> RouteNodeWithParams<T> {
170 if let Some(piece) = route.next() {
171 match self.children.get(piece) {
172 Some(child) => {
173 let results = child.match_route_with_params(route, params);
174
175 if results.1 {
176 results
177 } else {
178 match &self.wildcard_node {
179 Some(wildcard_node) => (results.0, wildcard_node.is_terminal_node, &wildcard_node.runnable),
180 None => {
181 if !self.is_wildcard {
182 results
183 } else {
184 (results.0, self.is_terminal_node, &self.runnable)
185 }
186 }
187 }
188 }
190 },
191 None => {
192 match &self.wildcard_node {
193 Some(wildcard_node) => {
194 if piece.is_empty() && wildcard_node.param_key.is_some() {
199 (params, false, &wildcard_node.runnable)
200 } else if piece.is_empty() && wildcard_node.param_key.is_none() {
201 (params, wildcard_node.is_terminal_node, &wildcard_node.runnable)
202 } else {
203 if let Some(param_key) = &wildcard_node.param_key {
204 params.insert(param_key.to_owned(), piece.to_owned());
205 }
206
207 let results = wildcard_node.match_route_with_params(route, params);
208
209 if results.1 {
212 results
213 } else {
214 (results.0, wildcard_node.is_terminal_node, &self.runnable)
215 }
216 }
217 }
218 None => (params, self.is_terminal_node, &self.runnable)
219 }
220 }
221 }
222 } else if self.is_terminal_node {
223 (params, self.is_terminal_node, &self.runnable)
224 } else if let Some(wildcard_node) = &self.wildcard_node {
225 if wildcard_node.param_key == None {
226 let results = wildcard_node.match_route_with_params(route, params);
227
228 if results.1 {
231 results
232 } else {
233 (results.0, self.is_terminal_node, &self.runnable)
234 }
235 } else {
236 (params, self.is_terminal_node, &self.runnable)
237 }
238 } else {
239 (params, self.is_terminal_node, &self.runnable)
240 }
241 }
242
243 pub fn tree_string(&self, indent: &str) -> String {
255 let mut in_progress = "".to_owned();
256 let value = match self.param_key.clone() {
257 Some(key) => format!(":{}", key),
258 None => self.value.to_owned()
259 };
260
261 in_progress = format!("{}\n{}{}: {}, {}",
262 in_progress,
263 indent,
264 value,
265 self.runnable.is_assigned(),
266 self.is_terminal_node);
267
268 for child in self.children.values() {
269 in_progress = format!("{}{}", in_progress, child.tree_string(&format!("{} ", indent)));
270 }
271
272 if let Some(wildcard_node) = &self.wildcard_node {
273 in_progress = format!("{}{}", in_progress, wildcard_node.tree_string(&format!("{} ", indent)));
274 }
275
276 in_progress
277 }
278
279 pub fn get_route_list(&self) -> RouteNodeEnumeration<T> {
280 let mut routes = SmallVec::new();
281
282 let self_route = &self.value;
283
284 for child in self.children.values() {
286 if child.is_terminal_node {
287 routes.push((
288 format!("{}/{}", self_route, child.value),
289 child.runnable.clone(),
290 child.is_terminal_node
291 ));
292 }
293
294 for child_route in child.get_route_list() {
295 routes.push((
296 format!("{}/{}", self_route, child_route.0),
297 child_route.1.clone(),
298 child_route.2
299 ));
300 }
301 }
302
303 if let Some(ref wildcard_node) = self.wildcard_node {
304 let piece = match wildcard_node.param_key {
305 Some(ref param_key) => format!(":{}", param_key),
306 None => wildcard_node.value.clone()
307 };
308
309 routes.push((
310 format!("{}/{}", self_route, piece),
311 wildcard_node.runnable.clone(),
312 wildcard_node.is_terminal_node
313 ));
314 }
315
316 routes
317 }
318
319 pub fn push_middleware_to_populated_nodes(&mut self, other_node: &Node<T>, accumulated_middleware: &MiddlewareChain<T>) {
324 let fake_node = Node::new("");
325
326 let accumulating_chain = if other_node.runnable.is_assigned() {
327 let mut accumulating_chain = other_node.runnable.clone();
328 accumulating_chain.chain(accumulated_middleware.clone());
329 accumulating_chain
330 } else {
331 accumulated_middleware.clone()
332 };
333
334 if self.runnable.is_assigned() {
335 let mut other = other_node.runnable.clone();
336 let mut other_2 = other.clone();
337 let mut accumulating_chain = accumulated_middleware.clone();
338 let old = self.runnable.clone();
339
340 other_2.chain(old);
341 accumulating_chain.chain(other_2);
342 other.chain(accumulating_chain);
343
344 self.runnable = other;
345 }
346
347 for (key, child) in &mut self.children {
349 let other_child = other_node.children.get(key).unwrap_or(&fake_node);
351
352 child.push_middleware_to_populated_nodes(other_child, &accumulating_chain.clone());
353 }
354
355 if let Some(ref mut wildcard_node) = self.wildcard_node {
357 if let Some(other_wildcard_node) = &other_node.wildcard_node {
358 wildcard_node.push_middleware_to_populated_nodes(other_wildcard_node, &accumulating_chain);
359 }
360 }
361 }
362}