rpc_toolkit/handler/
parent.rs

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}