1use std::{
2 collections::HashMap,
3 fmt::{self, Debug},
4 marker::PhantomData,
5 sync::Arc,
6};
7
8use async_fn_traits::{AsyncFn1, AsyncFn2, AsyncFn3, AsyncFn4};
9use async_trait::async_trait;
10
11use crate::{
12 Error,
13 commands::{Context, Converter, checks::Check},
14};
15
16#[derive(Clone)]
17pub struct Command<E, S> {
18 pub name: String,
19 pub handle: Arc<dyn CommandHandle<(), E, S>>,
20 pub children: HashMap<String, Command<E, S>>,
21 pub checks: Vec<Arc<dyn Check<E, S>>>,
22 pub aliases: Vec<String>,
23 pub description: Option<String>,
24 pub signature: Option<String>,
25 pub parents: Vec<String>,
26 pub hidden: bool,
27}
28
29impl<E, S> fmt::Debug for Command<E, S> {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 f.debug_struct("Command")
32 .field("name", &self.name)
33 .field("description", &self.description)
34 .field("children", &self.children)
35 .field("aliases", &self.aliases)
36 .field("signature", &self.signature)
37 .finish_non_exhaustive()
38 }
39}
40
41impl<
42 E: From<Error> + Clone + Debug + Send + Sync + 'static,
43 S: Debug + Clone + Send + Sync + 'static,
44> Command<E, S>
45{
46 pub fn new<T: Send + Sync + 'static, I: Into<String>, F: CommandHandle<T, E, S> + Clone>(
47 name: I,
48 handle: F,
49 ) -> Self {
50 let erased = ErasedCommandHandler {
51 handle,
52 _p: PhantomData,
53 };
54
55 Self {
56 name: name.into(),
57 handle: Arc::new(erased),
58 children: HashMap::new(),
59 checks: Vec::new(),
60 aliases: Vec::new(),
61 description: None,
62 signature: None,
63 parents: Vec::new(),
64 hidden: false,
65 }
66 }
67
68 pub fn child(mut self, mut command: Self) -> Self {
69 command.parents = self.parents.clone();
70 command.parents.push(self.name.clone());
71
72 self.children.insert(command.name.clone(), command.clone());
73
74 for alias in command.aliases.clone() {
75 self.children.insert(alias, command.clone());
76 }
77
78 self
79 }
80
81 pub fn description<I: Into<String>>(mut self, description: I) -> Self {
82 self.description = Some(description.into());
83
84 self
85 }
86
87 pub fn signature<I: Into<String>>(mut self, signature: I) -> Self {
88 self.signature = Some(signature.into());
89
90 self
91 }
92
93 pub fn check<C: Check<E, S>>(mut self, check: C) -> Self {
94 self.checks.push(Arc::new(check));
95
96 self
97 }
98
99 pub fn alias<I: Into<String>>(mut self, alias: I) -> Self {
100 self.aliases.push(alias.into());
101
102 self
103 }
104
105 pub fn hidden(mut self) -> Self {
106 self.hidden = true;
107
108 self
109 }
110
111 pub fn children(&self) -> Vec<Command<E, S>> {
112 self.children
113 .clone()
114 .into_iter()
115 .filter(|(name, command)| name == &command.name)
116 .map(|(_, command)| command)
117 .collect()
118 }
119
120 pub fn get_command(&self, name: &str) -> Option<Command<E, S>> {
121 self.children.get(name).cloned()
122 }
123
124 pub async fn can_run(&self, context: Context<E, S>) -> Result<bool, E> {
125 for check in &self.checks {
126 if check.run(context.clone()).await? == false {
127 return Err(Error::CheckFailure.into());
128 }
129 }
130
131 Ok(true)
132 }
133}
134
135#[async_trait]
136pub trait CommandHandle<
137 T,
138 E: From<Error> + Clone + Debug + Send + Sync + 'static,
139 S: Debug + Clone + Send + Sync + 'static,
140>: Send + Sync + 'static
141{
142 async fn handle(&self, context: Context<E, S>) -> Result<(), E>;
143}
144
145#[async_trait]
146impl<E, S, F> CommandHandle<(), E, S> for F
147where
148 E: From<Error> + Clone + Debug + Send + Sync + 'static,
149 S: Debug + Clone + Send + Sync + 'static,
150 F: AsyncFn1<Context<E, S>, Output = Result<(), E>> + Send + Sync + 'static,
151 F::OutputFuture: Send,
152{
153 async fn handle(&self, context: Context<E, S>) -> Result<(), E> {
154 (self)(context).await
155 }
156}
157
158#[async_trait]
159impl<T1, E, S, F> CommandHandle<(T1,), E, S> for F
160where
161 T1: Converter<E, S> + Send,
162 E: From<Error> + Clone + Debug + Send + Sync + 'static,
163 S: Debug + Clone + Send + Sync + 'static,
164 F: AsyncFn2<Context<E, S>, T1, Output = Result<(), E>> + Send + Sync + 'static,
165 F::OutputFuture: Send,
166{
167 async fn handle(&self, context: Context<E, S>) -> Result<(), E> {
168 let t1 = T1::from_context(&context).await?;
169 (self)(context, t1).await
170 }
171}
172
173#[async_trait]
174impl<T1, T2, E, S, F> CommandHandle<(T1, T2), E, S> for F
175where
176 T1: Converter<E, S> + Send,
177 T2: Converter<E, S> + Send,
178 E: From<Error> + Clone + Debug + Send + Sync + 'static,
179 S: Debug + Clone + Send + Sync + 'static,
180 F: AsyncFn3<Context<E, S>, T1, T2, Output = Result<(), E>> + Send + Sync + 'static,
181 F::OutputFuture: Send,
182{
183 async fn handle(&self, context: Context<E, S>) -> Result<(), E> {
184 let t1 = T1::from_context(&context).await?;
185 let t2 = T2::from_context(&context).await?;
186
187 (self)(context, t1, t2).await
188 }
189}
190
191#[async_trait]
192impl<T1, T2, T3, E, S, F> CommandHandle<(T1, T2, T3), E, S> for F
193where
194 T1: Converter<E, S> + Send,
195 T2: Converter<E, S> + Send,
196 T3: Converter<E, S> + Send,
197 E: From<Error> + Clone + Debug + Send + Sync + 'static,
198 S: Debug + Clone + Send + Sync + 'static,
199 F: AsyncFn4<Context<E, S>, T1, T2, T3, Output = Result<(), E>> + Send + Sync + 'static,
200 F::OutputFuture: Send,
201{
202 async fn handle(&self, context: Context<E, S>) -> Result<(), E> {
203 let t1 = T1::from_context(&context).await?;
204 let t2 = T2::from_context(&context).await?;
205 let t3 = T3::from_context(&context).await?;
206
207 (self)(context, t1, t2, t3).await
208 }
209}
210
211struct ErasedCommandHandler<
212 T: Send + Sync + 'static,
213 E: From<Error> + Clone + Debug + Send + Sync + 'static,
214 S: Debug + Clone + Send + Sync + 'static,
215 H: CommandHandle<T, E, S>,
216> {
217 handle: H,
218 _p: PhantomData<(T, E, S)>,
219}
220
221#[async_trait]
222impl<
223 T: Send + Sync + 'static,
224 E: From<Error> + Clone + Debug + Send + Sync + 'static,
225 S: Debug + Clone + Send + Sync + 'static,
226 H: CommandHandle<T, E, S>,
227> CommandHandle<(), E, S> for ErasedCommandHandler<T, E, S, H>
228{
229 async fn handle(&self, context: Context<E, S>) -> Result<(), E> {
230 self.handle.handle(context).await
231 }
232}