use crate::BufGetBytes;
use bytes::buf::BufExt;
use bytes::Buf;
use bytes::Bytes;
use std::cmp;
use std::io::IoSlice;
#[derive(Clone, Copy, Default)]
pub struct Zeroes(pub usize);
static ZEROES: &[u8] = &[0; 256];
impl Buf for Zeroes {
fn remaining(&self) -> usize {
self.0
}
fn bytes(&self) -> &[u8] {
let len = cmp::min(self.0, ZEROES.len());
&ZEROES[..len]
}
fn bytes_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
let mut c = self.clone();
let mut n = 0;
while c.0 != 0 && n != dst.len() {
let len = c.bytes().len();
dst[n] = IoSlice::new(&ZEROES[..len]);
c.0 -= len;
n += 1;
}
n
}
fn advance(&mut self, cnt: usize) {
assert!(cnt <= self.0);
self.0 -= cnt;
}
}
impl BufGetBytes for Zeroes {
fn get_bytes(&mut self, cnt: usize) -> Bytes {
assert!(cnt <= self.remaining());
if cnt <= ZEROES.len() {
self.0 -= cnt;
Bytes::from_static(&ZEROES[..cnt])
} else {
self.take(cnt).to_bytes()
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn buf_small() {
let mut z = Zeroes(5);
assert_eq!(&[0, 0, 0, 0, 0], z.bytes());
assert_eq!(5, z.remaining());
z.advance(3);
assert_eq!(2, z.remaining());
assert_eq!(&[0, 0], z.bytes());
z.advance(2);
assert_eq!(0, z.remaining());
}
#[test]
fn buf_large() {
let mut z = Zeroes(10000);
assert_eq!(ZEROES, z.bytes());
z.advance(ZEROES.len());
assert_eq!(10000 - ZEROES.len(), z.remaining());
}
#[test]
fn buf_bytes_vectored_small() {
let z = Zeroes(ZEROES.len() + 1);
let mut s = [IoSlice::new(&[])];
assert_eq!(1, z.bytes_vectored(&mut s));
assert_eq!(ZEROES, &*s[0]);
let mut s = [IoSlice::new(&[]), IoSlice::new(&[])];
assert_eq!(2, z.bytes_vectored(&mut s));
assert_eq!(ZEROES, &*s[0]);
assert_eq!(&[0], &*s[1]);
let mut s = [IoSlice::new(&[]), IoSlice::new(&[]), IoSlice::new(&[])];
assert_eq!(2, z.bytes_vectored(&mut s));
assert_eq!(ZEROES, &*s[0]);
assert_eq!(&[0], &*s[1]);
}
#[test]
fn buf_bytes_vectored_large() {
let z = Zeroes(10000);
let mut s = [IoSlice::new(&[])];
assert_eq!(1, z.bytes_vectored(&mut s));
assert_eq!(ZEROES, &*s[0]);
let mut s = [IoSlice::new(&[]), IoSlice::new(&[])];
assert_eq!(2, z.bytes_vectored(&mut s));
assert_eq!(ZEROES, &*s[0]);
assert_eq!(ZEROES, &*s[1]);
}
#[test]
fn buf_get_bytes() {
assert_eq!(ZEROES.as_ptr(), Zeroes(10).get_bytes(7).as_ptr());
assert_eq!(&ZEROES[..7], Zeroes(10).get_bytes(7));
assert_eq!(3, {
let mut z = Zeroes(10);
z.get_bytes(7);
z.remaining()
});
assert_eq!(
ZEROES.as_ptr(),
Zeroes(ZEROES.len() * 2 + 1).get_bytes(7).as_ptr()
);
assert_eq!(&ZEROES[..7], Zeroes(ZEROES.len() * 2 + 1).get_bytes(7));
assert_eq!(
vec![0; ZEROES.len() + 2],
Zeroes(ZEROES.len() * 2 + 1).get_bytes(ZEROES.len() + 2)
);
}
}