diff --git a/rust/radix204/src/base16.rs b/rust/radix204/src/base16.rs new file mode 100644 --- /dev/null +++ b/rust/radix204/src/base16.rs @@ -0,0 +1,73 @@ +// Copyright 2017 Facebook, Inc. +// +// This software may be used and distributed according to the terms of the +// GNU General Public License version 2 or any later version. + +//! Base16 iterators + +pub trait ToBase16Iter<'a, T> { + fn to_base16iter(&'a self) -> T; +} + +impl<'a, T: AsRef<[u8]>> ToBase16Iter<'a, SliceBase16Iter<'a, T>> for T { + #[inline] + fn to_base16iter(&'a self) -> SliceBase16Iter<'a, T> { SliceBase16Iter(self, 0) } +} + +/// Base16 iterator for [u8] +pub struct SliceBase16Iter<'a, T: 'a>(&'a T, usize); + +impl<'a, T: AsRef<[u8]>> Iterator for SliceBase16Iter<'a, T> { + type Item = u8; + + #[inline] + fn next(&mut self) -> Option { + let i = self.1; + match self.0.as_ref().get(i / 2) { + Some(v) => { + self.1 += 1; + if i & 1 == 0 { v >> 4 } else { v & 0xf }.into() + } + None => None, + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.0.as_ref().len() * 2 - self.1; + (len, Some(len)) + } + + #[inline] + fn count(self) -> usize { self.0.as_ref().len() * 2 } +} + +#[cfg(test)] +mod tests { + use super::*; + use types::Key; + use test::Bencher; + + // rustfmt makes code much longer + #[test] + #[cfg_attr(rustfmt, rustfmt_skip)] + fn test_key() { + let x: Key = [ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xde, 0xef, 0xfa, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa5, 0x00, 0x91, 0x92, 0x93, 0x56].into(); + assert_eq!(x.to_base16iter().count(), 40); + let y: Vec = x.to_base16iter().collect(); + assert_eq!(y, vec![ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 13, 14, 14, 15, 15, 10, 10, 1, 10, 2, 10, + 3, 10, 4, 10, 5, 0, 0, 9, 1, 9, 2, 9, 3, 5, 6]); + } + + #[bench] + fn bench_key_base64(b: &mut Bencher) { + let x: Key = [4u8; 20].into(); // change 20 to Key::len() when const fn is stable + b.iter(|| { + let y: u8 = x.to_base16iter().sum(); + assert_eq!(y, 4 * Key::fixed_len() as u8); + }) + } +} diff --git a/rust/radix204/src/lib.rs b/rust/radix204/src/lib.rs --- a/rust/radix204/src/lib.rs +++ b/rust/radix204/src/lib.rs @@ -22,3 +22,4 @@ pub mod types; pub mod errors; +pub mod base16;