|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  |  | 
|  | //! Sample command heirarchy. | 
|  | //! | 
|  | //! This module implements a sample command heirarchy to demonstrate | 
|  | //! the command framework for opentitantool. | 
|  |  | 
|  | use anyhow::Result; | 
|  | use erased_serde::Serialize; | 
|  | use std::any::Any; | 
|  | use structopt::StructOpt; | 
|  |  | 
|  | use opentitanlib::app::command::CommandDispatch; | 
|  | use opentitanlib::app::TransportWrapper; | 
|  |  | 
|  | #[derive(Debug, StructOpt)] | 
|  | /// The `hello world` command accepts an command option of `--cruel`. | 
|  | pub struct HelloWorld { | 
|  | #[structopt(short, long)] | 
|  | cruel: bool, | 
|  | } | 
|  |  | 
|  | #[derive(serde::Serialize)] | 
|  | /// The [`HelloMessage`] is the result of the `hello world` command. | 
|  | pub struct HelloMessage { | 
|  | pub greeting: String, | 
|  | } | 
|  |  | 
|  | impl CommandDispatch for HelloWorld { | 
|  | fn run( | 
|  | &self, | 
|  | _context: &dyn Any, | 
|  | _transport: &TransportWrapper, | 
|  | ) -> Result<Option<Box<dyn Serialize>>> { | 
|  | // Is the world cruel or not? | 
|  | let msg = if self.cruel { | 
|  | "Hello cruel World!" | 
|  | } else { | 
|  | "Hello World!" | 
|  | }; | 
|  | Ok(Some(Box::new(HelloMessage { | 
|  | greeting: msg.to_owned(), | 
|  | }))) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Debug, StructOpt)] | 
|  | /// The `hello people` command takes no additional switches or arguments. | 
|  | pub struct HelloPeople { | 
|  | // Unit structs not allowed by StructOpt | 
|  | } | 
|  |  | 
|  | impl CommandDispatch for HelloPeople { | 
|  | fn run( | 
|  | &self, | 
|  | _context: &dyn Any, | 
|  | _transport: &TransportWrapper, | 
|  | ) -> Result<Option<Box<dyn Serialize>>> { | 
|  | // The `hello people` command produces no result. | 
|  | Ok(None) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Debug, StructOpt, CommandDispatch)] | 
|  | /// There are two types of `hello` subcommand; this enum binds them together | 
|  | /// so they can both be under the `hello` command.  This enum also derives | 
|  | /// `CommandDispatch` which automatically builds a `run` method for this | 
|  | /// type which dispatches to the subcommands. | 
|  | pub enum HelloTypes { | 
|  | World(HelloWorld), | 
|  | People(HelloPeople), | 
|  | } | 
|  |  | 
|  | #[derive(Debug, StructOpt)] | 
|  | /// The `goodbye` command takes no options or arguments. | 
|  | pub struct GoodbyeCommand {} | 
|  |  | 
|  | #[derive(serde::Serialize)] | 
|  | /// The [`GoodbyeMessage`] is the result of the `goodbye` command. | 
|  | pub struct GoodbyeMessage { | 
|  | pub message: String, | 
|  | } | 
|  |  | 
|  | impl CommandDispatch for GoodbyeCommand { | 
|  | fn run( | 
|  | &self, | 
|  | _context: &dyn Any, | 
|  | _transport: &TransportWrapper, | 
|  | ) -> Result<Option<Box<dyn Serialize>>> { | 
|  | Ok(Some(Box::new(GoodbyeMessage { | 
|  | message: "Goodbye!".to_owned(), | 
|  | }))) | 
|  | } | 
|  | } | 
|  |  | 
|  | #[derive(Debug, StructOpt, CommandDispatch)] | 
|  | /// The [`Greetings`] enum binds the `hello` and `goodbye` command hirarchies | 
|  | /// in this module together into a single type which can be included into | 
|  | /// the root of the command heirarchy in `main.rs`. | 
|  | pub enum Greetings { | 
|  | Hello(HelloTypes), | 
|  | Goodbye(GoodbyeCommand), | 
|  | } |