use std::io;
use bytes::{Bytes, BytesMut};
mod decoder;
mod encoder;
pub use self::{decoder::Decoder, encoder::Encoder};
struct Writer {
buf: BytesMut,
remaining: Option<usize>,
}
impl Writer {
fn new() -> Writer {
Writer {
buf: BytesMut::with_capacity(8192),
remaining: None,
}
}
fn set_limit(&mut self, limit: usize) {
self.remaining = Some(limit);
}
fn take(&mut self) -> Bytes {
self.buf.split().freeze()
}
}
impl io::Write for Writer {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if let Some(remaining) = &mut self.remaining {
if buf.len() > *remaining {
*remaining = 0;
return Err(io::ErrorKind::FileTooLarge.into());
}
*remaining -= buf.len();
}
self.buf.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use std::io::Write as _;
use super::Writer;
#[test]
fn writer_rejects_overflow_without_copying() {
let mut writer = Writer::new();
writer.set_limit(3);
writer.write_all(b"ab").unwrap();
assert!(writer.write_all(b"cdef").is_err());
assert_eq!(writer.take().as_ref(), b"ab");
assert!(writer.write_all(b"more output").is_err());
assert!(writer.take().is_empty());
}
#[test]
fn writer_zero_limit_rejects_output() {
let mut writer = Writer::new();
writer.set_limit(0);
assert!(writer.write_all(b"ab").is_err());
assert!(writer.take().is_empty());
}
#[test]
fn taking_output_does_not_reset_limit() {
let mut writer = Writer::new();
writer.set_limit(3);
writer.write_all(b"ab").unwrap();
assert_eq!(writer.take().as_ref(), b"ab");
writer.write_all(b"c").unwrap();
assert!(writer.write_all(b"d").is_err());
assert_eq!(writer.take().as_ref(), b"c");
}
#[test]
fn writer_max_limit_does_not_wrap() {
let mut writer = Writer::new();
writer.set_limit(usize::MAX);
writer.write_all(b"abc").unwrap();
assert_eq!(writer.take().as_ref(), b"abc");
}
#[test]
fn writer_is_unlimited_by_default() {
let mut writer = Writer::new();
let data = vec![0; 1024 * 1024];
writer.write_all(&data).unwrap();
assert_eq!(writer.take().as_ref(), data);
}
}