use base64_const::{base64_decode, url_safe_util::{from_url_safe, to_url_safe}};
enum Command {
Encode(String),
EncodeBytes(Vec<u8>),
Decode(String),
EncodeUrlSafe(String),
DecodeUrlSafe(String),
ToUrlSafe(String),
FromUrlSafe(String),
}
fn main() {
const DECODED: &[u8] = &base64_decode!("TWE=");
assert_eq!(DECODED, b"Ma");
const LONG_DECODED: &[u8] = &base64_decode!("TWFu");
assert_eq!(LONG_DECODED, b"Man");
let command = args_to_command();
match command {
Command::Encode(value) => {
println!("base64 encoding \"{}\"", &value);
println!("encoded > {}", base64_const::encode(value.as_bytes()));
},
Command::EncodeBytes(bytes) => {
println!("base64 encoding hex({}) \"{:02x?}\"", bytes.len(), &bytes);
println!("encoded > {}", base64_const::encode(&bytes));
},
Command::Decode(value) => {
println!("base64 decoding \"{}\"", &value);
let result = base64_const::decode(value.as_bytes());
println!("decode bytes > ({}) [{}]", result.len(), bytes_to_hex_string(&result));
match std::str::from_utf8(&result) {
Ok(result) => println!("decode utf8 > {}", result),
Err(err) => println!("decode utf8 > failed, {}", err),
}
},
Command::EncodeUrlSafe(value) => {
println!("base64 Url-safe encoding \"{}\"", &value);
println!("encoded > {}", to_url_safe(base64_const::encode(value.as_bytes())));
},
Command::DecodeUrlSafe(value) => {
println!("base64 decoding \"{}\"", &value);
let result = base64_const::decode(from_url_safe(value).as_bytes());
println!("decode bytes > ({}) [{}]", result.len(), bytes_to_hex_string(&result));
match std::str::from_utf8(&result) {
Ok(result) => println!("decode utf8 > {}", result),
Err(err) => println!("decode utf8 > failed, {}", err),
}
},
Command::ToUrlSafe(value) => {
println!("Url safe > {}", to_url_safe(value));
},
Command::FromUrlSafe(value) => {
println!("Url Unsafe > {}", from_url_safe(value));
}
}
}
const DEFAULT_MSG:&str = " cargo run -- -e <string> : encode
cargo run -- -b <string> : encode bytes
cargo run -- -d <string> : decode
cargo run -- -se <string> : encode url safe
cargo run -- -sd <string> : decode url-safe
cargo run -- --to_url-safe <string> : convert to url safe
cargo run -- --from-url-safe <string> : convert from urlsafe";
fn args_to_command() -> Command{
let args = std::env::args().skip(1).collect::<Vec<_>>();
if args.len() == 0 {
panic!("{}", DEFAULT_MSG);
};
if args.len() > 1 && (args[0] == "e" || args[0] == "-e") {
Command::Encode(args[1].clone())
}
else if args.len() > 1 && (args[0] == "b" || args[0] == "-b") {
Command::EncodeBytes(parse_bytes(&args[1]))
}
else if args.len() > 1 && (args[0] == "d" || args[0] == "-d") {
Command::Decode(args[args.len() - 1].clone())
}
else if args.len() > 1 && (args[0] == "--se") {
Command::EncodeUrlSafe(args[args.len() - 1].clone())
}
else if args.len() > 1 && (args[0] == "--sd") {
Command::DecodeUrlSafe(args[args.len() - 1].clone())
}
else if args.len() > 1 && (args[0] == "--to-url-safe") {
Command::ToUrlSafe(args[args.len() - 1].clone())
}
else if args.len() > 1 && (args[0] == "--from-url-safe") {
Command::FromUrlSafe(args[args.len() - 1].clone())
}
else {
panic!("{}", DEFAULT_MSG)
}
}
fn parse_bytes(s:&str) -> Vec<u8>{
s.trim_start_matches("[").trim_end_matches("]")
.split(",")
.map(|item|u8::from_str_radix(item.trim().trim_start_matches("0x"), 16))
.collect::<Result<Vec<_>, _>>().expect("can't parse bytes array")
}
fn bytes_to_hex_string(bytes:&[u8]) -> String{
bytes.iter().map(|i|format!("{:#04x}", i)).collect::<Vec<_>>().join(", ")
}