use std::sync::Arc;
use async_trait::async_trait;
use miette::Result;
use ockam_node::Context;
use crate::{Command, CommandGlobalOpts};
pub struct ParsedCommands {
pub commands: Vec<Arc<dyn ParsedCommand>>,
}
impl ParsedCommands {
pub fn new<C: ParsedCommand + Send + 'static>(commands: Vec<C>) -> Self {
ParsedCommands {
commands: commands
.into_iter()
.map(|c| {
let b: Arc<dyn ParsedCommand> = Arc::new(c);
b
})
.collect::<Vec<Arc<dyn ParsedCommand>>>(),
}
}
pub async fn run(self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<()> {
for cmd in self.commands.into_iter() {
if cmd.is_valid(ctx, opts).await? {
cmd.run(ctx, opts).await?;
opts.terminal.write_line("")?;
}
}
Ok(())
}
}
impl<C: ParsedCommand> From<Vec<C>> for ParsedCommands {
fn from(cmds: Vec<C>) -> ParsedCommands {
ParsedCommands::new(cmds)
}
}
#[async_trait]
pub trait ParsedCommand: Send + Sync + 'static {
async fn is_valid(&self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<bool>;
async fn run(&self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<()>;
}
#[async_trait]
impl<C> ParsedCommand for C
where
C: Command + Clone + Send + Sync + 'static,
{
async fn is_valid(&self, _ctx: &Context, _opts: &CommandGlobalOpts) -> Result<bool> {
Ok(true)
}
async fn run(&self, ctx: &Context, opts: &CommandGlobalOpts) -> Result<()> {
Ok(self.clone().async_run_with_retry(ctx, opts.clone()).await?)
}
}
struct EmptyParsedCommand;
#[async_trait]
impl ParsedCommand for EmptyParsedCommand {
async fn run(&self, _ctx: &Context, _opts: &CommandGlobalOpts) -> Result<()> {
Ok(())
}
async fn is_valid(&self, _ctx: &Context, _opts: &CommandGlobalOpts) -> Result<bool> {
Ok(false)
}
}