1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::collections::HashMap;
use crate::{
command::{fn_handler, Factory, Handler},
Context,
};
#[derive(Default)]
pub struct Group {
commands: HashMap<String, Box<Handler>>,
children: HashMap<String, Self>,
}
impl Group {
#[must_use]
pub fn new() -> Self {
Self {
commands: HashMap::new(),
children: HashMap::new(),
}
}
#[inline]
pub fn command<S, F, I, R>(mut self, name: S, handler: F) -> Self
where
S: Into<String>,
F: Factory<I, R> + 'static,
{
self.commands
.insert(name.into(), Box::new(fn_handler(handler)));
self
}
#[inline]
pub fn group<S>(mut self, name: S, child: Self) -> Self
where
S: Into<String>,
{
self.children.insert(name.into(), child);
self
}
pub(crate) fn handle(
&self,
context: Context,
function: &str,
output: *mut libc::c_char,
size: libc::size_t,
args: Option<*mut *mut i8>,
count: Option<libc::c_int>,
) -> libc::c_int {
if let Some((group, function)) = function.split_once(':') {
self.children.get(group).map_or(1, |group| {
group.handle(context, function, output, size, args, count)
})
} else if let Some(handler) = self.commands.get(function) {
(handler.handler)(context, output, size, args, count)
} else {
1
}
}
}