The base64 decode algorithm is taken directly from Base64 wiki page. This exercise is meant to help me learn Rust, so any pointers in that general direction are very welcome. :)
fn main() {
println!("{}",
hex_to_base64("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d"));
}
fn hex_to_base64(hex_string: &str) -> String {
println!("Converting {} from hex to base64", hex_string);
let alphabet: Vec<char> =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".chars().collect();
// Decode the input string from hex into individual bytes
let input_chars: Vec<char> = hex_string.chars().collect();
let mut decoded_bytes: Vec<u8> = Vec::new();
for i in 0..hex_string.len() {
if i % 2 != 0 { continue }
let first_byte = input_chars[i].to_digit(16).unwrap() as u8;
let second_byte = input_chars[i + 1].to_digit(16).unwrap() as u8;
println!("Decoding 0x{}{} to bytes:", input_chars[i], input_chars[i + 1]);
let byte = (first_byte << 4) | second_byte;
println!(" {}", byte);
decoded_bytes.push(byte)
}
// Encode the decoded bytes into Base64
let mut output = String::from("");
let mut b: u8;
for i in 0..decoded_bytes.len() {
if i % 3 != 0 { continue }
b = (decoded_bytes[i] & 0xFC) >> 2;
output.push(alphabet[b as usize]);
b = (decoded_bytes[i] & 0x03) << 4;
if i + 1 < decoded_bytes.len() {
b |= (decoded_bytes[i + 1] & 0xF0) >> 4;
output.push(alphabet[b as usize]);
b = (decoded_bytes[i + 1] & 0x0F) << 2;
if i + 2 < decoded_bytes.len() {
b |= (decoded_bytes[i + 2] & 0xC0) >> 6;
output.push(alphabet[b as usize]);
b = decoded_bytes[i + 2] & 0x3F;
output.push(alphabet[b as usize]);
} else {
output.push(alphabet[b as usize]);
output.push('=');
}
} else {
output.push(alphabet[b as usize]);
output.push_str("==");
}
}
return output
}
#[test]
fn test_hex_to_base64() {
assert!(hex_to_base64("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d") == String::from("SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t"));
}