diff --git a/src/hex.rs b/src/hex.rs index 2d64da8..b9118df 100644 --- a/src/hex.rs +++ b/src/hex.rs @@ -55,11 +55,12 @@ pub trait HexEncodable { pub struct HexEncoder { input: T, current_byte: u8, + num_nibbles: u8, } impl HexEncoder { pub fn new(input: T) -> HexEncoder { - HexEncoder { input: input, current_byte: 0 } + HexEncoder { input: input, current_byte: 0, num_nibbles: 0 } } } @@ -67,12 +68,13 @@ impl<'a, T> Iterator for HexEncoder where T: Iterator + 'a { type Item = char; fn next(&mut self) -> Option { - if self.current_byte == 0 { + if self.num_nibbles == 0 { // Get a new byte. match self.input.next() { Some(byte) => { // Swap the order of the nibbles to make the code below nicer. self.current_byte = (byte << 4) + (byte >> 4); + self.num_nibbles = 2; } None => return None } @@ -81,6 +83,7 @@ impl<'a, T> Iterator for HexEncoder where T: Iterator + 'a { match char::from_digit((self.current_byte & 0xF) as u32, 16) { Some(ch) => { self.current_byte = self.current_byte >> 4; + self.num_nibbles -= 1; return Some(ch); }, None => panic!("This will never happen???") @@ -107,4 +110,32 @@ mod tests { let decoded: Vec = "313233".chars().hex_decoded().collect(); assert_eq!(decoded, vec![0x31u8, 0x32u8, 0x33u8]); } + + #[test] + fn cryptopals12_decode() { + let a = "1c0111001f010100061a024b53535009181c"; + let out: Vec = a.chars().hex_decoded().collect(); + assert_eq!(out, vec![0x1c, 0x01, 0x11, 0x00, 0x1f, 0x01, 0x01, 0x00, + 0x06, 0x1a, 0x02, 0x4b, 0x53, 0x53, 0x50, 0x09, + 0x18, 0x1c]); + } + + #[test] + fn each_byte_encodes_to_two_characters() { + let input: String = vec![0x06].into_iter().hex_encoded().collect(); + assert_eq!(input, "06"); + + // This was an actual bug, the last nibble was getting eaten. :( + let input: String = vec![0x20].into_iter().hex_encoded().collect(); + assert_eq!(input, "20"); + } + + #[test] + fn reciprocity_of_encode_and_decode() { + let input = "746865206b"; + let output: String = input.chars() + .hex_decoded().inspect(|x| println!("{:08b}", x)) + .hex_encoded().collect(); + assert_eq!(input, output); + } }