dev_kit/command/
base64.rs

1use crate::command::StringInput;
2use base64::Engine;
3use itertools::Itertools;
4use std::path::PathBuf;
5
6#[derive(clap::Subcommand)]
7pub enum Base64Command {
8    #[clap(about = "base64 decode, alias 'd'", alias = "d")]
9    Decode {
10        #[arg(help = "base64 text to decode", default_value = "")]
11        input: StringInput,
12        #[arg(short, long, help = "url safe", default_value = "false")]
13        url_safe: bool,
14        #[arg(short, long, help = "no padding", default_value = "false")]
15        no_pad: bool,
16        #[arg(short, long, help = "raw output", default_value = "false")]
17        raw_output: bool,
18        #[arg(short, long, help = "file to write output")]
19        file: Option<PathBuf>,
20    },
21    #[clap(about = "base64 encode, alias 'e'", alias = "e")]
22    Encode {
23        #[arg(help = "base64 text to decode", default_value = "")]
24        input: StringInput,
25        #[arg(short, long, help = "url safe", default_value = "false")]
26        url_safe: bool,
27        #[arg(short, long, help = "no padding", default_value = "false")]
28        no_pad: bool,
29        #[arg(short, long, help = "file to write output")]
30        file: Option<PathBuf>,
31    },
32}
33
34pub fn decode(text: &str, url_safe: bool, no_pad: bool) -> crate::Result<Vec<u8>> {
35    if url_safe {
36        if no_pad {
37            base64::prelude::BASE64_URL_SAFE.decode(text.as_bytes())
38        } else {
39            base64::prelude::BASE64_URL_SAFE_NO_PAD.decode(text.as_bytes())
40        }
41    } else {
42        if no_pad {
43            base64::prelude::BASE64_STANDARD_NO_PAD.decode(text.as_bytes())
44        } else {
45            base64::prelude::BASE64_STANDARD.decode(text.as_bytes())
46        }
47    }.map_err(|e| anyhow::anyhow!("base64 encode failed: {}", e))
48}
49
50pub fn encode(data: &[u8], url_safe: bool, no_pad: bool) -> crate::Result<String> {
51    let string = if url_safe {
52        if no_pad {
53            base64::prelude::BASE64_URL_SAFE.encode(data)
54        } else {
55            base64::prelude::BASE64_URL_SAFE_NO_PAD.encode(data)
56        }
57    } else {
58        if no_pad {
59            base64::prelude::BASE64_STANDARD_NO_PAD.encode(data)
60        } else {
61            base64::prelude::BASE64_STANDARD.encode(data)
62        }
63    };
64    Ok(string)
65}
66
67pub enum Base64Val {
68    EncodeString(String),
69    DecodeBytes(Vec<u8>),
70}
71
72impl super::Command for Base64Command {
73    fn run(&self) -> crate::Result<()> {
74        match self {
75            Self::Decode { input, url_safe, no_pad, raw_output, file } => {
76                let data = decode(input, *url_safe, *no_pad)?;
77                match (*raw_output, file) {
78                    (false, None) => {
79                        let text = String::from_utf8_lossy(&data);
80                        println!("{}", text);
81                    }
82                    (true, None) => {
83                        let text = data.chunks(8).flatten().map(|it| {
84                            format!("{:02x} ", *it)
85                        }).join("\n");
86                        println!("{}", text);
87                    }
88                    (false, Some(file)) => {
89                        let text = String::from_utf8_lossy(&data).to_string();
90                        let _ = std::fs::write(file, text)?;
91                        println!("write to {}", file.display())
92                    }
93                    (true, Some(file)) => {
94                        let _ = std::fs::write(file, data)?;
95                        println!("write to {}", file.display())
96                    }
97                }
98            }
99            Self::Encode { input, url_safe, no_pad, file } => {
100                let text = encode(input.as_bytes(), *url_safe, *no_pad)?;
101                if let Some(file) = file {
102                    let _ = std::fs::write(file, text)?;
103                    println!("write to {}", file.display())
104                } else {
105                    println!("{}", text);
106                }
107            }
108        }
109        Ok(())
110    }
111}
112
113