use super::{Buf, MutBuf};
use std::{cmp, fmt, mem, ptr, slice};
use std::rt::heap;
use std::io;
pub struct RingBuf {
ptr: *mut u8, cap: usize, pos: usize, len: usize }
impl RingBuf {
pub fn new(mut capacity: usize) -> RingBuf {
if capacity == 0 {
return RingBuf {
ptr: ptr::null_mut(),
cap: 0,
pos: 0,
len: 0
}
}
capacity = capacity.next_power_of_two();
let ptr = unsafe { heap::allocate(capacity, mem::min_align_of::<u8>()) };
RingBuf {
ptr: ptr as *mut u8,
cap: capacity,
pos: 0,
len: 0
}
}
pub fn is_full(&self) -> bool {
self.cap == self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn capacity(&self) -> usize {
self.cap
}
fn read_remaining(&self) -> usize {
self.len
}
fn write_remaining(&self) -> usize {
self.cap - self.len
}
fn advance_reader(&mut self, mut cnt: usize) {
if self.cap == 0 {
return;
}
cnt = cmp::min(cnt, self.read_remaining());
self.pos += cnt;
self.pos %= self.cap;
self.len -= cnt;
}
fn advance_writer(&mut self, mut cnt: usize) {
cnt = cmp::min(cnt, self.write_remaining());
self.len += cnt;
}
fn as_slice(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(self.ptr as *const u8, self.cap)
}
}
fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(self.ptr, self.cap)
}
}
}
impl Clone for RingBuf {
fn clone(&self) -> RingBuf {
use std::cmp;
let mut ret = RingBuf::new(self.cap);
ret.pos = self.pos;
ret.len = self.len;
unsafe {
let to = self.pos + self.len;
if to > self.cap {
ptr::copy(ret.ptr, self.ptr as *const u8, to % self.cap);
}
ptr::copy(
ret.ptr.offset(self.pos as isize),
self.ptr.offset(self.pos as isize) as *const u8,
cmp::min(self.len, self.cap - self.pos));
}
ret
}
}
impl fmt::Debug for RingBuf {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "RingBuf[.. {}]", self.len)
}
}
impl Drop for RingBuf {
fn drop(&mut self) {
if self.cap > 0 {
unsafe {
heap::deallocate(self.ptr, self.cap, mem::min_align_of::<u8>())
}
}
}
}
impl Buf for RingBuf {
fn remaining(&self) -> usize {
self.read_remaining()
}
fn bytes(&self) -> &[u8] {
let mut to = self.pos + self.len;
if to > self.cap {
to = self.cap
}
&self.as_slice()[self.pos .. to]
}
fn advance(&mut self, cnt: usize) {
self.advance_reader(cnt)
}
}
impl MutBuf for RingBuf {
fn remaining(&self) -> usize {
self.write_remaining()
}
fn advance(&mut self, cnt: usize) {
self.advance_writer(cnt)
}
fn mut_bytes(&mut self) -> &mut [u8] {
if self.cap == 0 {
return self.as_mut_slice();
}
let mut from;
let mut to;
from = self.pos + self.len;
from %= self.cap;
to = from + <Self as MutBuf>::remaining(&self);
if to >= self.cap {
to = self.cap;
}
&mut self.as_mut_slice()[from..to]
}
}
impl io::Read for RingBuf {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if !MutBuf::has_remaining(self) {
return Ok(0);
}
Ok(self.read_slice(buf))
}
}
impl io::Write for RingBuf {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if !Buf::has_remaining(self) {
return Ok(0);
}
Ok(self.write_slice(buf))
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
unsafe impl Send for RingBuf { }