rustutils_base64/
lib.rs

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/// Base64 encode or decode a file, or standard input, to standard output.
10#[derive(Parser, Clone, Debug)]
11#[clap(author, version, about, long_about = None)]
12pub struct Base64 {
13    /// Wrap encoded lines after COLS characters.
14    #[clap(long, short, default_value = "76")]
15    wrap: u16,
16    /// Don't perform any wrapping.
17    #[clap(long, short, conflicts_with = "wrap")]
18    no_wrap: bool,
19    /// Decode data rather than encoding.
20    #[clap(long, short)]
21    decode: bool,
22    /// When decoding, ignore non-alphabet characters.
23    #[clap(long, short, requires = "decode")]
24    ignore_garbage: bool,
25    /// File to encode or decode.
26    ///
27    /// When omitted, standard input is read instead.
28    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}