#[cfg(feature = "bytes")]
mod bytes;
use std::boxed::Box;
use std::error;
use std::fmt;
use std::io;
use std::ptr::copy_nonoverlapping;
use std::slice::from_raw_parts;
use std::slice::from_raw_parts_mut;
pub const DEFAULT_CAPACITY: usize = 4096;
pub const DEFAULT_SIZE_MULTIPLIER: usize = 2;
#[derive(Debug, Clone)]
pub enum CircBufError {
BufEmpty,
BufFull,
Overflow,
NotEnoughData,
NotEnoughPlace,
}
impl fmt::Display for CircBufError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CircBufError::BufEmpty => write!(f, "CircBuf is full"),
CircBufError::BufFull => write!(f, "CircBuf is empty"),
CircBufError::Overflow => write!(f, "Value would overflow usize"),
CircBufError::NotEnoughData => {
write!(f, "Doesn't have enough data to advance read cursor")
}
CircBufError::NotEnoughPlace => {
write!(f, "Doesn't have enough place to advance write cursor")
}
}
}
}
impl error::Error for CircBufError {}
#[derive(Debug, Default)]
pub struct CircBuf {
buf: Box<[u8]>,
write_cursor: usize,
read_cursor: usize,
}
impl CircBuf {
pub fn new() -> Self {
CircBuf {
buf: Box::new([0; DEFAULT_CAPACITY]),
write_cursor: 0,
read_cursor: 0,
}
}
pub fn with_capacity(cap: usize) -> Result<Self, CircBufError> {
let capacity = match cap.checked_next_power_of_two() {
Some(capacity) => capacity,
None => return Err(CircBufError::Overflow),
};
Ok(CircBuf {
buf: vec![0; capacity].into_boxed_slice(),
write_cursor: 0,
read_cursor: 0,
})
}
pub fn cap(&self) -> usize {
self.buf.len() - 1
}
fn cacl_len(read_cursor: usize, write_cursor: usize, len: usize) -> usize {
if write_cursor < read_cursor {
len - read_cursor + write_cursor
} else {
write_cursor - read_cursor
}
}
pub fn len(&self) -> usize {
Self::cacl_len(self.read_cursor, self.write_cursor, self.buf.len())
}
pub fn avail(&self) -> usize {
self.cap() - self.len()
}
pub fn is_empty(&self) -> bool {
self.read_cursor == self.write_cursor
}
pub fn is_full(&self) -> bool {
self.avail() == 0
}
pub fn find_from_index(&self, val: u8, index: usize) -> Option<usize> {
if index >= self.len() {
return None;
}
if self.write_cursor < self.read_cursor {
if self.read_cursor + index < self.buf.len() {
for (i, b) in self.buf[self.read_cursor + index..].iter().enumerate() {
if *b == val {
return Some(i + index);
}
}
}
for (i, b) in self.buf[..self.write_cursor].iter().enumerate() {
if *b == val {
return Some(i + self.buf.len() - self.read_cursor);
}
}
None
} else {
for (i, b) in self.buf[self.read_cursor + index..self.write_cursor]
.iter()
.enumerate()
{
if *b == val {
return Some(i + index);
}
}
None
}
}
pub fn find(&self, val: u8) -> Option<usize> {
self.find_from_index(val, 0)
}
pub fn peek(&self) -> Result<u8, CircBufError> {
if self.is_empty() {
return Err(CircBufError::BufEmpty);
}
Ok(self.buf[self.read_cursor])
}
pub fn get(&mut self) -> Result<u8, CircBufError> {
if self.is_empty() {
return Err(CircBufError::BufEmpty);
}
let val = self.buf[self.read_cursor];
self.advance_read_raw(1);
Ok(val)
}
pub fn put(&mut self, val: u8) -> Result<(), CircBufError> {
if self.avail() == 0 {
return Err(CircBufError::BufFull);
}
self.buf[self.write_cursor] = val;
self.advance_write_raw(1);
Ok(())
}
fn cacl_read(read_cursor: usize, num: usize, len: usize) -> usize {
(read_cursor + num) % len
}
pub fn advance_read_raw(&mut self, num: usize) {
self.read_cursor = Self::cacl_read(self.read_cursor, num, self.buf.len());
}
pub fn advance_read(&mut self, num: usize) -> Result<(), CircBufError> {
if num > self.len() {
Err(CircBufError::NotEnoughData)
} else {
self.advance_read_raw(num);
Ok(())
}
}
pub fn advance_write_raw(&mut self, num: usize) {
self.write_cursor = (self.write_cursor + num) % self.buf.len();
}
pub fn advance_write(&mut self, num: usize) -> Result<(), CircBufError> {
if num > self.avail() {
Err(CircBufError::NotEnoughPlace)
} else {
self.advance_write_raw(num);
Ok(())
}
}
pub fn clear(&mut self) {
self.write_cursor = 0;
self.read_cursor = 0;
}
pub fn grow_with_factor(&mut self, factor: usize) -> Result<(), CircBufError> {
let cap = match self.buf.len().checked_mul(factor) {
Some(cap) => cap,
None => return Err(CircBufError::Overflow),
};
let cap_checked = match cap.checked_next_power_of_two() {
Some(cap) => cap,
None => return Err(CircBufError::Overflow),
};
let mut new_buf = vec![0; cap_checked].into_boxed_slice();
let mut bytes_written = 0;
if self.write_cursor < self.read_cursor {
let num_to_end = self.buf.len() - self.read_cursor;
unsafe { copy_nonoverlapping(&self.buf[self.read_cursor], &mut new_buf[0], num_to_end) }
bytes_written += num_to_end;
unsafe {
copy_nonoverlapping(&self.buf[0], &mut new_buf[bytes_written], self.write_cursor)
}
bytes_written += self.write_cursor;
} else {
let num_to_copy = self.write_cursor - self.read_cursor;
unsafe {
copy_nonoverlapping(&self.buf[self.read_cursor], &mut new_buf[0], num_to_copy)
}
bytes_written += num_to_copy;
}
self.buf = new_buf;
self.write_cursor = bytes_written;
self.read_cursor = 0;
Ok(())
}
pub fn grow(&mut self) -> Result<(), CircBufError> {
self.grow_with_factor(DEFAULT_SIZE_MULTIPLIER)
}
pub fn get_avail_upto_size(&mut self, size: usize) -> [&mut [u8]; 2] {
let first_buf;
let second_buf;
let min = if self.avail() < size {
self.avail()
} else {
size
};
if self.write_cursor >= self.read_cursor && min > self.buf.len() - self.write_cursor {
unsafe {
first_buf = from_raw_parts_mut(
&mut self.buf[self.write_cursor],
self.buf.len() - self.write_cursor,
);
second_buf = from_raw_parts_mut(
&mut self.buf[0],
min - (self.buf.len() - self.write_cursor),
);
}
} else {
unsafe {
first_buf = from_raw_parts_mut(&mut self.buf[self.write_cursor], min);
second_buf = from_raw_parts_mut(&mut self.buf[self.write_cursor], 0);
}
}
[first_buf, second_buf]
}
pub fn get_bytes_upto_size(&self, size: usize) -> [&[u8]; 2] {
let first_buf;
let second_buf;
let min = if self.len() < size { self.len() } else { size };
if self.write_cursor < self.read_cursor && min > self.buf.len() - self.read_cursor {
unsafe {
first_buf = from_raw_parts(
&self.buf[self.read_cursor],
self.buf.len() - self.read_cursor,
);
second_buf =
from_raw_parts(&self.buf[0], min - (self.buf.len() - self.read_cursor));
}
} else {
unsafe {
first_buf = from_raw_parts(&self.buf[self.read_cursor], min);
second_buf = from_raw_parts(&self.buf[self.read_cursor], 0);
}
}
[first_buf, second_buf]
}
pub fn get_avail(&mut self) -> [&mut [u8]; 2] {
let avail = self.avail();
self.get_avail_upto_size(avail)
}
pub fn get_bytes(&self) -> [&[u8]; 2] {
let len = self.len();
self.get_bytes_upto_size(len)
}
pub fn reader_peek(&self) -> CircBufPeekReader {
CircBufPeekReader {
inner: self,
peek_cursor: self.read_cursor,
}
}
unsafe fn read_peek(
src: &[u8],
dest: &mut [u8],
len: usize,
read_cursor: usize,
) -> io::Result<usize> {
let num_to_read = if len < dest.len() { len } else { dest.len() };
let num_to_end = src.len() - read_cursor;
if num_to_read > num_to_end {
copy_nonoverlapping(&src[read_cursor], &mut dest[0], num_to_end);
copy_nonoverlapping(&src[0], &mut dest[num_to_end], num_to_read - num_to_end);
} else {
copy_nonoverlapping(&src[read_cursor], &mut dest[0], num_to_read);
}
Ok(num_to_read)
}
}
pub struct CircBufPeekReader<'a> {
inner: &'a CircBuf,
peek_cursor: usize,
}
impl<'a> CircBufPeekReader<'a> {
pub fn len(&self) -> usize {
CircBuf::cacl_len(
self.peek_cursor,
self.inner.write_cursor,
self.inner.buf.len(),
)
}
pub fn is_empty(&self) -> bool {
self.peek_cursor == self.inner.write_cursor
}
pub fn reset(&mut self) {
self.peek_cursor = self.inner.read_cursor;
}
pub fn count_peek(&self) -> usize {
self.inner.len() - self.len()
}
}
impl<'a> io::Read for CircBufPeekReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let len = self.len();
if len == 0 {
Ok(0)
} else {
let readed =
unsafe { CircBuf::read_peek(&self.inner.buf, buf, len, self.peek_cursor)? };
self.peek_cursor = CircBuf::cacl_read(self.peek_cursor, readed, self.inner.buf.len());
Ok(readed)
}
}
}
impl io::Read for CircBuf {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let len = self.len();
if len == 0 {
Ok(0)
} else {
let readed = unsafe { CircBuf::read_peek(&self.buf, buf, len, self.read_cursor)? };
self.advance_read_raw(readed);
Ok(readed)
}
}
}
impl io::Write for CircBuf {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let avail = self.avail();
if avail == 0 || buf.is_empty() {
return Ok(0);
}
let num_to_write = if avail < buf.len() { avail } else { buf.len() };
if self.write_cursor < self.read_cursor {
unsafe { copy_nonoverlapping(&buf[0], &mut self.buf[self.write_cursor], num_to_write) };
} else {
let num_to_end = self.buf.len() - self.write_cursor;
let min = if num_to_write < num_to_end {
num_to_write
} else {
num_to_end
};
unsafe { copy_nonoverlapping(&buf[0], &mut self.buf[self.write_cursor], min) };
if min != num_to_write {
unsafe { copy_nonoverlapping(&buf[min], &mut self.buf[0], num_to_write - min) };
}
}
self.advance_write_raw(num_to_write);
Ok(num_to_write)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::{CircBuf, CircBufError, DEFAULT_CAPACITY};
use std::io::{Read, Write};
#[test]
fn create_circbuf() {
let c = CircBuf::new();
assert_eq!(c.cap(), DEFAULT_CAPACITY - 1);
assert_eq!(c.avail(), DEFAULT_CAPACITY - 1);
assert_eq!(c.len(), 0);
assert!(c.is_empty());
}
#[test]
fn create_circbuf_with_capacity() {
let c = CircBuf::with_capacity(49).unwrap();
assert_eq!(c.cap(), 64 - 1);
assert_eq!(c.avail(), 64 - 1);
assert_eq!(c.len(), 0);
assert!(c.is_empty());
}
#[test]
fn put_peek_and_get_bytes() {
let mut c = CircBuf::with_capacity(4).unwrap();
c.put(1).unwrap();
c.put(2).unwrap();
c.put(3).unwrap();
assert_eq!(
c.put(4).unwrap_err().to_string(),
CircBufError::BufFull.to_string()
);
assert_eq!(c.avail(), 0);
assert_eq!(c.len(), 3);
assert!(c.is_full());
assert_eq!(c.peek().unwrap(), 1);
assert_eq!(c.get().unwrap(), 1);
assert_eq!(c.peek().unwrap(), 2);
assert_eq!(c.get().unwrap(), 2);
assert_eq!(c.peek().unwrap(), 3);
assert_eq!(c.get().unwrap(), 3);
assert_eq!(
c.get().unwrap_err().to_string(),
CircBufError::BufEmpty.to_string()
);
assert_eq!(c.avail(), 3);
assert_eq!(c.len(), 0);
assert!(c.is_empty());
c.put(4).unwrap();
c.put(5).unwrap();
c.put(6).unwrap();
assert_eq!(c.peek().unwrap(), 4);
assert_eq!(c.get().unwrap(), 4);
assert_eq!(c.peek().unwrap(), 5);
assert_eq!(c.get().unwrap(), 5);
assert_eq!(c.peek().unwrap(), 6);
assert_eq!(c.get().unwrap(), 6);
}
#[test]
fn find_bytes() {
let mut c = CircBuf::with_capacity(8).unwrap();
c.put(7).unwrap();
c.put(6).unwrap();
c.put(5).unwrap();
c.put(4).unwrap();
c.put(3).unwrap();
c.put(2).unwrap();
c.put(1).unwrap();
assert_eq!(c.find(4).unwrap(), 3);
assert_eq!(c.find_from_index(3, 2).unwrap(), 4);
assert!(c.find_from_index(6, 2).is_none());
c.advance_read(4).unwrap();
assert_eq!(c.find(1).unwrap(), 2);
assert!(c.find(5).is_none());
c.put(10).unwrap();
c.put(11).unwrap();
c.put(12).unwrap();
assert_eq!(c.find(12).unwrap(), 5);
assert_eq!(c.find_from_index(12, 4).unwrap(), 5);
}
#[test]
fn grow_buffer() {
let mut c = CircBuf::with_capacity(4).unwrap();
c.put(1).unwrap();
c.put(2).unwrap();
c.put(3).unwrap();
c.grow().unwrap();
assert!(c.cap() == 8 - 1);
assert!(c.avail() == 4);
assert!(c.len() == 3);
assert_eq!(c.get().unwrap(), 1);
assert_eq!(c.get().unwrap(), 2);
assert_eq!(c.get().unwrap(), 3);
c.advance_read_raw(7);
c.advance_write_raw(7);
c.put(1).unwrap();
c.put(2).unwrap();
c.put(3).unwrap();
c.grow().unwrap();
assert_eq!(c.get().unwrap(), 1);
assert_eq!(c.get().unwrap(), 2);
assert_eq!(c.get().unwrap(), 3);
}
#[test]
fn read_and_write_bytes() {
let mut c = CircBuf::with_capacity(8).unwrap();
assert_eq!(c.write(b"foo").unwrap(), 3);
assert_eq!(c.write(b"bar").unwrap(), 3);
assert_eq!(c.write(b"").unwrap(), 0);
assert_eq!(c.cap(), 7);
assert_eq!(c.avail(), 1);
assert_eq!(c.len(), 6);
let mut buf = [0; 6];
assert_eq!(c.read(&mut buf).unwrap(), 6);
assert!(b"foobar".iter().zip(buf.iter()).all(|(a, b)| a == b));
assert_eq!(c.cap(), 7);
assert_eq!(c.avail(), 7);
assert_eq!(c.len(), 0);
c.advance_read_raw(7);
c.advance_write_raw(7);
assert_eq!(c.write(b"foo").unwrap(), 3);
assert_eq!(c.write(b"bar").unwrap(), 3);
let mut buf = [0; 6];
assert_eq!(c.read(&mut buf).unwrap(), 6);
assert!(b"foobar".iter().zip(buf.iter()).all(|(a, b)| a == b));
}
#[test]
fn get_bytes_and_avail() {
let mut c = CircBuf::with_capacity(16).unwrap();
assert_eq!(c.write(b"funkytowns").unwrap(), 10);
assert_eq!(c.len(), 10);
assert_eq!(c.avail(), 5);
{
let bufs = c.get_avail_upto_size(4);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 4);
assert_eq!(bufs[1].len(), 0);
}
{
let bufs = c.get_bytes_upto_size(5);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 5);
assert_eq!(bufs[1].len(), 0);
assert!(b"funky".iter().zip(bufs[0].iter()).all(|(a, b)| a == b));
}
{
let bufs = c.get_avail_upto_size(10);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 5);
assert_eq!(bufs[1].len(), 0);
}
{
let bufs = c.get_bytes_upto_size(12);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 10);
assert_eq!(bufs[1].len(), 0);
assert!(b"funky".iter().zip(bufs[0].iter()).all(|(a, b)| a == b));
}
{
let bufs = c.get_avail();
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 5);
assert_eq!(bufs[1].len(), 0);
}
{
let bufs = c.get_bytes();
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 10);
assert_eq!(bufs[1].len(), 0);
assert!(b"funkytowns"
.iter()
.zip(bufs[0].iter())
.all(|(a, b)| a == b));
}
c.advance_read(10).unwrap();
assert_eq!(c.write(b"brickhouse").unwrap(), 10);
assert_eq!(c.len(), 10);
assert_eq!(c.avail(), 5);
{
let bufs = c.get_avail_upto_size(4);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 4);
assert_eq!(bufs[1].len(), 0);
}
{
let bufs = c.get_bytes_upto_size(8);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 6);
assert_eq!(bufs[1].len(), 2);
assert!(b"brickh".iter().zip(bufs[0].iter()).all(|(a, b)| a == b));
assert!(b"ou".iter().zip(bufs[1].iter()).all(|(a, b)| a == b));
}
{
let bufs = c.get_avail_upto_size(17);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 5);
assert_eq!(bufs[1].len(), 0);
}
{
let bufs = c.get_bytes_upto_size(12);
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 6);
assert_eq!(bufs[1].len(), 4);
assert!(b"brickh".iter().zip(bufs[0].iter()).all(|(a, b)| a == b));
assert!(b"ouse".iter().zip(bufs[1].iter()).all(|(a, b)| a == b));
}
{
let bufs = c.get_avail();
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 5);
assert_eq!(bufs[1].len(), 0);
}
{
let bufs = c.get_bytes();
assert_eq!(bufs.len(), 2);
assert_eq!(bufs[0].len(), 6);
assert_eq!(bufs[1].len(), 4);
assert!(b"brickh".iter().zip(bufs[0].iter()).all(|(a, b)| a == b));
assert!(b"ouse".iter().zip(bufs[1].iter()).all(|(a, b)| a == b));
}
}
#[test]
fn reader_peek() {
let data = &b"foo\nbar\nbaz\n"[..];
let mut c = CircBuf::with_capacity(data.len()).unwrap();
for _ in 0..42 {
c.write_all(data).unwrap();
let read_cursor = c.read_cursor;
let mut v = Vec::new();
let mut peek_reader = c.reader_peek();
let readed = std::io::copy(&mut peek_reader, &mut v).unwrap() as usize;
assert!(peek_reader.is_empty());
assert_eq!(peek_reader.count_peek(), data.len());
assert_eq!(peek_reader.len(), 0);
assert_eq!(v, data);
assert_eq!(c.read_cursor, read_cursor);
c.advance_read(readed).unwrap();
}
}
#[test]
#[cfg(unix)]
fn vecio() {
use std::io::{Seek, SeekFrom};
use vecio::Rawv;
let mut c = CircBuf::with_capacity(16).unwrap();
let mut file = tempfile::tempfile().unwrap();
assert_eq!(file.write(b"foo\nbar\nbaz\n").unwrap(), 12);
file.seek(SeekFrom::Current(-12)).unwrap();
{
let mut bufs = c.get_avail();
assert_eq!(file.readv(&mut bufs).unwrap(), 12);
}
c.advance_write(12).unwrap();
c.advance_read(12).unwrap();
assert_eq!(c.write(b"fizzbuzz").unwrap(), 8);
let mut s = String::new();
assert_eq!(c.read_to_string(&mut s).unwrap(), 8);
assert_eq!(s, "fizzbuzz");
}
}