base64.rs 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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. use base64::{alphabet, engine, read, write};
  7. use structopt::StructOpt;
  8. #[derive(Debug, StructOpt)]
  9. enum Alphabet {
  10. Standard,
  11. UrlSafe,
  12. }
  13. impl Default for Alphabet {
  14. fn default() -> Self {
  15. Self::Standard
  16. }
  17. }
  18. impl FromStr for Alphabet {
  19. type Err = String;
  20. fn from_str(s: &str) -> Result<Self, String> {
  21. match s {
  22. "standard" => Ok(Self::Standard),
  23. "urlsafe" => Ok(Self::UrlSafe),
  24. _ => Err(format!("alphabet '{}' unrecognized", s)),
  25. }
  26. }
  27. }
  28. /// Base64 encode or decode FILE (or standard input), to standard output.
  29. #[derive(Debug, StructOpt)]
  30. struct Opt {
  31. /// decode data
  32. #[structopt(short = "d", long = "decode")]
  33. decode: bool,
  34. /// The alphabet to choose. Defaults to the standard base64 alphabet.
  35. /// Supported alphabets include "standard" and "urlsafe".
  36. #[structopt(long = "alphabet")]
  37. alphabet: Option<Alphabet>,
  38. /// The file to encode/decode.
  39. #[structopt(parse(from_os_str))]
  40. file: Option<PathBuf>,
  41. }
  42. fn main() {
  43. let opt = Opt::from_args();
  44. let stdin;
  45. let mut input: Box<dyn Read> = match opt.file {
  46. None => {
  47. stdin = io::stdin();
  48. Box::new(stdin.lock())
  49. }
  50. Some(ref f) if f.as_os_str() == "-" => {
  51. stdin = io::stdin();
  52. Box::new(stdin.lock())
  53. }
  54. Some(f) => Box::new(File::open(f).unwrap()),
  55. };
  56. let alphabet = opt.alphabet.unwrap_or_default();
  57. let engine = engine::GeneralPurpose::new(
  58. &match alphabet {
  59. Alphabet::Standard => alphabet::STANDARD,
  60. Alphabet::UrlSafe => alphabet::URL_SAFE,
  61. },
  62. engine::general_purpose::PAD,
  63. );
  64. let stdout = io::stdout();
  65. let mut stdout = stdout.lock();
  66. let r = if opt.decode {
  67. let mut decoder = read::DecoderReader::new(&mut input, &engine);
  68. io::copy(&mut decoder, &mut stdout)
  69. } else {
  70. let mut encoder = write::EncoderWriter::new(&mut stdout, &engine);
  71. io::copy(&mut input, &mut encoder)
  72. };
  73. if let Err(e) = r {
  74. eprintln!(
  75. "Base64 {} failed with {}",
  76. if opt.decode { "decode" } else { "encode" },
  77. e
  78. );
  79. process::exit(1);
  80. }
  81. }