Skip to main content

lgui_core/command/
handle.rs

1use std::marker::PhantomData;
2
3use crate::application::ApplicationContext;
4
5use super::{Command, CommandContext};
6
7pub struct CommandHandle<C> {
8    application: ApplicationContext,
9    _command: PhantomData<fn() -> C>,
10}
11
12impl<C> Clone for CommandHandle<C> {
13    fn clone(&self) -> Self {
14        Self {
15            application: self.application.clone(),
16            _command: PhantomData,
17        }
18    }
19}
20
21impl<C> CommandHandle<C>
22where
23    C: Command,
24{
25    pub(crate) fn new(application: ApplicationContext) -> Self {
26        Self {
27            application,
28            _command: PhantomData,
29        }
30    }
31
32    pub async fn invoke(&self, args: C::Args) -> Result<C::Output, C::Error> {
33        let handler = self.application.command_registry().handler::<C>();
34        let result = self
35            .application
36            .scope(handler.invoke(
37                CommandContext::new(self.application.clone()),
38                Box::new(args),
39            ))
40            .await;
41        match result {
42            Ok(output) => Ok(output
43                .downcast::<C::Output>()
44                .map(|output| *output)
45                .unwrap_or_else(|_| {
46                    panic!("command `{}` returned an invalid output type", C::NAME)
47                })),
48            Err(error) => Err(*error.downcast::<C::Error>().unwrap_or_else(|_| {
49                panic!("command `{}` returned an invalid error type", C::NAME)
50            })),
51        }
52    }
53}