Convert hex to base64 (Cryptopals challenge 1) I've been spending some time learning Rust and I came across the Cryptopals Challenges.
This is my implementation of challenge 1


  Convert hex to base64 The string:

49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d

  
  Should produce:

SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t

  
  So go ahead and make that happen. You'll need to use this code for the
  rest of the exercises.
  
  Cryptopals Rule: Always operate on raw bytes, never on encoded strings. Only use hex and base64 for pretty-printing.


I did go ahead and pull in a crate for handling base64 encoding. It didn't seem important to implement that myself.

mod basics {
    extern crate base64;
    use self::base64::encode;

    pub fn hex_to_base64(hex: &amp;str) -&gt; String {
        encode(&amp;hex_to_bytes(hex))
    }

    pub fn hex_to_bytes(hex: &amp;str) -&gt; Vec&lt;u8&gt; {
        hex.chars()
            .collect::&lt;Vec&lt;_&gt;&gt;() //convert to slice-able
            .chunks(2)           //each char is one nibble
            .map(|byte| byte.iter().collect::&lt;String&gt;())
            .map(|byte| u8::from_str_radix(&amp;byte[..], 16).unwrap())
            .collect()
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn can_convert_hex_to_base64() {
            let hex_as_string =
                "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
            let base64_as_string =
                "SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t";

            assert_eq!(hex_to_base64(hex_as_string), base64_as_string);
        }

        #[test]
        fn ff_byte_hex_string_to_byte_vector() {
            let hex = "FF";
            assert_eq!(vec![0xFF], hex_to_bytes(hex));
        }

        #[test]
        fn single_byte_hex_string_to_byte_vector() {
            let hex = "2A";
            assert_eq!(vec![0x2A], hex_to_bytes(hex));
        }

        #[test]
        fn multibyte_hex_string_to_byte_vector() {
            let hex = "2ABE";
            assert_eq!(vec![0x2A, 0xBE], hex_to_bytes(hex));
        }
    }
}
pub fn hex_to_base64(hex: &amp;str) -&gt; String {
    encode(&amp;hex_to_bytes(hex))


I would not use self::base64::encode and instead refer to base64::encode here so that it is clearer what is being encoded.

}

pub fn hex_to_bytes(hex: &amp;str) -&gt; Vec&lt;u8&gt; {
    hex.chars()
        .collect::&lt;Vec&lt;_&gt;&gt;() //convert to slice-able


Given that you are doing hex, which is all in the ASCII range, you may want to use as_bytes() which will give you a slice of bytes without copying the whole string into a new Vec.

        .chunks(2)           //each char is one nibble


What happens if the string length isn't a multiple of two?

        .map(|byte| byte.iter().collect::&lt;String&gt;())


byte isn't correct here as it is a slice of chars. Further, if you don't use chars() as I suggest as above, you can use std::str::from_utf8 to get a &amp;str without allocating a new String.

        .map(|byte| u8::from_str_radix(&amp;byte[..], 16).unwrap())


byte really isn't correct here as you have a String.  Additionally, there is no need to take a slice.

        .collect()
}