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 #[arg(value_enum, default_value_t)]
26 channel: Channel,
27 #[command(subcommand)]
28 cmd: Cmd,
29}
30
31impl Root {
32 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 Types(types::Cmd),
68 Guess(guess::Cmd),
70 Decode(decode::Cmd),
72 Encode(encode::Cmd),
74 Compare(compare::Cmd),
75 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
96pub 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}