dev_kit/command/
base64.rs1use 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