Make the damn hex methods work -- fuck
This commit is contained in:
parent
9c6c5c8ac6
commit
e0adca798a
1 changed files with 116 additions and 6 deletions
122
src/hex.rs
122
src/hex.rs
|
@ -111,16 +111,126 @@ impl<'a> AsHexBytes<'a> for &'a str {
|
|||
fn hex_bytes(&self) -> HexBytes<'a> { HexBytes::new(self) }
|
||||
}
|
||||
|
||||
//pub trait HexDecodable {
|
||||
// fn hex_decoded(self) -> Option<Vec<u8>>;
|
||||
//}
|
||||
//
|
||||
//impl<'a> HexDecodable for &'a str {
|
||||
// fn hex_decoded(self) -> Option<Vec<u8>> {
|
||||
// fn valid(ch: &&str) -> bool { ch.chars().all(|c| c.is_digit(16)) }
|
||||
// fn decode(ch: &str) -> u8 { ch.chars().fold(0u8, |acc, c| (acc << 4) + c.to_digit(16).unwrap() as u8) }
|
||||
// self.splitn(2, "")
|
||||
// .take_while(valid)
|
||||
// .map(decode)
|
||||
// .collect::<Vec<u8>>()
|
||||
// }
|
||||
//}
|
||||
|
||||
pub trait HexDecodable<T> {
|
||||
fn hex_decoded(self) -> HexDecoder<T>;
|
||||
}
|
||||
|
||||
pub struct HexDecoder<T> {
|
||||
input: T,
|
||||
}
|
||||
|
||||
impl<T> HexDecoder<T> {
|
||||
pub fn new(input: T) -> HexDecoder<T> {
|
||||
HexDecoder { input: input }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator for HexDecoder<T> where T: Iterator<Item=char> + 'a {
|
||||
type Item = u8;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let c0 = match self.input.next() {
|
||||
Some(ch) => match ch.to_digit(16) {
|
||||
Some(digit) => digit as u8,
|
||||
None => return None
|
||||
},
|
||||
None => return None
|
||||
};
|
||||
|
||||
let c1 = match self.input.next() {
|
||||
Some(ch) => match ch.to_digit(16) {
|
||||
Some(digit) => Some(digit as u8),
|
||||
None => return None
|
||||
},
|
||||
None => None
|
||||
};
|
||||
|
||||
let out_char = if let Some(c1) = c1 {
|
||||
(c0 << 4) + (c1 & 0x0F)
|
||||
} else {
|
||||
c0 & 0x0F
|
||||
};
|
||||
|
||||
Some(out_char)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> HexDecodable<T> for T where T: Iterator<Item=char> + 'a {
|
||||
fn hex_decoded(self) -> HexDecoder<T> { HexDecoder::new(self) }
|
||||
}
|
||||
|
||||
pub trait HexEncodable<T> {
|
||||
fn hex_encoded(self) -> HexEncoder<T>;
|
||||
}
|
||||
|
||||
pub struct HexEncoder<T> {
|
||||
input: T,
|
||||
current_byte: u8,
|
||||
}
|
||||
|
||||
impl<T> HexEncoder<T> {
|
||||
pub fn new(input: T) -> HexEncoder<T> {
|
||||
HexEncoder { input: input, current_byte: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator for HexEncoder<T> where T: Iterator<Item=u8> + 'a {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.current_byte == 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);
|
||||
}
|
||||
None => return None
|
||||
}
|
||||
}
|
||||
// Convert the lowest order nibble to a hex digit.
|
||||
match char::from_digit((self.current_byte & 0xF) as u32, 16) {
|
||||
Some(ch) => {
|
||||
self.current_byte = self.current_byte >> 4;
|
||||
return Some(ch);
|
||||
},
|
||||
None => panic!("This will never happen???")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> HexEncodable<T> for T where T: Iterator<Item=u8> + 'a {
|
||||
fn hex_encoded(self) -> HexEncoder<T> { HexEncoder::new(self) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn simple() {
|
||||
let collected: Vec<u8> = "123".hex_bytes().map(|c| match c {
|
||||
HexResult::Byte(c) => c,
|
||||
_ => panic!(),
|
||||
}).collect();
|
||||
assert_eq!(collected, vec![1, 2, 3]);
|
||||
fn simple_encode() {
|
||||
let collected: String = "123".bytes().hex_encoded().collect();
|
||||
assert_eq!(collected, "313233");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_decode() {
|
||||
let decoded: Vec<u8> = "313233".chars().hex_decoded().collect();
|
||||
assert_eq!(decoded, vec![0x31u8, 0x32u8, 0x33u8]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue