1use std::sync::Arc;
4
5use crate::error::{Error, Result};
6use crate::value::{CommandDataKind, Value};
7use crate::dev::CommandInfo;
8
9use super::dev::{some_doc, Access, Dev, ModelRef};
10use super::def::{CommandDef, ExecFn};
11use super::Model;
12
13
14pub struct Command<M: Model> {
20 def: Arc<CommandDef<M>>,
22}
23
24impl<M: Model> Command<M> {
25
26 pub(super) fn new(def: Arc<CommandDef<M>>) -> Self {
28 Self { def }
29 }
30
31 #[inline]
33 pub fn name(&self) -> &str {
34 &self.def.name
35 }
36
37 pub(super) fn access(&self) -> Access {
39 match &self.def.exec {
40 Some(ExecFn::ExclusiveSync(_) | ExecFn::ExclusiveAsync(_)) => Access::Exclusive,
41 _ => Access::Shared,
42 }
43 }
44
45 pub(super) fn may_block(&self) -> bool {
48 matches!(&self.def.exec, Some(ExecFn::SharedSync(_) | ExecFn::ExclusiveSync(_)))
49 }
50
51 pub fn info(&self) -> CommandInfo {
54 CommandInfo {
55 display_level: self.def.display_level,
56 in_kind: self.def.in_kind.unwrap_or(CommandDataKind::Void),
57 out_kind: self.def.out_kind.unwrap_or(CommandDataKind::Void),
58 in_doc: some_doc(&self.def.in_doc),
59 out_doc: some_doc(&self.def.out_doc),
60 }
61 }
62
63 pub(super) async fn exec(&self, dev: &Dev<M>, model: &mut ModelRef<'_, M>, input: Value) -> Result<Value> {
66 match &self.def.exec {
67 Some(ExecFn::SharedSync(func)) => func(model.shared(), dev, input),
68 Some(ExecFn::ExclusiveSync(func)) => func(model.exclusive()?, dev, input),
69 Some(ExecFn::SharedAsync(func)) => func(model.shared(), dev, input).await,
70 Some(ExecFn::ExclusiveAsync(func)) => func(model.exclusive()?, dev, input).await,
71 None => Err(Error::not_implemented()
72 .with_description(format!("The command {} of the device {} has no execution function", self.name(), dev.name()))),
73 }
74 }
75
76}