Skip to content

Commit 75f29a0

Browse files
authored
feat: allow cli/ tool to read data from stdin (#108)
Read data from stdin if no '-i' argument is given This is especially useful for binary data, which may not survive in an argument list (e.g. due to the presence of NUL bytes). The 'encode' and 'decode' commands are now exact inverses of each other, so data will roundtrip correctly, e.g. $ echo "hello world" | ./multibase encode | ./multibase decode hello world $ echo "hello world" | ./multibase encode | ./multibase decode | ./multibase encode z2yGEbwRFyhPZZckJm $ echo "hello world" | ./multibase encode z2yGEbwRFyhPZZckJm Also avoid extra newlines, or additions like "Result: ", since they make the command less useful.
1 parent ea6c3a9 commit 75f29a0

File tree

1 file changed

+30
-9
lines changed

1 file changed

+30
-9
lines changed

cli/main.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::fmt;
2+
use std::io::{self, Read, Write};
23
use std::str::FromStr;
34

45
use anyhow::{anyhow, Error, Result};
@@ -19,24 +20,44 @@ enum Mode {
1920
/// The base to use for encoding.
2021
#[structopt(short = "b", long = "base", default_value = "base58btc")]
2122
base: StrBase,
22-
/// The data need to be encoded.
23+
/// The data to encode. Reads from stdin if not provided.
2324
#[structopt(short = "i", long = "input")]
24-
input: String,
25+
input: Option<String>,
2526
},
2627
#[structopt(name = "decode")]
2728
Decode {
28-
/// The data need to be decoded.
29+
/// The data to decode. Reads from stdin if not provided.
2930
#[structopt(short = "i", long = "input")]
30-
input: String,
31+
input: Option<String>,
3132
},
3233
}
3334

3435
fn main() -> Result<()> {
3536
env_logger::init();
3637
let opts = Opts::from_args();
3738
match opts.mode {
38-
Mode::Encode { base, input } => encode(base, input.as_bytes()),
39-
Mode::Decode { input } => decode(&input),
39+
Mode::Encode { base, input } => {
40+
let input_bytes = match input {
41+
Some(s) => s.into_bytes(),
42+
None => {
43+
let mut buf = Vec::new();
44+
io::stdin().read_to_end(&mut buf)?;
45+
buf
46+
}
47+
};
48+
encode(base, &input_bytes)
49+
}
50+
Mode::Decode { input } => {
51+
let input_str = match input {
52+
Some(s) => s,
53+
None => {
54+
let mut buf = String::new();
55+
io::stdin().read_to_string(&mut buf)?;
56+
buf
57+
}
58+
};
59+
decode(&input_str)
60+
}
4061
}
4162
}
4263

@@ -119,13 +140,13 @@ impl From<StrBase> for Base {
119140
fn encode(base: StrBase, input: &[u8]) -> Result<()> {
120141
log::debug!("Encode {:?} with {}", input, base);
121142
let result = multibase::encode(base.into(), input);
122-
println!("Result: {}", result);
143+
print!("{}", result);
123144
Ok(())
124145
}
125146

126147
fn decode(input: &str) -> Result<()> {
127148
log::debug!("Decode {:?}", input);
128-
let (base, result) = multibase::decode(input)?;
129-
println!("Result: {}, {:?}", StrBase(base), result);
149+
let (_, result) = multibase::decode(input)?;
150+
io::stdout().write_all(&result)?;
130151
Ok(())
131152
}

0 commit comments

Comments
 (0)