use std::io::{
BufRead,
Read,
Result,
};
pub struct LimitReader<R> {
inner: R,
remaining: u64,
}
impl<R> LimitReader<R> {
#[inline]
pub fn new(inner: R, limit: u64) -> Self {
Self {
inner,
remaining: limit,
}
}
#[inline]
pub fn remaining(&self) -> u64 {
self.remaining
}
#[inline]
pub fn get_ref(&self) -> &R {
&self.inner
}
#[inline]
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
#[inline]
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R> Read for LimitReader<R>
where
R: Read,
{
fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
if self.remaining == 0 || buffer.is_empty() {
return Ok(0);
}
let requested = self.remaining.min(buffer.len() as u64) as usize;
let count = self.inner.read(&mut buffer[..requested])?;
self.remaining -= count as u64;
Ok(count)
}
}
impl<R> BufRead for LimitReader<R>
where
R: BufRead,
{
fn fill_buf(&mut self) -> Result<&[u8]> {
if self.remaining == 0 {
return Ok(&[]);
}
let buffer = self.inner.fill_buf()?;
let limit = self.remaining.min(buffer.len() as u64) as usize;
Ok(&buffer[..limit])
}
fn consume(&mut self, amount: usize) {
let count = self.remaining.min(amount as u64);
self.remaining -= count;
self.inner.consume(count as usize);
}
}