stellar_xdr/cli/
mod.rs

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