1use base64_stream::{FromBase64Reader, ToBase64Reader};
2use clap::Parser;
3use rustutils_runnable::Runnable;
4use std::error::Error;
5use std::fs::File;
6use std::io::Read;
7use std::path::PathBuf;
8
9#[derive(Parser, Clone, Debug)]
11#[clap(author, version, about, long_about = None)]
12pub struct Base64 {
13 #[clap(long, short, default_value = "76")]
15 wrap: u16,
16 #[clap(long, short, conflicts_with = "wrap")]
18 no_wrap: bool,
19 #[clap(long, short)]
21 decode: bool,
22 #[clap(long, short, requires = "decode")]
24 ignore_garbage: bool,
25 file: Option<PathBuf>,
29}
30
31impl Base64 {
32 pub fn wrapping(&self) -> Option<u16> {
33 if self.no_wrap || self.wrap == 0 {
34 None
35 } else {
36 Some(self.wrap)
37 }
38 }
39
40 pub fn run(&self) -> Result<(), Box<dyn Error>> {
41 let input: Box<dyn Read> = match &self.file {
42 Some(file) if file.as_os_str() != "-" => Box::new(File::open(file)?),
43 _ => Box::new(std::io::stdin()),
44 };
45 match self.decode {
46 false => self.encode(input)?,
47 true => self.decode(input)?,
48 }
49 Ok(())
50 }
51
52 pub fn encode(&self, stream: Box<dyn Read>) -> Result<(), Box<dyn Error>> {
53 let mut encoder = ToBase64Reader::new(stream);
54 let mut stdout = std::io::stdout();
55 std::io::copy(&mut encoder, &mut stdout)?;
56 Ok(())
57 }
58
59 pub fn decode(&self, stream: Box<dyn Read>) -> Result<(), Box<dyn Error>> {
60 let mut encoder = FromBase64Reader::new(stream);
61 let mut stdout = std::io::stdout();
62 std::io::copy(&mut encoder, &mut stdout)?;
63 Ok(())
64 }
65}
66
67impl Runnable for Base64 {
68 fn run(&self) -> Result<(), Box<dyn Error>> {
69 self.run()?;
70 Ok(())
71 }
72}