1use std::collections::VecDeque;
2use std::fmt::Debug;
3
4use clap::{ArgMatches, Command, CommandFactory, FromArgMatches};
5use imbl_value::imbl::OrdMap;
6use imbl_value::Value;
7use serde::Serialize;
8use yajrc::RpcError;
9
10use crate::util::{combine, Flat, PhantomData};
11use crate::{
12 CliBindings, DynHandler, Empty, HandleAny, HandleAnyArgs, Handler, HandlerArgs, HandlerArgsFor,
13 HandlerFor, HandlerTypes, WithContext,
14};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17pub(crate) struct Name(pub(crate) &'static str);
18impl<'a> std::borrow::Borrow<&'a str> for Name {
19 fn borrow(&self) -> &&'a str {
20 &self.0
21 }
22}
23
24pub(crate) struct SubcommandMap<Context, Params, InheritedParams>(
25 pub(crate) Option<DynHandler<Context, InheritedParams>>,
26 pub(crate) OrdMap<Name, DynHandler<Context, Flat<Params, InheritedParams>>>,
27);
28impl<Context, Params, InheritedParams> Clone for SubcommandMap<Context, Params, InheritedParams> {
29 fn clone(&self) -> Self {
30 Self(self.0.clone(), self.1.clone())
31 }
32}
33impl<Context, Params, InheritedParams> Debug for SubcommandMap<Context, Params, InheritedParams> {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 let mut map = f.debug_map();
36 if let Some(root) = &self.0 {
37 #[derive(Debug)]
38 struct Root;
39 map.entry(&Root, root);
40 }
41 map.entries(self.1.iter()).finish()
42 }
43}
44impl<Context, Params, InheritedParams> SubcommandMap<Context, Params, InheritedParams> {
45 fn set_root(&mut self, handler: DynHandler<Context, InheritedParams>) {
46 self.0 = Some(handler);
47 }
48 fn get_root<'a>(&'a self) -> Option<&'a DynHandler<Context, InheritedParams>> {
49 self.0.as_ref()
50 }
51 fn insert(
52 &mut self,
53 name: &'static str,
54 handler: DynHandler<Context, Flat<Params, InheritedParams>>,
55 ) {
56 self.1.insert(Name(name), handler);
57 }
58 fn get<'a>(
59 &'a self,
60 name: &str,
61 ) -> Option<(Name, &'a DynHandler<Context, Flat<Params, InheritedParams>>)> {
62 if let Some((name, handler)) = self.1.get_key_value(&name) {
63 Some((*name, handler))
64 } else {
65 None
66 }
67 }
68}
69
70pub struct ParentHandler<Context, Params = Empty, InheritedParams = Empty> {
71 _phantom: PhantomData<Context>,
72 pub(crate) subcommands: SubcommandMap<Context, Params, InheritedParams>,
73 metadata: OrdMap<&'static str, Value>,
74}
75impl<Context, Params, InheritedParams> ParentHandler<Context, Params, InheritedParams> {
76 pub fn new() -> Self {
77 Self {
78 _phantom: PhantomData::new(),
79 subcommands: SubcommandMap(None, OrdMap::new()),
80 metadata: OrdMap::new(),
81 }
82 }
83 pub fn with_metadata(mut self, key: &'static str, value: Value) -> Self {
84 self.metadata.insert(key, value);
85 self
86 }
87}
88impl<Context, Params, InheritedParams> Clone for ParentHandler<Context, Params, InheritedParams> {
89 fn clone(&self) -> Self {
90 Self {
91 _phantom: PhantomData::new(),
92 subcommands: self.subcommands.clone(),
93 metadata: self.metadata.clone(),
94 }
95 }
96}
97impl<Context, Params, InheritedParams> std::fmt::Debug
98 for ParentHandler<Context, Params, InheritedParams>
99{
100 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101 f.debug_tuple("ParentHandler")
102 .field(&self.subcommands)
103 .finish()
104 }
105}
106
107impl<Context: crate::Context, Params, InheritedParams>
108 ParentHandler<Context, Params, InheritedParams>
109{
110 pub fn subcommand<C: crate::Context, H>(mut self, name: &'static str, handler: H) -> Self
111 where
112 WithContext<C, H>: Handler<Flat<Params, InheritedParams>>,
113 {
114 if let Some(h) = DynHandler::new(handler) {
115 self.subcommands.insert(name.into(), h);
116 }
117 self
118 }
119 pub fn root_handler<C: crate::Context, H>(mut self, handler: H) -> Self
120 where
121 WithContext<C, H>: Handler<InheritedParams>,
122 <WithContext<C, H> as Handler<InheritedParams>>::H: HandlerTypes<Params = Params>,
123 {
124 if let Some(h) = DynHandler::new(handler) {
125 self.subcommands.set_root(h);
126 }
127 self
128 }
129}
130
131impl<Context, Params, InheritedParams> HandlerTypes
132 for ParentHandler<Context, Params, InheritedParams>
133where
134 Params: Send + Sync,
135 InheritedParams: Send + Sync,
136{
137 type Params = Params;
138 type InheritedParams = InheritedParams;
139 type Ok = Value;
140 type Err = RpcError;
141}
142
143impl<Context, Params, InheritedParams> HandlerFor<Context>
144 for ParentHandler<Context, Params, InheritedParams>
145where
146 Context: crate::Context,
147 Params: Send + Sync + 'static,
148 InheritedParams: Send + Sync + 'static,
149{
150 fn handle_sync(
151 &self,
152 HandlerArgs {
153 context,
154 mut parent_method,
155 mut method,
156 params,
157 inherited_params,
158 raw_params,
159 }: HandlerArgsFor<Context, Self>,
160 ) -> Result<Self::Ok, Self::Err> {
161 let cmd = method.pop_front();
162 if let Some(cmd) = cmd {
163 parent_method.push_back(cmd);
164 if let Some((_, sub_handler)) = &self.subcommands.get(cmd) {
165 sub_handler.handle_sync(HandleAnyArgs {
166 context,
167 parent_method,
168 method,
169 params: raw_params,
170 inherited: Flat(params, inherited_params),
171 })
172 } else {
173 Err(yajrc::METHOD_NOT_FOUND_ERROR)
174 }
175 } else {
176 if let Some(sub_handler) = &self.subcommands.get_root() {
177 sub_handler.handle_sync(HandleAnyArgs {
178 context,
179 parent_method,
180 method,
181 params: raw_params,
182 inherited: inherited_params,
183 })
184 } else {
185 Err(yajrc::METHOD_NOT_FOUND_ERROR)
186 }
187 }
188 }
189 async fn handle_async(
190 &self,
191 HandlerArgs {
192 context,
193 mut parent_method,
194 mut method,
195 params,
196 inherited_params,
197 raw_params,
198 }: HandlerArgsFor<Context, Self>,
199 ) -> Result<Self::Ok, Self::Err> {
200 let cmd = method.pop_front();
201 if let Some(cmd) = cmd {
202 parent_method.push_back(cmd);
203 if let Some((_, sub_handler)) = &self.subcommands.get(cmd) {
204 sub_handler
205 .handle_async(HandleAnyArgs {
206 context,
207 parent_method,
208 method,
209 params: raw_params,
210 inherited: Flat(params, inherited_params),
211 })
212 .await
213 } else {
214 Err(yajrc::METHOD_NOT_FOUND_ERROR)
215 }
216 } else {
217 if let Some(sub_handler) = &self.subcommands.get_root() {
218 sub_handler
219 .handle_async(HandleAnyArgs {
220 context,
221 parent_method,
222 method,
223 params: raw_params,
224 inherited: inherited_params,
225 })
226 .await
227 } else {
228 Err(yajrc::METHOD_NOT_FOUND_ERROR)
229 }
230 }
231 }
232 fn metadata(&self, mut method: VecDeque<&'static str>) -> OrdMap<&'static str, Value> {
233 let metadata = self.metadata.clone();
234 if let Some(cmd) = method.pop_front() {
235 if let Some((_, handler)) = self.subcommands.get(cmd) {
236 handler.metadata(method).union(metadata)
237 } else {
238 metadata
239 }
240 } else {
241 if let Some(handler) = self.subcommands.get_root() {
242 handler.metadata(method).union(metadata)
243 } else {
244 metadata
245 }
246 }
247 }
248 fn method_from_dots(&self, method: &str) -> Option<VecDeque<&'static str>> {
249 let (head, tail) = if method.is_empty() {
250 (None, None)
251 } else {
252 method
253 .split_once(".")
254 .map(|(head, tail)| (Some(head), Some(tail)))
255 .unwrap_or((Some(method), None))
256 };
257 if let Some(head) = head {
258 let (Name(name), h) = self.subcommands.get(head)?;
259 let mut res = VecDeque::new();
260 res.push_back(name);
261 if let Some(tail) = tail {
262 res.append(&mut h.method_from_dots(tail)?);
263 }
264 Some(res)
265 } else {
266 let h = self.subcommands.get_root()?;
267 let mut res = VecDeque::new();
268 if let Some(tail) = tail {
269 res.append(&mut h.method_from_dots(tail)?);
270 }
271 Some(res)
272 }
273 }
274}
275
276impl<Context, Params, InheritedParams> CliBindings<Context>
277 for ParentHandler<Context, Params, InheritedParams>
278where
279 Context: crate::Context,
280 Params: FromArgMatches + CommandFactory + Serialize + Send + Sync + 'static,
281 InheritedParams: Send + Sync + 'static,
282{
283 fn cli_command(&self) -> Command {
284 let mut base = if let Some(cli) = &self.subcommands.0.as_ref().and_then(|h| h.cli()) {
285 cli.cli_command().subcommand_required(false)
286 } else {
287 Params::command().subcommand_required(true)
288 };
289 for (name, handler) in &self.subcommands.1 {
290 match (name, handler.cli()) {
291 (Name(name), Some(cli)) => {
292 base = base.subcommand(cli.cli_command().name(name));
293 }
294 _ => (),
295 }
296 }
297 base
298 }
299 fn cli_parse(
300 &self,
301 root_matches: &ArgMatches,
302 ) -> Result<(VecDeque<&'static str>, Value), clap::Error> {
303 let (name, matches) = match root_matches.subcommand() {
304 Some((name, matches)) => (Some(name), matches),
305 None => (None, root_matches),
306 };
307 if let Some(name) = name {
308 let root_params = imbl_value::to_value(&Params::from_arg_matches(root_matches)?)
309 .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?;
310 if let Some((Name(name), cli)) = self
311 .subcommands
312 .get(name)
313 .and_then(|(n, h)| h.cli().map(|c| (n, c)))
314 {
315 let (mut method, params) = cli.cli_parse(matches)?;
316 method.push_front(name);
317
318 Ok((
319 method,
320 combine(root_params, params).map_err(|e| {
321 clap::Error::raw(clap::error::ErrorKind::ArgumentConflict, e)
322 })?,
323 ))
324 } else {
325 Ok((VecDeque::new(), root_params))
326 }
327 } else {
328 if let Some(cli) = self.subcommands.get_root().and_then(|h| h.cli()) {
329 let (method, params) = cli.cli_parse(matches)?;
330
331 Ok((method, params))
332 } else {
333 let root_params = imbl_value::to_value(&Params::from_arg_matches(matches)?)
334 .map_err(|e| clap::Error::raw(clap::error::ErrorKind::ValueValidation, e))?;
335 Ok((VecDeque::new(), root_params))
336 }
337 }
338 }
339 fn cli_display(
340 &self,
341 HandlerArgs {
342 context,
343 mut parent_method,
344 mut method,
345 params,
346 inherited_params,
347 raw_params,
348 }: HandlerArgsFor<Context, Self>,
349 result: Self::Ok,
350 ) -> Result<(), Self::Err> {
351 let cmd = method.pop_front();
352 if let Some(cmd) = cmd {
353 parent_method.push_back(cmd);
354 if let Some((_, cli)) = self
355 .subcommands
356 .get(cmd)
357 .and_then(|(n, h)| h.cli().map(|c| (n, c)))
358 {
359 cli.cli_display(
360 HandleAnyArgs {
361 context,
362 parent_method,
363 method,
364 params: raw_params,
365 inherited: Flat(params, inherited_params),
366 },
367 result,
368 )
369 } else {
370 Err(yajrc::METHOD_NOT_FOUND_ERROR)
371 }
372 } else {
373 if let Some(cli) = self.subcommands.get_root().and_then(|h| h.cli()) {
374 cli.cli_display(
375 HandleAnyArgs {
376 context,
377 parent_method,
378 method,
379 params: raw_params,
380 inherited: inherited_params,
381 },
382 result,
383 )
384 } else {
385 Err(yajrc::METHOD_NOT_FOUND_ERROR)
386 }
387 }
388 }
389}