stellar_xdr/cli/
mod.rs

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