hcnet_xdr/cli/
mod.rs

1mod decode;
2mod encode;
3mod guess;
4mod types;
5mod version;
6
7use clap::{Parser, Subcommand, ValueEnum};
8use std::{ffi::OsString, fmt::Debug};
9
10#[derive(Parser, Debug, Clone)]
11#[command(
12    author,
13    version,
14    about,
15    long_about = None,
16    disable_help_subcommand = true,
17    disable_version_flag = true,
18    disable_colored_help = true,
19    infer_subcommands = true,
20)]
21pub struct Root {
22    /// Channel of XDR to operate on
23    #[arg(value_enum, default_value_t)]
24    channel: Channel,
25    #[command(subcommand)]
26    cmd: Cmd,
27}
28
29impl Root {
30    /// Run the CLIs root command.
31    ///
32    /// ## Errors
33    ///
34    /// If the root command is configured with state that is invalid.
35    pub fn run(&self) -> Result<(), Error> {
36        match &self.cmd {
37            Cmd::Types(c) => c.run(&self.channel),
38            Cmd::Guess(c) => c.run(&self.channel)?,
39            Cmd::Decode(c) => c.run(&self.channel)?,
40            Cmd::Encode(c) => c.run(&self.channel)?,
41            Cmd::Version => version::Cmd::run(),
42        }
43        Ok(())
44    }
45}
46
47#[derive(ValueEnum, Debug, Clone)]
48pub enum Channel {
49    #[value(name = "+curr")]
50    Curr,
51    #[value(name = "+next")]
52    Next,
53}
54
55impl Default for Channel {
56    fn default() -> Self {
57        Self::Curr
58    }
59}
60
61#[derive(Subcommand, Debug, Clone)]
62pub enum Cmd {
63    /// View information about types
64    Types(types::Cmd),
65    /// Guess the XDR type
66    Guess(guess::Cmd),
67    /// Decode XDR
68    Decode(decode::Cmd),
69    /// Encode XDR
70    Encode(encode::Cmd),
71    /// Print version information
72    Version,
73}
74
75#[derive(thiserror::Error, Debug)]
76#[allow(clippy::enum_variant_names)]
77pub enum Error {
78    #[error("{0}")]
79    Clap(#[from] clap::Error),
80    #[error("error decoding XDR: {0}")]
81    Guess(#[from] guess::Error),
82    #[error("error reading file: {0}")]
83    Decode(#[from] decode::Error),
84    #[error("error reading file: {0}")]
85    Encode(#[from] encode::Error),
86}
87
88/// Run the CLI with the given args.
89///
90/// ## Errors
91///
92/// If the input cannot be parsed.
93pub fn run<I, T>(args: I) -> Result<(), Error>
94where
95    I: IntoIterator<Item = T>,
96    T: Into<OsString> + Clone,
97{
98    let root = Root::try_parse_from(args)?;
99    root.run()
100}