Skip to content

Commit 940d4cc

Browse files
committed
Add a base64 command line tool.
1 parent 23106c3 commit 940d4cc

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ harness = false
1919
# 0.3.3 requires rust 1.36.0 for stable copied()
2020
criterion = "=0.3.2"
2121
rand = "0.6.1"
22+
structopt = "0.3"
2223

2324
[features]
2425
default = ["std"]

examples/base64.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use std::fs::File;
2+
use std::io::{self, Read};
3+
use std::path::PathBuf;
4+
use std::process;
5+
use std::str::FromStr;
6+
7+
use base64::{read, write};
8+
use structopt::StructOpt;
9+
10+
#[derive(Debug, StructOpt)]
11+
enum CharacterSet {
12+
Standard,
13+
UrlSafe,
14+
}
15+
16+
impl Default for CharacterSet {
17+
fn default() -> Self {
18+
CharacterSet::Standard
19+
}
20+
}
21+
22+
impl Into<base64::Config> for CharacterSet {
23+
fn into(self) -> base64::Config {
24+
match self {
25+
CharacterSet::Standard => base64::STANDARD,
26+
CharacterSet::UrlSafe => base64::URL_SAFE,
27+
}
28+
}
29+
}
30+
31+
impl FromStr for CharacterSet {
32+
type Err = String;
33+
fn from_str(s: &str) -> Result<CharacterSet, String> {
34+
match s {
35+
"standard" => Ok(CharacterSet::Standard),
36+
"urlsafe" => Ok(CharacterSet::UrlSafe),
37+
_ => Err(format!("charset '{}' unrecognized", s)),
38+
}
39+
}
40+
}
41+
42+
/// Base64 encode or decode FILE (or standard input), to standard output.
43+
#[derive(Debug, StructOpt)]
44+
struct Opt {
45+
/// decode data
46+
#[structopt(short = "d", long = "decode")]
47+
decode: bool,
48+
/// The character set to choose. Defaults to the standard base64 character set.
49+
/// Supported character sets include "standard" and "urlsafe".
50+
#[structopt(long = "charset")]
51+
charset: Option<CharacterSet>,
52+
/// The file to encode/decode.
53+
#[structopt(parse(from_os_str))]
54+
file: Option<PathBuf>,
55+
}
56+
57+
fn main() {
58+
let opt = Opt::from_args();
59+
let stdin;
60+
let mut input: Box<dyn Read> = match opt.file {
61+
None => {
62+
stdin = io::stdin();
63+
Box::new(stdin.lock())
64+
}
65+
Some(ref f) if f.as_os_str() == "-" => {
66+
stdin = io::stdin();
67+
Box::new(stdin.lock())
68+
}
69+
Some(f) => Box::new(File::open(f).unwrap()),
70+
};
71+
let config = opt.charset.unwrap_or_default().into();
72+
let stdout = io::stdout();
73+
let mut stdout = stdout.lock();
74+
let r = if opt.decode {
75+
let mut decoder = read::DecoderReader::new(&mut input, config);
76+
io::copy(&mut decoder, &mut stdout)
77+
} else {
78+
let mut encoder = write::EncoderWriter::new(&mut stdout, config);
79+
io::copy(&mut input, &mut encoder)
80+
};
81+
if let Err(e) = r {
82+
println!(
83+
"Base64 {} failed with {}",
84+
if opt.decode { "decode" } else { "encode" },
85+
e
86+
);
87+
process::exit(1);
88+
}
89+
}

0 commit comments

Comments
 (0)