1use std::collections::HashMap;
2use std::fmt::Debug;
3use std::sync::Arc;
4use std::task::Context;
5
6use serde::de::DeserializeOwned;
7use serde::Serialize;
8
9use crate::rpc::{conversions, get_handler_key, ReqResBound};
10use crate::rpc::conversions::rpc_error;
11use crate::rpc::http::{HttpHandler, HttpRequest, HttpResponse};
12
13pub trait Request<Req> {}
14
15pub struct Handlers<Ctx> {
16 handlers: HashMap<String, Box<dyn Fn(&str, Ctx) -> String + Send + Sync>>,
17}
18
19
20impl<Ctx: 'static> Handlers<Ctx> {
21 pub fn new() -> Handlers<Ctx> {
22 Handlers { handlers: HashMap::new() }
23 }
24
25 pub fn new_http_handler(self, context_generator: fn(&HttpRequest) -> Ctx) -> HttpHandler {
26 Arc::new(move |req: HttpRequest| -> HttpResponse {
27 HttpResponse::new(self.dispatch(&req.content, context_generator(&req)))
28 })
29 }
30
31 pub fn register<Req: ReqResBound, Res: ReqResBound>(&mut self, callback: impl Fn(Req, Ctx) -> Result<Res, String> + Send + Sync + 'static)
32 where Req: Request<Res>
33 {
34 let handler_key = get_handler_key::<Req>();
35 println!("registering=`{handler_key}`");
36 self.handlers.insert(handler_key, Box::new(move |payload, ctx| {
37 let req = conversions::rpc_req_from_str(payload);
38 if let Err(msg) = req { return msg; }
39 let res = callback(req.unwrap(), ctx);
40 match res {
41 Ok(ok) => { conversions::rpc_res_to_str(&ok) }
42 Err(msg) => { rpc_error(&msg) }
43 }
44 }));
45 }
46
47 pub fn dispatch(&self, request_payload: &str, ctx: Ctx) -> String {
48 let payload = Payload::from(request_payload);
49 match payload {
50 Err(msg) => { rpc_error(&msg) }
51 Ok(payload) => {
52 let x = self.handlers.get(payload.handler_key);
53 match x {
54 None => {
55 let msg1 = format!("dispatch(...) handler not found `{}`", payload.handler_key);
56 rpc_error(&msg1)
57 }
58 Some(fun) => { fun(payload.json, ctx) }
59 }
60 }
61 }
62 }
63}
64
65
66pub struct Payload<'a> {
67 pub handler_key: &'a str,
68 pub json: &'a str,
69}
70
71impl<'a> Payload<'a> {
72 pub fn from(payload: &str) -> Result<Payload, String> {
73 let mut s = payload.splitn(2, "\n");
74 let h = s.next().ok_or("Payload split 1")?;
75 let j = s.next().ok_or("Payload split 2")?;
76 Ok(Payload {
77 handler_key: h,
78 json: j,
79 })
80 }
81
82 pub fn to_string(&self) -> String {
83 self.handler_key.to_owned() + "\n" + &*self.json
84 }
85}
86