b64_cli/
lib.rs

1use base64::{Engine as _, engine::general_purpose::STANDARD};
2
3pub fn encode_to_base64(input: &str) -> String {
4    STANDARD.encode(input)
5}
6
7pub fn decode_from_base64(input: &str) -> Result<Vec<u8>, base64::DecodeError> {
8    STANDARD.decode(input)
9}
10
11pub fn process_args(args: &[String]) -> String {
12    if is_arg_len_invalid(args) {
13        println!("Invalid number of arguments. Ex: b64 e hello");
14        return String::new();
15    }
16
17    let process = extract_process(args);
18    let input = extract_input(args);
19
20    let result = process_input(process, input);
21
22    println!("{}", result);
23    result
24}
25
26fn is_arg_len_invalid(args: &[String]) -> bool {
27    args.len() > 3 || args.len() < 2
28}
29
30fn extract_process(args: &[String]) -> &str {
31    args.get(1)
32        .expect("Missing process please enter encode or decode, or e or d. Ex: b64 e hello")
33        .trim()
34}
35
36fn extract_input(args: &[String]) -> &str {
37    args.get(2)
38        .expect("Missing input please enter a string to encode or decode")
39        .trim()
40}
41
42fn process_input(process: &str, input: &str) -> String {
43    if process == "decode" || process == "d" {
44        return match decode_from_base64(input) {
45            Ok(bytes) => String::from_utf8_lossy(&bytes).to_string(),
46            Err(err) => {
47                println!("Error: {}", err);
48                panic!("Invalid base64 input");
49            }
50        };
51    } else if process == "encode" || process == "e" {
52        return encode_to_base64(input);
53    }
54    eprintln!("Invalid process");
55    String::new()
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_encode() {
64        let input = "hello";
65        let output = encode_to_base64(input);
66        assert_eq!(output, "aGVsbG8=");
67    }
68
69    #[test]
70    fn test_decode() {
71        let input = "aGVsbG8=";
72        let output = decode_from_base64(input).unwrap();
73        assert_eq!(String::from_utf8_lossy(&output), "hello");
74    }
75
76    #[test]
77    fn test_decode_error() {
78        let input = "aGVsbG8";
79        let output = decode_from_base64(input);
80        assert!(output.is_err());
81    }
82    #[test]
83    fn test_is_arg_len_invalid() {
84        let args = vec![
85            "hello".to_string(),
86            "yo".to_string(),
87            "b".to_string(),
88            "s".to_string(),
89        ];
90        assert!(is_arg_len_invalid(&args));
91    }
92
93    #[test]
94    fn test_extract_process() {
95        let args = vec!["b64".to_string(), "encode".to_string(), "hello".to_string()];
96        let output = extract_process(&args);
97        assert_eq!(output, "encode");
98    }
99
100    #[test]
101    #[should_panic(
102        expected = "Missing process please enter encode or decode, or e or d. Ex: b64 e hello"
103    )]
104    fn test_extract_process_error() {
105        let args = vec!["hello".to_string()];
106        let output = extract_process(&args);
107        assert_eq!(output, "invalid");
108    }
109
110    #[test]
111    fn test_extract_input() {
112        let args = vec!["b64".to_string(), "encode".to_string(), "hello".to_string()];
113        let output = extract_input(&args);
114        assert_eq!(output, "hello");
115    }
116
117    #[test]
118    #[should_panic(expected = "Missing input please enter a string to encode or decode")]
119    fn test_extract_input_error() {
120        let args = vec!["b64".to_string(), "encode".to_string()];
121        extract_input(&args);
122    }
123}