extern crate rand;
use rand::distributions::{IndependentSample, Range};
use std::cmp::min;
use std::io::{self, Read, Write};
pub struct DribbleReader<R: Read> {
source: R,
buffer: Vec<u8>,
used: usize,
available: usize
}
impl<R: Read> DribbleReader<R> {
pub fn new(source: R) -> Self {
DribbleReader{source: source, buffer: vec![0; 64],
used: 0, available: 0}
}
}
impl<R: Read> Read for DribbleReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
assert!(self.used <= self.available);
if self.used == self.available {
self.used = 0;
self.available = 0;
self.available = try!(self.source.read(&mut self.buffer));
}
if self.available == 0 {
Ok(0)
} else {
let mut rng = rand::thread_rng();
let bytes = min(buf.len(),
min(Range::new(1, 5).ind_sample(&mut rng),
self.available - self.used));
assert!(1 <= bytes && bytes <= 4);
for i in 0..bytes { buf[i] = self.buffer[self.used+i]; }
self.used += bytes;
Ok(bytes)
}
}
}
pub struct DribbleWriter<W: Write> {
dest: W
}
impl<W: Write> DribbleWriter<W> {
pub fn new(dest: W) -> Self {
DribbleWriter{dest: dest}
}
}
impl<W: Write> Write for DribbleWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut rng = rand::thread_rng();
let mut written = 0;
while written < buf.len() {
let bytes = min(buf.len() - written,
Range::new(0, 5).ind_sample(&mut rng));
try!(self.dest.write(&buf[written..written+bytes]));
written += bytes;
}
Ok(written)
}
fn flush(&mut self) -> io::Result<()> {
self.dest.flush()
}
}