1#![allow(clippy::print_stdout, clippy::print_stderr)]
6
7pub mod client;
8
9#[cfg(feature = "async-send")]
10pub use std::marker::Send as MaybeSend;
11#[cfg(feature = "async-send")]
12pub use std::marker::Sync as MaybeSync;
13
14pub use client::Client;
15use namada_core::*;
16
17#[allow(missing_docs)]
18#[cfg(not(feature = "async-send"))]
19pub trait MaybeSync {}
20#[cfg(not(feature = "async-send"))]
21impl<T> MaybeSync for T where T: ?Sized {}
22
23#[allow(missing_docs)]
24#[cfg(not(feature = "async-send"))]
25pub trait MaybeSend {}
26#[cfg(not(feature = "async-send"))]
27impl<T> MaybeSend for T where T: ?Sized {}
28
29#[derive(Debug, Clone, Copy)]
31pub struct DevNullProgressBar;
32
33pub trait ProgressBar {
36 fn upper_limit(&self) -> u64;
39
40 fn set_upper_limit(&mut self, limit: u64);
43
44 fn increment_by(&mut self, amount: u64);
47
48 fn message(&mut self, message: String);
50
51 fn finish(&mut self);
53}
54
55impl ProgressBar for DevNullProgressBar {
56 fn upper_limit(&self) -> u64 {
57 0
58 }
59
60 fn set_upper_limit(&mut self, _: u64) {}
61
62 fn increment_by(&mut self, _: u64) {}
63
64 fn message(&mut self, _: String) {}
65
66 fn finish(&mut self) {}
67}
68
69#[cfg(not(target_family = "wasm"))]
70impl ProgressBar for kdam::Bar {
71 fn upper_limit(&self) -> u64 {
72 self.total as u64
73 }
74
75 fn set_upper_limit(&mut self, limit: u64) {
76 self.total = limit as usize;
77 }
78
79 fn increment_by(&mut self, amount: u64) {
80 kdam::BarExt::update(self, amount as usize).unwrap();
81 }
82
83 fn message(&mut self, message: String) {
84 kdam::BarExt::write(self, message).unwrap();
85 }
86
87 fn finish(&mut self) {
88 println!();
89 }
90}
91
92#[cfg_attr(feature = "async-send", async_trait::async_trait)]
94#[cfg_attr(not(feature = "async-send"), async_trait::async_trait(?Send))]
95pub trait Io {
96 fn print(&self, output: impl AsRef<str>) {
98 print!("{}", output.as_ref());
99 }
100
101 fn flush(&self) {
103 use std::io::Write;
104 std::io::stdout().flush().unwrap();
105 }
106
107 fn println(&self, output: impl AsRef<str>) {
109 println!("{}", output.as_ref());
110 }
111
112 fn write<W: std::io::Write>(
114 &self,
115 mut writer: W,
116 output: impl AsRef<str>,
117 ) -> std::io::Result<()> {
118 write!(writer, "{}", output.as_ref())
119 }
120
121 fn writeln<W: std::io::Write>(
123 &self,
124 mut writer: W,
125 output: impl AsRef<str>,
126 ) -> std::io::Result<()> {
127 writeln!(writer, "{}", output.as_ref())
128 }
129
130 fn eprintln(&self, output: impl AsRef<str>) {
132 eprintln!("{}", output.as_ref());
133 }
134
135 async fn read(&self) -> std::io::Result<String> {
137 #[cfg(not(target_family = "wasm"))]
138 {
139 read_aux(tokio::io::stdin()).await
140 }
141 #[cfg(target_family = "wasm")]
142 {
143 unreachable!("Wasm should not perform general IO")
144 }
145 }
146
147 async fn prompt(
149 &self,
150 question: impl AsRef<str> + MaybeSync + MaybeSend,
151 ) -> String {
152 #[cfg(not(target_family = "wasm"))]
153 {
154 prompt_aux(
155 tokio::io::stdin(),
156 tokio::io::stdout(),
157 question.as_ref(),
158 )
159 .await
160 }
161 #[cfg(target_family = "wasm")]
162 {
163 unreachable!(
164 "Wasm should not perform general IO; received call for input \
165 with question\n: {}",
166 question.as_ref()
167 )
168 }
169 }
170}
171
172#[derive(Default)]
174pub struct StdIo;
175
176#[cfg_attr(feature = "async-send", async_trait::async_trait)]
177#[cfg_attr(not(feature = "async-send"), async_trait::async_trait(?Send))]
178impl Io for StdIo {}
179
180pub struct NullIo;
182
183#[cfg_attr(feature = "async-send", async_trait::async_trait)]
184#[cfg_attr(not(feature = "async-send"), async_trait::async_trait(?Send))]
185impl Io for NullIo {
186 fn print(&self, _output: impl AsRef<str>) {}
187
188 fn flush(&self) {}
189
190 fn println(&self, _output: impl AsRef<str>) {}
191
192 fn write<W: std::io::Write>(
193 &self,
194 mut _writer: W,
195 _output: impl AsRef<str>,
196 ) -> std::io::Result<()> {
197 Ok(())
198 }
199
200 fn writeln<W: std::io::Write>(
201 &self,
202 mut _writer: W,
203 _output: impl AsRef<str>,
204 ) -> std::io::Result<()> {
205 Ok(())
206 }
207
208 fn eprintln(&self, _output: impl AsRef<str>) {}
209
210 async fn read(&self) -> std::io::Result<String> {
211 panic!("Unsupported operation")
212 }
213
214 async fn prompt(
215 &self,
216 _question: impl AsRef<str> + MaybeSend + MaybeSync,
217 ) -> String {
218 panic!("Unsupported operation")
219 }
220}
221
222#[cfg(not(target_family = "wasm"))]
225pub async fn prompt_aux<R, W>(
226 mut reader: R,
227 mut writer: W,
228 question: &str,
229) -> String
230where
231 R: tokio::io::AsyncReadExt + Unpin,
232 W: tokio::io::AsyncWriteExt + Unpin,
233{
234 writer
235 .write_all(question.as_bytes())
236 .await
237 .expect("Unable to write");
238 writer.flush().await.unwrap();
239 let mut s = String::new();
240 reader.read_to_string(&mut s).await.expect("Unable to read");
241 s
242}
243
244#[cfg(not(target_family = "wasm"))]
246pub async fn read_aux<R>(mut reader: R) -> tokio::io::Result<String>
247where
248 R: tokio::io::AsyncReadExt + Unpin,
249{
250 let mut s = String::new();
251 reader.read_to_string(&mut s).await?;
252 Ok(s)
253}
254
255#[macro_export]
258macro_rules! display {
259 ($io:expr) => {
260 $io.print("")
261 };
262 ($io:expr, $w:expr; $($args:tt)*) => {
263 $io.write($w, format_args!($($args)*).to_string())
264 };
265 ($io:expr,$($args:tt)*) => {
266 $io.print(format_args!($($args)*).to_string())
267 };
268}
269
270#[macro_export]
273macro_rules! display_line {
274 ($io:expr) => {
275 $io.println("")
276 };
277 ($io:expr, $w:expr; $($args:tt)*) => {
278 $io.writeln($w, format_args!($($args)*).to_string())
279 };
280 ($io:expr,$($args:tt)*) => {
281 $io.println(format_args!($($args)*).to_string())
282 };
283}
284
285#[macro_export]
288macro_rules! edisplay_line {
289 ($io:expr,$($args:tt)*) => {
290 $io.eprintln(format_args!($($args)*).to_string())
291 };
292}
293
294#[macro_export]
295macro_rules! prompt {
298 ($io:expr,$($arg:tt)*) => {{
299 $io.prompt(format!("{}", format_args!($($arg)*)))
300 }}
301}
302
303#[cfg_attr(feature = "async-send", async_trait::async_trait)]
304#[cfg_attr(not(feature = "async-send"), async_trait::async_trait(?Send))]
305pub trait NamadaIo: Sized + MaybeSync + MaybeSend {
306 type Client: Client + MaybeSend + Sync;
308 type Io: Io + MaybeSend + MaybeSync;
310
311 fn client(&self) -> &Self::Client;
313
314 fn io(&self) -> &Self::Io;
316}