use rand::distributions::uniform::Uniform;
use rand::distributions::Distribution;
use rand::Rng;
pub fn smallest_number_in_n_byte_varint(byte_length: usize) -> u64 {
assert!(byte_length <= 9 && byte_length >= 1);
match byte_length {
1 => 0,
_ => largest_number_in_n_byte_varint(byte_length - 1) + 1,
}
}
pub fn largest_number_in_n_byte_varint(byte_length: usize) -> u64 {
assert!(byte_length <= 9 && byte_length >= 1);
match byte_length {
9 => u64::max_value(),
_ => largest_number_in_7_bit_chunk(byte_length - 1),
}
}
fn largest_number_in_7_bit_chunk(chunk_index: usize) -> u64 {
assert!(chunk_index <= 7);
let lower_bits = match chunk_index {
0 => 0,
_ => largest_number_in_7_bit_chunk(chunk_index - 1),
};
let this_chunk = 0x7F_u64 << (chunk_index * 7);
lower_bits | this_chunk
}
pub struct RandomVarintEncodedLengthIter<R: Rng> {
ranges: [Uniform<u64>; 9],
range_for_picking_range: Uniform<usize>,
rng: R,
}
impl<R: Rng> RandomVarintEncodedLengthIter<R> {
pub fn new(rng: R) -> RandomVarintEncodedLengthIter<R> {
RandomVarintEncodedLengthIter {
ranges: [
Uniform::new(
smallest_number_in_n_byte_varint(1),
largest_number_in_n_byte_varint(1) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(2),
largest_number_in_n_byte_varint(2) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(3),
largest_number_in_n_byte_varint(3) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(4),
largest_number_in_n_byte_varint(4) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(5),
largest_number_in_n_byte_varint(5) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(6),
largest_number_in_n_byte_varint(6) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(7),
largest_number_in_n_byte_varint(7) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(8),
largest_number_in_n_byte_varint(8) + 1,
),
Uniform::new(
smallest_number_in_n_byte_varint(9),
largest_number_in_n_byte_varint(9),
),
],
range_for_picking_range: Uniform::new(0, 9),
rng,
}
}
}
impl<R: Rng> Iterator for RandomVarintEncodedLengthIter<R> {
type Item = u64;
fn next(&mut self) -> Option<Self::Item> {
let value_range = self.ranges[self.range_for_picking_range.sample(&mut self.rng)];
Some(value_range.sample(&mut self.rng))
}
}
#[test]
fn largest_number_in_7_bit_chunk_correct() {
for i in 0..8 {
let largest = largest_number_in_7_bit_chunk(i);
assert_eq!((i as u32 + 1) * 7, largest.count_ones());
assert_eq!(64 - ((i as u32) + 1) * 7, largest.leading_zeros());
assert_eq!(largest.leading_zeros() - 1, (largest + 1).leading_zeros());
}
}