1use std::collections::HashMap;
7use std::io::{self, BufRead, Write};
8
9use serde_json::Value;
10
11use crate::protocol::{Request, Response};
12
13pub type Handler = fn(Vec<Value>) -> Result<Value, String>;
39
40#[derive(Debug)]
68pub struct BinaryServer {
69 handlers: HashMap<String, Handler>,
70}
71
72impl BinaryServer {
73 pub fn new() -> Self {
83 Self {
84 handlers: HashMap::new(),
85 }
86 }
87
88 pub fn register(&mut self, action: &str, handler: Handler) {
114 self.handlers.insert(action.to_string(), handler);
115 }
116
117 pub fn run(&self) {
128 let stdin = io::stdin();
129 let mut stdout = io::stdout();
130
131 for line in stdin.lock().lines() {
132 let line = match line {
133 Ok(l) => l,
134 Err(_) => continue,
135 };
136
137 let response = match serde_json::from_str::<Request>(&line) {
138 Ok(req) => self.handle_request(req),
139 Err(err) => {
140 let raw = format!(r#"{{"status":"error","error":"invalid json: {}"}}"#, err);
141 let _ = writeln!(stdout, "{}", raw);
142 let _ = stdout.flush();
143 continue;
144 }
145 };
146
147 match serde_json::to_string(&response) {
148 Ok(out) => {
149 let _ = writeln!(stdout, "{}", out);
150 let _ = stdout.flush();
151 }
152 Err(err) => {
153 let raw = format!(
154 r#"{{"status":"error","error":"serialization failed: {}"}}"#,
155 err
156 );
157 let _ = writeln!(stdout, "{}", raw);
158 let _ = stdout.flush();
159 }
160 }
161 }
162 }
163
164 fn handle_request(&self, req: Request) -> Response {
174 match self.handlers.get(&req.action) {
175 Some(handler) => match handler(req.params) {
176 Ok(result) => Response::Ok { id: req.id, result },
177 Err(msg) => Response::Error {
178 id: req.id,
179 error: msg,
180 },
181 },
182 None => Response::Error {
183 id: req.id,
184 error: format!("unknown action: {}", req.action),
185 },
186 }
187 }
188}
189
190impl Default for BinaryServer {
191 fn default() -> Self {
192 Self::new()
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199 use serde_json::json;
200
201 fn test_handler_success(params: Vec<Value>) -> Result<Value, String> {
202 Ok(json!({"received": params.len()}))
203 }
204
205 fn test_handler_error(_params: Vec<Value>) -> Result<Value, String> {
206 Err("intentional error".to_string())
207 }
208
209 fn add_handler(params: Vec<Value>) -> Result<Value, String> {
210 if params.len() != 2 {
211 return Err("Expected 2 parameters".into());
212 }
213 let a = params[0].as_i64().ok_or("Invalid number")?;
214 let b = params[1].as_i64().ok_or("Invalid number")?;
215 Ok(Value::from(a + b))
216 }
217
218 #[test]
219 fn test_server_creation() {
220 let server = BinaryServer::new();
221 assert_eq!(server.handlers.len(), 0);
222 }
223
224 #[test]
225 fn test_server_default() {
226 let server = BinaryServer::default();
227 assert_eq!(server.handlers.len(), 0);
228 }
229
230 #[test]
231 fn test_register_handler() {
232 let mut server = BinaryServer::new();
233 server.register("test", test_handler_success);
234 assert_eq!(server.handlers.len(), 1);
235 assert!(server.handlers.contains_key("test"));
236 }
237
238 #[test]
239 fn test_register_multiple_handlers() {
240 let mut server = BinaryServer::new();
241 server.register("handler1", test_handler_success);
242 server.register("handler2", test_handler_error);
243 assert_eq!(server.handlers.len(), 2);
244 }
245
246 #[test]
247 fn test_handle_request_success() {
248 let mut server = BinaryServer::new();
249 server.register("test", test_handler_success);
250
251 let request = Request {
252 id: "req-1".to_string(),
253 action: "test".to_string(),
254 params: vec![json!(1), json!(2)],
255 };
256
257 let response = server.handle_request(request);
258
259 match response {
260 Response::Ok { id, result } => {
261 assert_eq!(id, "req-1");
262 assert_eq!(result, json!({"received": 2}));
263 }
264 _ => panic!("Expected Ok response"),
265 }
266 }
267
268 #[test]
269 fn test_handle_request_handler_error() {
270 let mut server = BinaryServer::new();
271 server.register("test", test_handler_error);
272
273 let request = Request {
274 id: "req-2".to_string(),
275 action: "test".to_string(),
276 params: vec![],
277 };
278
279 let response = server.handle_request(request);
280
281 match response {
282 Response::Error { id, error } => {
283 assert_eq!(id, "req-2");
284 assert_eq!(error, "intentional error");
285 }
286 _ => panic!("Expected Error response"),
287 }
288 }
289
290 #[test]
291 fn test_handle_request_unknown_action() {
292 let server = BinaryServer::new();
293
294 let request = Request {
295 id: "req-3".to_string(),
296 action: "nonexistent".to_string(),
297 params: vec![],
298 };
299
300 let response = server.handle_request(request);
301
302 match response {
303 Response::Error { id, error } => {
304 assert_eq!(id, "req-3");
305 assert_eq!(error, "unknown action: nonexistent");
306 }
307 _ => panic!("Expected Error response"),
308 }
309 }
310
311 #[test]
312 fn test_add_handler_success() {
313 let mut server = BinaryServer::new();
314 server.register("add", add_handler);
315
316 let request = Request {
317 id: "req-4".to_string(),
318 action: "add".to_string(),
319 params: vec![json!(5), json!(10)],
320 };
321
322 let response = server.handle_request(request);
323
324 match response {
325 Response::Ok { id, result } => {
326 assert_eq!(id, "req-4");
327 assert_eq!(result, json!(15));
328 }
329 _ => panic!("Expected Ok response"),
330 }
331 }
332
333 #[test]
334 fn test_add_handler_wrong_param_count() {
335 let mut server = BinaryServer::new();
336 server.register("add", add_handler);
337
338 let request = Request {
339 id: "req-5".to_string(),
340 action: "add".to_string(),
341 params: vec![json!(5)],
342 };
343
344 let response = server.handle_request(request);
345
346 match response {
347 Response::Error { id, error } => {
348 assert_eq!(id, "req-5");
349 assert_eq!(error, "Expected 2 parameters");
350 }
351 _ => panic!("Expected Error response"),
352 }
353 }
354
355 #[test]
356 fn test_add_handler_invalid_type() {
357 let mut server = BinaryServer::new();
358 server.register("add", add_handler);
359
360 let request = Request {
361 id: "req-6".to_string(),
362 action: "add".to_string(),
363 params: vec![json!("not a number"), json!(10)],
364 };
365
366 let response = server.handle_request(request);
367
368 match response {
369 Response::Error { id, error } => {
370 assert_eq!(id, "req-6");
371 assert_eq!(error, "Invalid number");
372 }
373 _ => panic!("Expected Error response"),
374 }
375 }
376}