1use std::any::type_name;
2use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3use std::fmt::Debug;
4use crate::api::{ApiTrait, EventHandler};
5use dce_util::mixed::{DceErr, DceResult};
6use dce_util::atom_tree::ATree;
7use dce_util::atom_tree::{KeyFactory, TreeTraverBreak};
8use std::sync::{Arc, RwLockReadGuard};
9use log::debug;
10use crate::protocol::RoutableProtocol;
11use crate::request::{PathParam, Context};
12
13pub const PATH_PART_SEPARATOR: char = '/';
14pub const SUFFIX_BOUNDARY: char = '.';
15const VARIABLE_OPENER: char = '{';
16const VARIABLE_CLOSING: char = '}';
17const VAR_TYPE_OPTIONAL: char = '?';
18const VAR_TYPE_EMPTABLE_VECTOR: char = '*';
19const VAR_TYPE_VECTOR: char = '+';
20
21pub const CODE_NOT_FOUND: isize = 404;
22
23#[derive(Debug)]
24pub struct Router<Rp: RoutableProtocol + 'static> {
25 path_part_separator: char,
26 suffix_boundary: char,
27 api_buffer: Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
28 raw_omitted_paths: HashSet<&'static str>,
29 id_api_mapping: HashMap<&'static str, &'static (dyn ApiTrait<Rp> + Send + Sync)>,
30 apis_mapping: HashMap<&'static str, Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>>,
32 apis_tree: Arc<ATree<ApiBranch<Rp>, &'static str>>,
33 before_controller: Option<EventHandler<Rp>>,
34 after_controller: Option<EventHandler<Rp>>,
35}
36
37impl<Rp: RoutableProtocol + Debug + 'static> Router<Rp> {
38 pub fn new() -> DceResult<Self> {
39 Ok(Self {
40 path_part_separator: PATH_PART_SEPARATOR,
41 suffix_boundary: SUFFIX_BOUNDARY,
42 api_buffer: vec![],
43 raw_omitted_paths: Default::default(),
44 id_api_mapping: Default::default(),
45 apis_mapping: Default::default(),
46 apis_tree: ATree::new(ApiBranch::new("", vec![]))?,
47 before_controller: None,
48 after_controller: None,
49 })
50 }
51
52 pub fn set_separator(mut self, path_part_separator: char , suffix_separator: char) -> Self {
53 self.path_part_separator = path_part_separator;
54 self.suffix_boundary = suffix_separator;
55 self
56 }
57
58 pub fn suffix_boundary(&self) -> char {
59 self.suffix_boundary
60 }
61
62 pub fn apis_tree(&self) -> &Arc<ATree<ApiBranch<Rp>, &'static str>> {
63 &self.apis_tree
64 }
65
66 pub fn before_controller(&self) -> &Option<EventHandler<Rp>> {
67 &self.before_controller
68 }
69
70 pub fn after_controller(&self) -> &Option<EventHandler<Rp>> {
71 &self.after_controller
72 }
73
74 pub fn set_event_handlers(mut self, before_controller: Option<EventHandler<Rp>>, after_controller: Option<EventHandler<Rp>>) -> Self {
75 self.before_controller = before_controller;
76 self.after_controller = after_controller;
77 self
78 }
79
80 pub fn push(mut self, supplier: fn() -> &'static (dyn ApiTrait<Rp> + Send + Sync)) -> Self {
81 let api = supplier();
82 if api.omission() {
83 self.raw_omitted_paths.insert(api.path());
84 }
85 if ! api.id().is_empty() {
86 self.id_api_mapping.insert(api.id(), api);
87 }
88 self.api_buffer.push(api);
89 self
90 }
91
92 pub fn consumer_push(self, consumer: fn(Self) -> Self) -> Self {
93 consumer(self)
94 }
95
96 fn omitted_path(&self, path: &'static str) -> String {
97 let parts = path.split(PATH_PART_SEPARATOR).collect::<Vec<_>>();
98 parts.iter().enumerate()
99 .filter(|(i, _)| ! self.raw_omitted_paths.contains(parts[0..=*i].join(PATH_PART_SEPARATOR.to_string().as_str()).as_str()))
101 .map(|t| t.1.to_string())
102 .collect::<Vec<_>>()
103 .join(PATH_PART_SEPARATOR.to_string().as_str())
104 }
105
106 fn closing(&mut self) -> DceResult<()> {
107 self.build_tree()?;
108 while let Some(api) = self.api_buffer.pop() {
109 let path = self.omitted_path(api.path());
110 let mut apis = vec![api];
111 let mut suffixes = api.suffixes().clone();
112 for index in (0..self.api_buffer.len()).rev() {
113 if path.eq_ignore_ascii_case(self.omitted_path(&self.api_buffer[index].path()).as_str()) {
114 let sibling_api = self.api_buffer.remove(index);
116 suffixes.extend(sibling_api.suffixes().clone());
117 apis.insert(0, sibling_api);
118 }
119 }
120 for suffix in suffixes {
122 let suffixed_path = self.suffix_path(&path, &*suffix);
123 self.apis_mapping.insert(Box::leak(suffixed_path.into_boxed_str()), apis.iter()
124 .filter(|api| api.suffixes().contains(&suffix))
125 .map(|api| *api)
126 .collect::<Vec<_>>());
127 }
128 }
129 Ok(())
130 }
131
132 fn suffix_path(&self, path: &String, suffix: &str) -> String {
133 format!("{}{}", path, if suffix.is_empty() { "".to_owned() } else { format!("{}{}", SUFFIX_BOUNDARY, suffix) })
134 }
135
136 fn build_tree(&mut self) -> DceResult<()> {
137 let suffix_less_apis_groups: Vec<Vec<_>> = self.api_buffer.iter().map(|a| a.path()).collect::<HashSet<_>>()
138 .iter().map(|path| self.api_buffer.iter().filter_map(|api| if api.path().eq(*path) { Some(*api) } else { None }).collect()).collect();
139 self.apis_tree.build(
141 suffix_less_apis_groups.iter().map(|apis| ApiBranch::new(apis[0].path(), apis.clone())).collect::<Vec<_>>(),
142 Some(|tree: &ATree<ApiBranch<Rp>, &'static str>, mut remains: Vec<ApiBranch<Rp>>| {
146 let mut fills: BTreeMap<Vec<&'static str>, ApiBranch<Rp>> = BTreeMap::new();
147 while let Some(element) = remains.pop() {
148 let paths: Vec<_> = element.path.split(PATH_PART_SEPARATOR).collect();
149 for i in 0..paths.len() - 1 {
150 let path = paths[..=i].to_vec();
151 if matches!(tree.get_by_path(&path), None) && ! fills.contains_key(&path) {
152 let api_path = ApiBranch::new(Box::leak(path.clone().join(PATH_PART_SEPARATOR.to_string().as_str()).into_boxed_str()), vec![]);
154 fills.insert(path, api_path);
155 }
156 }
157 fills.insert(paths, element);
159 }
160 while let Some((paths, nb)) = fills.pop_first() {
161 let _ = tree.set_by_path(paths, nb);
162 }
163 }),
164 )?;
165 self.apis_tree.traversal(|tree| {
167 let is_var_elem = ! matches!(tree.read().map_err(DceErr::closed0)?.var_type, VarType::NotVar);
168 let mut current = tree.clone();
169 let mut is_omitted_passed_child = false;
170 while let Some(parent) = current.parent() {
171 if ! parent.read().map_err(DceErr::closed0)?.is_omission {
172 let mut parent_writable = parent.write().map_err(DceErr::closed0)?;
173 match parent_writable.var_type {
174 VarType::Required(_) => parent_writable.is_mid_var = true,
175 VarType::NotVar => {},
176 _ => panic!("Ambiguous type var '{}' cannot in middle.", parent_writable.key()),
177 }
178 if is_var_elem {
180 parent_writable.var_children.push(tree.clone());
181 } else if is_omitted_passed_child {
182 parent_writable.omitted_passed_children.insert(tree.read().map_err(DceErr::closed0)?.key(), tree.clone());
183 }
184 break;
185 }
186 is_omitted_passed_child = true;
187 current = parent;
188 }
189 Ok(TreeTraverBreak::Continue)
190 })
191 }
192
193 pub fn ready(mut self) -> DceResult<&'static Arc<Router<Rp>>> {
194 self.closing()?;
195 Ok(Box::leak(Box::new(Arc::new(self))))
196 }
197
198 fn locate(
199 &self,
200 mut path: &str,
201 api_finder: impl Fn(&Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>) -> DceResult<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
202 ) -> DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)> {
203 let request_path = path;
204 let mut api;
205 let mut path_args = Default::default();
206 let mut suffix = None;
207 loop {
209 let mut apis = self.apis_mapping.get(path);
210 if let Some((tmp_path, tmp_path_args, tmp_suffix)) = if apis.is_some() { None } else { self.match_var_path(path) } {
211 apis = self.apis_mapping.get(self.suffix_path(&self.omitted_path(tmp_path), tmp_suffix).as_str());
214 (path_args, suffix) = (tmp_path_args, Some(tmp_suffix));
215 }
216 api = api_finder(apis.ok_or_else(|| DceErr::openly(CODE_NOT_FOUND, format!(r#"path "{}" route failed, could not matched by Router"#, path)))?)?;
217 if api.redirect().is_empty() {
218 break;
219 }
220 path = api.redirect();
221 }
222 debug!(r#"{}: path "{}" matched api "{}""#, type_name::<Rp>(), request_path, api.path());
223 Ok((api, path_args, suffix))
224 }
225
226 fn match_var_path(
227 &self,
228 path: &str,
229 ) -> Option<(&'static str, HashMap<&'static str, PathParam>, &'static str)> {
230 let path_parts = path.split(self.path_part_separator).collect::<Vec<_>>();
231 let mut loop_items = vec![(self.apis_tree.clone(), 0_usize)];
232 let mut target_api_branch = None;
233 let mut suffix = "";
234 let mut path_args = HashMap::new();
235 'outer: while let Some((api_branch, part_number)) = loop_items.pop() {
236 let is_last_part = part_number == path_parts.len() - 1;
237 let is_overflowed = part_number >= path_parts.len();
238 if is_overflowed && ! api_branch.read().ok()?.apis.is_empty() {
239 target_api_branch = Some(api_branch.clone());
241 break;
242 }
243 if let Some((sub_api_branch, matched_suffix)) = if is_overflowed { None } else {
245 self.find_consider_suffix(&path_parts[part_number], is_last_part, api_branch.children().read().ok()?, &api_branch.read().ok()?.omitted_passed_children)
246 } {
247 loop_items.push((sub_api_branch.clone(), 1 + part_number));
249 suffix = matched_suffix;
250 } else {
251 let insert_pos = loop_items.len();
252 for var_api_branch in api_branch.read().ok()?.var_children.clone() {
253 let var_api_branch_read = var_api_branch.read().ok()?;
254 if ! var_api_branch_read.is_mid_var {
255 let mut suffix_extractor = |path_parts: Vec<&str>, consumer: &mut dyn FnMut(Vec<&str>) -> Option<PathParam>| -> Option<PathParam> {
258 let mut path_parts = path_parts.clone();
259 if let Some(mut last_part) = path_parts.pop() {
260 if let Some(tmp_suffix) = var_api_branch_read.apis.iter().flat_map(|api| api.suffixes()).collect::<BTreeSet<_>>()
263 .iter().find(|suf| last_part.ends_with(format!("{}{}", self.suffix_boundary, &****suf).as_str())) {
264 last_part = &last_part[0..last_part.len() - tmp_suffix.len() - 1];
265 suffix = &**tmp_suffix;
266 }
267 path_parts.push(last_part);
268 }
269 consumer(path_parts)
270 };
271 match var_api_branch_read.var_type {
273 VarType::Optional(var_name) if is_overflowed => path_args.insert(var_name, PathParam::Option(None)),
275 VarType::Optional(var_name) if is_last_part =>
277 suffix_extractor(path_parts, &mut |pps| path_args.insert(var_name, PathParam::Option(Some(pps[part_number].to_string())))),
278 VarType::Required(var_name) if is_last_part =>
279 suffix_extractor(path_parts, &mut |pps| path_args.insert(var_name, PathParam::Required(pps[part_number].to_string()))),
280 VarType::EmptableVector(var_name) if is_overflowed => path_args.insert(var_name, PathParam::Vector(vec![])),
281 VarType::EmptableVector(var_name) | VarType::Vector(var_name) if !is_overflowed =>
283 suffix_extractor(path_parts, &mut |pps| path_args.insert(var_name, PathParam::Vector(pps[part_number..].iter().map(|p| p.to_string()).collect::<Vec<_>>()))),
284 _ => continue,
286 };
287 target_api_branch = Some(var_api_branch.clone());
288 break 'outer;
289 } else if let VarType::Required(var_name) = var_api_branch_read.var_type {
290 path_args.insert(var_name, PathParam::Required(path_parts[part_number].to_string()));
292 loop_items.insert(insert_pos, (var_api_branch.clone(), 1 + part_number));
293 }
294 }
295 }
296 }
297 target_api_branch?.read().map(|branch| (branch.path, path_args, suffix)).ok()
298 }
299
300 fn find_consider_suffix(
301 &self,
302 part: &str,
303 is_last_part: bool,
304 children: RwLockReadGuard<BTreeMap<&'static str, Arc<ATree<ApiBranch<Rp>, &'static str>>>>,
305 omitted_passed_children: &BTreeMap<&'static str, Arc<ATree<ApiBranch<Rp>, &'static str>>>,
306 ) -> Option<(Arc<ATree<ApiBranch<Rp>, &'static str>>, &'static str)> {
307 let matches = children.get(part).or_else(|| omitted_passed_children.get(part));
308 if matches.is_none() && is_last_part {
309 let mut boundary = part.len();
310 while let Some(previous) = part[0..boundary].rfind(self.suffix_boundary) {
311 let matches = children.get(&part[0..previous]).or_else(|| omitted_passed_children.get(&part[0..previous]));
313 if let Some(matches) = matches {
314 return matches.read().ok()?.apis.iter()
315 .flat_map(|api| api.suffixes())
316 .find(|suffix| part[previous + 1 ..].eq(&***suffix))
317 .map(|suffix| (matches.clone(), &**suffix));
318 }
319 boundary = previous;
320 }
321 }
322 return matches.map(|tree| (tree.clone(), ""));
324 }
325
326 #[cfg(feature = "async")]
327 async fn routed_handle(result: DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)>, context: &mut Context<Rp>) -> DceResult<()> {
328 let (api, path_args, suffix) = result?;
329 context.set_routed_info(api, path_args, suffix);
330 api.call_controller(context).await
331 }
332
333 #[cfg(not(feature = "async"))]
334 fn routed_handle(result: DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)>, context: &mut Context<Rp>) -> DceResult<()> {
335 let (api, path_args, suffix) = result?;
336 context.set_routed_info(api, path_args, suffix);
337 api.call_controller(context)
338 }
339
340 #[cfg(feature = "async")]
341 pub async fn route(context: &mut Context<Rp>) -> DceResult<()> {
342 Self::routed_handle(context.router().locate(context.rp().path(), |apis| context.rp().api_match(apis)), context).await
343 }
344
345 #[cfg(not(feature = "async"))]
346 pub fn route(context: &mut Context<Rp>) -> DceResult<()> {
347 Self::routed_handle(context.router().locate(context.rp().path(), |apis| context.rp().api_match(apis)), context)
348 }
349
350 fn id_locate(&self, id: &str) -> DceResult<(&'static (dyn ApiTrait<Rp> + Send + Sync), HashMap<&'static str, PathParam>, Option<&'static str>)> {
351 self.id_api_mapping.get(id).map_or_else(
352 || Err(DceErr::openly(CODE_NOT_FOUND, format!(r#"id "{}" route failed, could not matched by Router"#, id))),
353 |api| {
354 debug!(r#"{}: id "{}" matched api "{}""#, type_name::<Rp>(), id, api.path());
355 Ok((*api, Default::default(), None))
356 })
357 }
358
359 #[cfg(feature = "async")]
360 pub async fn id_route(context: &mut Context<Rp>) -> DceResult<()> {
361 Self::routed_handle(context.router().id_locate(context.rp().path()), context).await
362 }
363
364 #[cfg(not(feature = "async"))]
365 pub fn id_route(context: &mut Context<Rp>) -> DceResult<()> {
366 Self::routed_handle(context.router().id_locate(context.rp().path()), context)
367 }
368}
369
370#[derive(PartialEq, Debug, Clone)]
371enum VarType {
372 Required(&'static str),
373 Optional(&'static str),
374 EmptableVector(&'static str),
375 Vector(&'static str),
376 NotVar,
377}
378
379#[derive(Debug)]
380pub struct ApiBranch<Rp: RoutableProtocol + 'static> {
381 path: &'static str,
382 var_type: VarType,
383 is_mid_var: bool,
384 is_omission: bool,
385 apis: Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>,
386 var_children: Vec<Arc<ATree<ApiBranch<Rp>, &'static str>>>,
387 omitted_passed_children: BTreeMap<&'static str, Arc<ATree<ApiBranch<Rp>, &'static str>>>,
388}
389
390impl<Rp: RoutableProtocol> ApiBranch<Rp> {
391 fn new(path: &'static str, apis: Vec<&'static (dyn ApiTrait<Rp> + Send + Sync)>) -> ApiBranch<Rp> {
392 ApiBranch {
393 path,
394 var_type: VarType::NotVar,
395 is_mid_var: false,
396 is_omission: apis.iter().any(|api| api.omission()),
397 apis,
398 var_children: Default::default(),
399 omitted_passed_children: Default::default(),
400 }.fill_var_type()
401 }
402
403 fn fill_var_type(mut self) -> ApiBranch<Rp> {
404 let key = self.key();
405 if key.starts_with(VARIABLE_OPENER) && key.ends_with(VARIABLE_CLOSING) {
406 if self.is_omission {
407 panic!("Var path could not be omissible.");
408 }
409 let var = key[1..key.len() - 1].trim();
410 self.var_type = match var.chars().last() {
411 Some(VAR_TYPE_OPTIONAL) => VarType::Optional(var[0..var.len() - 1].trim_end()),
412 Some(VAR_TYPE_EMPTABLE_VECTOR) => VarType::EmptableVector(var[0..var.len() - 1].trim_end()),
413 Some(VAR_TYPE_VECTOR) => VarType::Vector(var[0..var.len() - 1].trim_end()),
414 _ => VarType::Required(var),
415 }
416 }
417 self
418 }
419}
420
421impl<Rp: RoutableProtocol> KeyFactory<&'static str> for ApiBranch<Rp> {
422 fn key(&self) -> &'static str {
423 self.path.rfind(PATH_PART_SEPARATOR).map_or_else(|| self.path.trim(), |index| &self.path[index+1 ..].trim())
424 }
425
426 fn child_of(&self, parent: &Self) -> bool {
427 self.path.rfind(PATH_PART_SEPARATOR).map_or_else(|| parent.path.is_empty(), |index| &self.path[..index] == parent.path)
428 }
429}
430
431impl<Rp: RoutableProtocol> PartialEq for ApiBranch<Rp> {
432 fn eq(&self, other: &Self) -> bool {
433 self.path == other.path
434 }
435}