base64_easy/
base64.rs

1use std::{char, str};
2
3pub fn decode(s: String) -> Result<String, String> {
4    let s = s.trim_end_matches('=');
5    let mut result = String::from("");
6    for c in s.chars() {
7        let maped_c = base64decode_map(c);
8        result.push_str(&format!("{:06b}", maped_c));
9    }
10    let loop_t = result.len() / 8;
11    let len = &loop_t * 8;
12    let binary = &result[..len];
13
14    let mut n = 1;
15    let mut vec = Vec::new();
16    while n <= loop_t {
17        let slice = &binary[(8 * (n - 1))..(8 * n)];
18        let intval = u8::from_str_radix(slice, 2).unwrap();
19        vec.push(intval);
20        n += 1;
21    }
22    Ok(str::from_utf8(&vec).map_err(|e| e.to_string())?.to_owned())
23}
24
25pub fn encode(s: String) -> String {
26    let chars = s.as_bytes();
27    let mut b = String::from("");
28    for x in chars {
29        b.push_str(&format!("{:08b}", x));
30    }
31    let len = b.len();
32    let mut loop_t = len / 6;
33    let remainder = len % 6;
34    if remainder != 0 {
35        b.push_str(&format!("{n:>0width$}", n = 0, width = (6 - remainder)));
36        loop_t += 1;
37    }
38    let mut result = String::from("");
39    let mut n = 1;
40    while n <= loop_t {
41        let slice = &b[(6 * (n - 1))..(6 * n)];
42        let intval = u8::from_str_radix(slice, 2).unwrap();
43        result.push_str(&base64encode_map(intval));
44        n += 1;
45    }
46
47    if remainder == 2 {
48        result.push_str("==");
49    } else if remainder == 4 {
50        result.push_str("=");
51    }
52    result
53}
54
55fn base64encode_map(index: u8) -> String {
56    let mut offset = 0;
57    if index < 26 {
58        offset = 65;
59    } else if index >= 26 && index < 52 {
60        offset = 97 - 26;
61    } else if index >= 52 && index < 62 {
62        offset = 80 - 52;
63    } else if index == 62 {
64        return "+".to_owned();
65    } else if index == 63 {
66        return "/".to_owned();
67    }
68    let result = format!("{}", (index + offset) as char);
69    result
70}
71
72fn base64decode_map(s: char) -> u8 {
73    if s == '+' {
74        62
75    } else if s == '/' {
76        63
77    } else {
78        let c = format!("{}", s as u8).parse::<u8>().unwrap();
79        if c >= 65 && c < 91 {
80            return c - 65;
81        } else if c >= 97 && c < 123 {
82            return c - 71;
83        } else if c >= 80 && c < 90 {
84            return c - 28;
85        }
86        return 0;
87    }
88}
89
90#[cfg(test)]
91mod test {
92    use super::*;
93    #[test]
94    fn test_encode() {
95        let input = String::from("Ma");
96        let output = encode(input);
97        assert_eq!("TWE=".to_string(), output);
98    }
99
100    #[test]
101    fn test_decode() {
102        let input = String::from("TWE=");
103        let output = decode(input);
104        assert_eq!("Ma".to_string(), output.unwrap());
105    }
106}