use crate::compat;
use std::io::Write;
const SMALL_BUFFER_SIZE: usize = 64;
pub struct Buffer {
buf: Vec<u8>,
off: usize,
}
impl Buffer {
pub fn new() -> Self {
Self {
buf: Vec::with_capacity(SMALL_BUFFER_SIZE),
off: 0,
}
}
pub fn bytes(&self) -> &[u8] {
&self.buf[self.off..]
}
pub fn string(&self) -> String {
String::from_utf8_lossy(self.bytes()).to_string()
}
fn empty(&self) -> bool {
self.buf.len() <= self.off
}
pub fn len(&self) -> usize {
self.buf.len() - self.off
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn cap(&self) -> usize {
self.buf.capacity()
}
pub fn truncate(&mut self, n: usize) {
if n == 0 {
self.reset();
return;
}
if n > self.len() {
panic!("bytes::Buffer::new(): truncation out of range");
}
self.buf.truncate(n + self.off);
}
pub fn reset(&mut self) {
self.off = 0;
self.buf.clear();
}
fn guarantee_space(&mut self, n: usize) {
let data_size = self.buf.len() - self.off;
if data_size == 0 {
self.reset();
} else if self.off > SMALL_BUFFER_SIZE && self.off > self.buf.capacity() / 2 {
let end = self.buf.len();
self.buf.copy_within(self.off..end, 0);
self.buf.truncate(data_size);
self.off = 0;
}
let space_left = self.buf.capacity() - data_size;
if space_left < n {
let missing_capacity = n - space_left;
self.buf.reserve(missing_capacity);
}
}
pub fn grow(&mut self, n: usize) {
self.guarantee_space(n);
}
}
impl Default for Buffer {
fn default() -> Self {
Self::new()
}
}
impl std::io::Read for Buffer {
fn read(&mut self, p: &mut [u8]) -> std::io::Result<usize> {
if self.empty() {
self.reset();
if p.is_empty() {
return Ok(0);
}
return Ok(0);
}
let n = compat::copy(p, &self.buf[self.off..]);
self.off += n;
if n > 0 {
}
Ok(n)
}
}
impl std::io::Write for Buffer {
fn write(&mut self, p: &[u8]) -> std::io::Result<usize> {
self.guarantee_space(p.len());
self.buf.extend_from_slice(p);
Ok(p.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl Buffer {
pub fn write_string(&mut self, s: &str) -> std::io::Result<usize> {
self.write(s.as_bytes())
}
pub fn write_byte(&mut self, c: u8) -> std::io::Result<()> {
self.guarantee_space(1);
self.buf.push(c);
Ok(())
}
pub fn read_byte(&mut self) -> Option<u8> {
if self.empty() {
self.reset();
return None;
}
let c = self.buf[self.off];
self.off += 1;
Some(c)
}
}
pub fn new_buffer(buf: Vec<u8>) -> Buffer {
Buffer { buf, off: 0 }
}
pub fn new_buffer_string(s: &str) -> Buffer {
Buffer {
buf: s.as_bytes().to_vec(),
off: 0,
}
}
impl std::io::BufRead for Buffer {
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
Ok(self.bytes())
}
fn consume(&mut self, amt: usize) {
self.off += amt.min(self.len());
}
}