vantage_cmd/
expr_data_source.rs1use std::future::Future;
8use std::pin::Pin;
9
10use ciborium::Value as CborValue;
11use vantage_core::Result;
12use vantage_expressions::{
13 Expression,
14 traits::datasource::{DataSource, ExprDataSource},
15 traits::expressive::{DeferredFn, ExpressiveEnum},
16};
17
18use crate::cmd::Cmd;
19
20impl DataSource for Cmd {}
21
22impl ExprDataSource<CborValue> for Cmd {
23 async fn execute(&self, expr: &Expression<CborValue>) -> Result<CborValue> {
24 if expr.parameters.is_empty() {
25 Ok(CborValue::Text(expr.template.clone()))
26 } else if expr.parameters.len() == 1 {
27 resolve_param(&expr.parameters[0]).await
28 } else {
29 Ok(CborValue::Null)
30 }
31 }
32
33 fn defer(&self, expr: Expression<CborValue>) -> DeferredFn<CborValue> {
34 let this = self.clone();
35 DeferredFn::new(move || {
36 let this = this.clone();
37 let expr = expr.clone();
38 Box::pin(async move {
39 let result = ExprDataSource::execute(&this, &expr).await?;
40 Ok(ExpressiveEnum::Scalar(result))
41 })
42 })
43 }
44}
45
46pub(crate) fn resolve_param(
50 param: &ExpressiveEnum<CborValue>,
51) -> Pin<Box<dyn Future<Output = Result<CborValue>> + Send + '_>> {
52 Box::pin(async move {
53 match param {
54 ExpressiveEnum::Scalar(v) => Ok(v.clone()),
55 ExpressiveEnum::Deferred(deferred) => {
56 let result = deferred.call().await?;
57 match result {
58 ExpressiveEnum::Scalar(v) => Ok(v),
59 other => resolve_param(&other).await,
60 }
61 }
62 ExpressiveEnum::Nested(expr) => {
63 if expr.parameters.is_empty() {
64 Ok(CborValue::Text(expr.template.clone()))
65 } else if expr.parameters.len() == 1 {
66 resolve_param(&expr.parameters[0]).await
67 } else {
68 Ok(CborValue::Text(expr.template.clone()))
69 }
70 }
71 }
72 })
73}