-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.rs
146 lines (127 loc) · 3.81 KB
/
server.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use crate::graph::{FileMetadata, Graph, RelatedFileContext};
use crate::symbol::{Symbol, SymbolKind};
use axum::extract::Query;
use axum::routing::get;
use axum::Router;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::sync::{Arc, RwLock};
lazy_static::lazy_static! {
pub static ref GRAPH_INST: Arc<RwLock<Graph>> = Arc::new(RwLock::new(Graph::empty()));
}
pub(crate) const VERSION: &str = env!("CARGO_PKG_VERSION");
#[tokio::main]
pub async fn server_main(server_conf: ServerConfig) {
*GRAPH_INST.write().unwrap() = server_conf.graph;
let routers = create_router();
let listener = tokio::net::TcpListener::bind(format!("127.0.0.1:{}", server_conf.port))
.await
.unwrap();
axum::serve(listener, routers).await.unwrap();
}
pub fn create_router() -> Router {
Router::new()
.nest(
"/file",
Router::new()
.route("/metadata", get(file_metadata_handler))
.route("/relation", get(file_relation_handler))
.route("/list", get(file_list_handler)),
)
.nest(
"/symbol",
Router::new()
.route("/relation", get(symbol_relation_handler))
.route("/metadata", get(symbol_metadata_handler)),
)
.route("/", get(root_handler))
}
pub struct ServerConfig {
pub port: u16,
pub graph: Graph,
}
impl ServerConfig {
pub fn new(g: Graph) -> ServerConfig {
ServerConfig {
port: 9411,
graph: g,
}
}
}
async fn root_handler() -> axum::Json<Desc> {
axum::Json(Desc {
version: VERSION.to_string(),
})
}
#[derive(Deserialize, Serialize, Debug)]
struct Desc {
version: String,
}
#[derive(Deserialize, Serialize, Debug)]
struct FileParams {
pub path: String,
}
#[derive(Deserialize, Serialize, Debug)]
struct SymbolParams {
pub path: String,
pub start_byte: usize,
}
#[derive(Deserialize, Serialize, Debug)]
struct SymbolIdParams {
pub id: String,
}
async fn file_metadata_handler(Query(params): Query<FileParams>) -> axum::Json<FileMetadata> {
let g = GRAPH_INST.read().unwrap();
axum::Json(g.file_metadata(¶ms.path))
}
async fn file_relation_handler(
Query(params): Query<FileParams>,
) -> axum::Json<Vec<RelatedFileContext>> {
let g = GRAPH_INST.read().unwrap();
axum::Json(g.related_files(¶ms.path))
}
async fn file_list_handler() -> axum::Json<HashSet<String>> {
let g = GRAPH_INST.read().unwrap();
axum::Json(g.files())
}
async fn symbol_relation_handler(
Query(params): Query<SymbolParams>,
) -> axum::Json<HashMap<String, usize>> {
let g = GRAPH_INST.read().unwrap();
let targets: Vec<Symbol> = g
.file_metadata(¶ms.path)
.symbols
.into_iter()
.filter(|each| {
return each.range.start_byte == params.start_byte;
})
.collect();
if targets.len() == 0 {
return axum::Json(HashMap::new());
}
// only one
let target = &targets[0];
let symbol_map = match target.kind {
SymbolKind::DEF => g.symbol_graph.list_references_by_definition(&target.id()),
SymbolKind::REF => g.symbol_graph.list_definitions_by_reference(&target.id()),
};
let str_symbol_map: HashMap<String, usize> = symbol_map
.into_iter()
.map(|(key, value)| {
return (key.id(), value);
})
.collect();
axum::Json(str_symbol_map)
}
async fn symbol_metadata_handler(
Query(params): Query<SymbolIdParams>,
) -> axum::Json<Option<Symbol>> {
let g = GRAPH_INST.read().unwrap();
let ret = g.symbol_graph.symbol_mapping.get(¶ms.id);
if ret.is_none() {
return axum::Json(None);
}
axum::Json(Option::from(
g.symbol_graph.g[*ret.unwrap()].get_symbol().unwrap(),
))
}