blob: 878089dc039e2af60574983f2ef96b232e2c37f1 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::{commands::*, types::*},
argh::FromArgs,
async_trait::async_trait,
serde_json,
};
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
pub enum SubCommand {
List(ListCommand),
ListAccessors(ListAccessorsCommand),
ListFiles(ListFilesCommand),
Selectors(SelectorsCommand),
Show(ShowCommand),
ShowFile(ShowFileCommand),
}
#[derive(FromArgs, PartialEq, Debug)]
/// Top-level command.
pub struct CommandLine {
#[argh(option, default = "Format::Text", short = 'f')]
/// the format to be used to display the results (json, text).
pub format: Format,
#[argh(subcommand)]
pub command: SubCommand,
}
// Once Generic Associated types are implemented we could have something along the lines of
// `type Result = Box<T: Serialize>` and not rely on this macro.
macro_rules! execute_and_format {
($self:ident, [$($command:ident),*]) => {
match &$self.command {
$(
SubCommand::$command(command) => {
let result = command.execute().await?;
match $self.format {
Format::Json => {
serde_json::to_string_pretty(&result)
.map_err(|e| Error::InvalidCommandResponse(e))
}
Format::Text => {
Ok(result.to_text())
}
}
}
)*
}
}
}
#[async_trait]
impl Command for CommandLine {
type Result = String;
async fn execute(&self) -> Result<Self::Result, Error> {
execute_and_format!(self, [List, ListAccessors, ListFiles, Selectors, Show, ShowFile])
}
}