Fix the hex encoder

This commit is contained in:
Eryn Wells 2018-03-31 16:15:56 -07:00
parent 3db9fd5dab
commit 589efa5ad6

View file

@ -55,11 +55,12 @@ pub trait HexEncodable<T> {
pub struct HexEncoder<T> { pub struct HexEncoder<T> {
input: T, input: T,
current_byte: u8, current_byte: u8,
num_nibbles: u8,
} }
impl<T> HexEncoder<T> { impl<T> HexEncoder<T> {
pub fn new(input: T) -> HexEncoder<T> { pub fn new(input: T) -> HexEncoder<T> {
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<T> where T: Iterator<Item=u8> + 'a {
type Item = char; type Item = char;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.current_byte == 0 { if self.num_nibbles == 0 {
// Get a new byte. // Get a new byte.
match self.input.next() { match self.input.next() {
Some(byte) => { Some(byte) => {
// Swap the order of the nibbles to make the code below nicer. // Swap the order of the nibbles to make the code below nicer.
self.current_byte = (byte << 4) + (byte >> 4); self.current_byte = (byte << 4) + (byte >> 4);
self.num_nibbles = 2;
} }
None => return None None => return None
} }
@ -81,6 +83,7 @@ impl<'a, T> Iterator for HexEncoder<T> where T: Iterator<Item=u8> + 'a {
match char::from_digit((self.current_byte & 0xF) as u32, 16) { match char::from_digit((self.current_byte & 0xF) as u32, 16) {
Some(ch) => { Some(ch) => {
self.current_byte = self.current_byte >> 4; self.current_byte = self.current_byte >> 4;
self.num_nibbles -= 1;
return Some(ch); return Some(ch);
}, },
None => panic!("This will never happen???") None => panic!("This will never happen???")
@ -107,4 +110,32 @@ mod tests {
let decoded: Vec<u8> = "313233".chars().hex_decoded().collect(); let decoded: Vec<u8> = "313233".chars().hex_decoded().collect();
assert_eq!(decoded, vec![0x31u8, 0x32u8, 0x33u8]); assert_eq!(decoded, vec![0x31u8, 0x32u8, 0x33u8]);
} }
#[test]
fn cryptopals12_decode() {
let a = "1c0111001f010100061a024b53535009181c";
let out: Vec<u8> = 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);
}
} }