stellar_xdr/cli/generate/
default.rs1use clap::{Args, ValueEnum};
2use std::{
3 io::{stdout, Write},
4 str::FromStr,
5};
6
7use crate::cli::{util, Channel};
8
9#[derive(thiserror::Error, Debug)]
10pub enum Error {
11 #[error("unknown type {0}, choose one of {1:?}")]
12 UnknownType(String, &'static [&'static str]),
13 #[error("error reading file: {0}")]
14 ReadFile(#[from] std::io::Error),
15 #[error("error generating XDR: {0}")]
16 WriteXdrCurr(crate::curr::Error),
17 #[error("error generating XDR: {0}")]
18 WriteXdrNext(crate::next::Error),
19 #[error("error generating JSON: {0}")]
20 GenerateJson(#[from] serde_json::Error),
21 #[error("error generating arbitrary value: {0}")]
22 Arbitrary(#[from] arbitrary::Error),
23 #[error("type doesn't have a text representation, use 'json' as output")]
24 TextUnsupported,
25}
26
27impl From<crate::curr::Error> for Error {
28 fn from(e: crate::curr::Error) -> Self {
29 match e {
30 crate::curr::Error::Invalid
31 | crate::curr::Error::Unsupported
32 | crate::curr::Error::LengthExceedsMax
33 | crate::curr::Error::LengthMismatch
34 | crate::curr::Error::NonZeroPadding
35 | crate::curr::Error::Utf8Error(_)
36 | crate::curr::Error::InvalidHex
37 | crate::curr::Error::Io(_)
38 | crate::curr::Error::DepthLimitExceeded
39 | crate::curr::Error::LengthLimitExceeded
40 | crate::curr::Error::Arbitrary(_)
41 | crate::curr::Error::Json(_) => Error::WriteXdrCurr(e),
42 }
43 }
44}
45
46impl From<crate::next::Error> for Error {
47 fn from(e: crate::next::Error) -> Self {
48 match e {
49 crate::next::Error::Invalid
50 | crate::next::Error::Unsupported
51 | crate::next::Error::LengthExceedsMax
52 | crate::next::Error::LengthMismatch
53 | crate::next::Error::NonZeroPadding
54 | crate::next::Error::Utf8Error(_)
55 | crate::next::Error::InvalidHex
56 | crate::next::Error::Io(_)
57 | crate::next::Error::DepthLimitExceeded
58 | crate::next::Error::LengthLimitExceeded
59 | crate::next::Error::Arbitrary(_)
60 | crate::next::Error::Json(_) => Error::WriteXdrNext(e),
61 }
62 }
63}
64
65#[derive(Args, Debug, Clone)]
67#[command()]
68pub struct Cmd {
69 #[arg(long)]
71 pub r#type: String,
72
73 #[arg(long = "output", value_enum, default_value_t)]
75 pub output_format: OutputFormat,
76}
77
78#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ValueEnum)]
79pub enum OutputFormat {
80 Single,
81 SingleBase64,
82 Json,
86 JsonFormatted,
87 Text,
88}
89
90impl Default for OutputFormat {
91 fn default() -> Self {
92 Self::SingleBase64
93 }
94}
95
96macro_rules! run_x {
97 ($f:ident, $m:ident) => {
98 fn $f(&self) -> Result<(), Error> {
99 use crate::$m::WriteXdr;
100 let r#type = crate::$m::TypeVariant::from_str(&self.r#type).map_err(|_| {
101 Error::UnknownType(self.r#type.clone(), &crate::$m::TypeVariant::VARIANTS_STR)
102 })?;
103 let v = crate::$m::Type::default(r#type);
104 match self.output_format {
105 OutputFormat::Single => {
106 let l = crate::$m::Limits::none();
107 stdout().write_all(&v.to_xdr(l)?)?
108 }
109 OutputFormat::SingleBase64 => {
110 let l = crate::$m::Limits::none();
111 println!("{}", v.to_xdr_base64(l)?)
112 }
113 OutputFormat::Json => {
114 println!("{}", serde_json::to_string(&v)?);
115 }
116 OutputFormat::JsonFormatted => {
117 println!("{}", serde_json::to_string_pretty(&v)?);
118 }
119 OutputFormat::Text => {
120 let v = serde_json::to_value(v)?;
121 let text = util::serde_json_value_to_text(v).ok_or(Error::TextUnsupported)?;
122 println!("{text}")
123 }
124 }
125 Ok(())
126 }
127 };
128}
129
130impl Cmd {
131 pub fn run(&self, channel: &Channel) -> Result<(), Error> {
137 match channel {
138 Channel::Curr => self.run_curr()?,
139 Channel::Next => self.run_next()?,
140 }
141 Ok(())
142 }
143
144 run_x!(run_curr, curr);
145 run_x!(run_next, next);
146}