Fix the hex encoder
This commit is contained in:
parent
3db9fd5dab
commit
589efa5ad6
1 changed files with 33 additions and 2 deletions
35
src/hex.rs
35
src/hex.rs
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue