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