1use crate::protocol::fusen::{request::Path, service::MethodInfo};
2use async_recursion::async_recursion;
3use std::{collections::HashMap, sync::Arc};
4use tokio::sync::RwLock;
5
6#[derive(Debug, Default)]
7pub struct PathCache {
8 path_cache: HashMap<String, Arc<MethodInfo>>,
9 rest_trie: Trie,
10}
11
12impl PathCache {
13 pub async fn seach(&self, path: &Path) -> Option<QueryResult> {
14 let key = format!("{}:{}", path.method, path.path);
15 if let Some(method_info) = self.path_cache.get(key.as_str()) {
16 Some(QueryResult {
17 method_info: method_info.clone(),
18 rest_fields: None,
19 })
20 } else {
21 self.rest_trie.search(key.as_str()).await
22 }
23 }
24 pub async fn build(method_infos: Vec<Arc<MethodInfo>>) -> Self {
25 let mut rest_trie = Trie::default();
26 let mut path_cache = HashMap::new();
27 for method_info in method_infos {
28 rest_trie.insert(method_info.clone()).await;
29 let _ = path_cache.insert(
30 format!("{}:{}", method_info.method, method_info.path),
31 method_info,
32 );
33 }
34 Self {
35 path_cache,
36 rest_trie,
37 }
38 }
39}
40
41#[derive(Debug, Default)]
42pub struct Trie {
43 root: Arc<RwLock<TreeNode>>,
44}
45
46unsafe impl Sync for Trie {}
47unsafe impl Send for Trie {}
48
49#[derive(Debug, Default)]
50struct TreeNode {
51 nodes: HashMap<String, Arc<RwLock<TreeNode>>>,
52 value: Option<Arc<MethodInfo>>,
53}
54
55#[derive(Debug)]
56pub struct QueryResult {
57 pub method_info: Arc<MethodInfo>,
58 pub rest_fields: Option<Vec<(String, String)>>,
59}
60
61impl Trie {
62 pub async fn insert(&mut self, handler_info: Arc<MethodInfo>) {
63 let path = format!("{}:{}", handler_info.method, handler_info.path);
64 let paths: Vec<&str> = path.split('/').collect();
65 let mut temp = self.root.clone();
66 for item in paths {
67 let res_node = temp.read().await.nodes.get(item).cloned();
68 match res_node {
69 Some(node) => {
70 temp = node;
71 }
72 None => {
73 let new_node = Arc::new(RwLock::new(Default::default()));
74 temp.clone()
75 .write()
76 .await
77 .nodes
78 .insert(item.to_owned(), new_node.clone());
79 temp = new_node;
80 }
81 }
82 }
83 let _ = temp.write().await.value.insert(handler_info);
84 }
85
86 pub async fn search(&self, path: &str) -> Option<QueryResult> {
87 Self::search_by_nodes(path, self.root.clone()).await
88 }
89
90 #[async_recursion]
91 async fn search_by_nodes(path: &str, mut temp: Arc<RwLock<TreeNode>>) -> Option<QueryResult> {
92 let mut rest_fields: Vec<(String, String)> = vec![];
93 let paths: Vec<&str> = path.split('/').collect();
94 for (idx, item) in paths.iter().enumerate() {
95 let res_node = temp.read().await.nodes.get(*item).cloned();
96 match res_node {
97 Some(node) => {
98 temp = node;
99 }
100 None => {
101 let temp_path = paths[idx + 1..].join("/").to_string();
102 for entry in temp.read().await.nodes.iter() {
103 if entry.0.starts_with('{') {
104 if temp_path.is_empty() && entry.1.read().await.value.is_some() {
105 rest_fields.push((
106 entry.0[1..entry.0.len() - 1].to_string(),
107 item.to_string(),
108 ));
109 return entry.1.read().await.value.as_ref().map(|method_info| {
110 QueryResult {
111 method_info: method_info.clone(),
112 rest_fields: if rest_fields.is_empty() {
113 None
114 } else {
115 Some(rest_fields)
116 },
117 }
118 });
119 }
120 if let Some(query_result) =
121 Self::search_by_nodes(&temp_path, entry.1.clone()).await
122 {
123 rest_fields.push((
124 entry.0[1..entry.0.len() - 1].to_string(),
125 item.to_string(),
126 ));
127 if let Some(mut temp_query_fields) = query_result.rest_fields {
128 rest_fields.append(&mut temp_query_fields);
129 }
130 return Some(QueryResult {
131 method_info: query_result.method_info,
132 rest_fields: if rest_fields.is_empty() {
133 None
134 } else {
135 Some(rest_fields)
136 },
137 });
138 }
139 }
140 }
141 return None;
142 }
143 }
144 }
145 temp.read()
146 .await
147 .value
148 .as_ref()
149 .map(|method_info| QueryResult {
150 method_info: method_info.clone(),
151 rest_fields: if rest_fields.is_empty() {
152 None
153 } else {
154 Some(rest_fields)
155 },
156 })
157 }
158}