Skip to main content

fusen_rs/server/
path.rs

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}