• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
default() -> Self17     fn default() -> Self {
18         CharacterSet::Standard
19     }
20 }
21 
22 impl Into<base64::Config> for CharacterSet {
into(self) -> base64::Config23     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;
from_str(s: &str) -> Result<CharacterSet, 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 
main()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         eprintln!(
83             "Base64 {} failed with {}",
84             if opt.decode { "decode" } else { "encode" },
85             e
86         );
87         process::exit(1);
88     }
89 }
90