1use ash_rpc_core::{Message, MessageProcessor, Request, Response};
16use std::sync::Arc;
17
18pub trait ServiceContext: Send + Sync + 'static {
20 type Error: std::error::Error + Send + Sync + 'static;
21}
22
23pub trait StatefulHandler<C: ServiceContext>: Send + Sync {
25 fn handle_request(&self, context: &C, request: Request) -> Result<Response, C::Error>;
27
28 fn handle_notification(
30 &self,
31 context: &C,
32 notification: ash_rpc_core::Notification,
33 ) -> Result<(), C::Error> {
34 let _ = context;
35 let _ = notification;
36 Ok(())
37 }
38}
39
40pub trait StatefulMethodHandler<C: ServiceContext>: Send + Sync {
42 fn call(
44 &self,
45 context: &C,
46 params: Option<serde_json::Value>,
47 id: Option<ash_rpc_core::RequestId>,
48 ) -> Result<Response, C::Error>;
49}
50
51impl<C, F> StatefulMethodHandler<C> for F
52where
53 C: ServiceContext,
54 F: Fn(
55 &C,
56 Option<serde_json::Value>,
57 Option<ash_rpc_core::RequestId>,
58 ) -> Result<Response, C::Error>
59 + Send
60 + Sync,
61{
62 fn call(
63 &self,
64 context: &C,
65 params: Option<serde_json::Value>,
66 id: Option<ash_rpc_core::RequestId>,
67 ) -> Result<Response, C::Error> {
68 self(context, params, id)
69 }
70}
71
72pub struct StatefulMethodRegistry<C: ServiceContext> {
74 methods: std::collections::HashMap<String, Box<dyn StatefulMethodHandler<C>>>,
75}
76
77impl<C: ServiceContext> StatefulMethodRegistry<C> {
78 pub fn new() -> Self {
80 Self {
81 methods: std::collections::HashMap::new(),
82 }
83 }
84
85 pub fn register<H>(mut self, method: impl Into<String>, handler: H) -> Self
87 where
88 H: StatefulMethodHandler<C> + 'static,
89 {
90 self.methods.insert(method.into(), Box::new(handler));
91 self
92 }
93
94 pub fn register_fn<F>(mut self, method: impl Into<String>, handler: F) -> Self
96 where
97 F: Fn(
98 &C,
99 Option<serde_json::Value>,
100 Option<ash_rpc_core::RequestId>,
101 ) -> Result<Response, C::Error>
102 + Send
103 + Sync
104 + 'static,
105 {
106 self.methods.insert(method.into(), Box::new(handler));
107 self
108 }
109
110 pub fn call(
112 &self,
113 context: &C,
114 method: &str,
115 params: Option<serde_json::Value>,
116 id: Option<ash_rpc_core::RequestId>,
117 ) -> Result<Response, C::Error> {
118 if let Some(handler) = self.methods.get(method) {
119 handler.call(context, params, id)
120 } else {
121 Ok(ash_rpc_core::ResponseBuilder::new()
122 .error(
123 ash_rpc_core::ErrorBuilder::new(
124 ash_rpc_core::error_codes::METHOD_NOT_FOUND,
125 "Method not found",
126 )
127 .build(),
128 )
129 .id(id)
130 .build())
131 }
132 }
133}
134
135impl<C: ServiceContext> Default for StatefulMethodRegistry<C> {
136 fn default() -> Self {
137 Self::new()
138 }
139}
140
141impl<C: ServiceContext> StatefulHandler<C> for StatefulMethodRegistry<C> {
142 fn handle_request(&self, context: &C, request: Request) -> Result<Response, C::Error> {
143 self.call(context, &request.method, request.params, request.id)
144 }
145
146 fn handle_notification(
147 &self,
148 context: &C,
149 notification: ash_rpc_core::Notification,
150 ) -> Result<(), C::Error> {
151 let _ = self.call(context, ¬ification.method, notification.params, None)?;
152 Ok(())
153 }
154}
155
156pub struct StatefulProcessor<C: ServiceContext> {
157 context: Arc<C>,
158 handler: Arc<dyn StatefulHandler<C>>,
159}
160
161impl<C: ServiceContext> StatefulProcessor<C> {
162 pub fn new<H>(context: C, handler: H) -> Self
163 where
164 H: StatefulHandler<C> + 'static,
165 {
166 Self {
167 context: Arc::new(context),
168 handler: Arc::new(handler),
169 }
170 }
171
172 pub fn builder(context: C) -> StatefulProcessorBuilder<C> {
173 StatefulProcessorBuilder::new(context)
174 }
175}
176
177impl<C: ServiceContext> MessageProcessor for StatefulProcessor<C> {
178 fn process_message(&self, message: Message) -> Option<Response> {
179 match message {
180 Message::Request(request) => {
181 match self.handler.handle_request(&self.context, request) {
182 Ok(response) => Some(response),
183 Err(_) => Some(
184 ash_rpc_core::ResponseBuilder::new()
185 .error(
186 ash_rpc_core::ErrorBuilder::new(
187 ash_rpc_core::error_codes::INTERNAL_ERROR,
188 "Internal server error",
189 )
190 .build(),
191 )
192 .id(None)
193 .build(),
194 ),
195 }
196 }
197 Message::Notification(notification) => {
198 let _ = self
199 .handler
200 .handle_notification(&self.context, notification);
201 None
202 }
203 Message::Response(_) => None,
204 }
205 }
206}
207
208pub struct StatefulProcessorBuilder<C: ServiceContext> {
209 context: C,
210 handler: Option<Arc<dyn StatefulHandler<C>>>,
211}
212
213impl<C: ServiceContext> StatefulProcessorBuilder<C> {
214 pub fn new(context: C) -> Self {
215 Self {
216 context,
217 handler: None,
218 }
219 }
220
221 pub fn handler<H>(mut self, handler: H) -> Self
222 where
223 H: StatefulHandler<C> + 'static,
224 {
225 self.handler = Some(Arc::new(handler));
226 self
227 }
228
229 pub fn registry(mut self, registry: StatefulMethodRegistry<C>) -> Self {
230 self.handler = Some(Arc::new(registry));
231 self
232 }
233
234 pub fn build(self) -> Result<StatefulProcessor<C>, Box<dyn std::error::Error>> {
235 let handler = self.handler.ok_or("Handler not set")?;
236 Ok(StatefulProcessor {
237 context: Arc::new(self.context),
238 handler,
239 })
240 }
241}