extern crate bytes;
use std::mem::MaybeUninit;
pub use bytes::{Buf, BufMut};
#[derive(Debug, Clone)]
pub struct RingBuffer {
buffer: Vec<MaybeUninit<u8>>,
begin: usize,
len: usize,
}
impl RingBuffer {
pub fn new(capacity: usize) -> Self {
Self {
buffer: vec![MaybeUninit::uninit(); capacity],
begin: 0,
len: 0,
}
}
pub fn capacity(&self) -> usize {
self.buffer.len()
}
}
impl Buf for RingBuffer {
fn remaining(&self) -> usize {
self.len
}
fn bytes(&self) -> &[u8] {
let end = (self.begin + self.len).min(self.capacity());
let slice = &self.buffer[self.begin..end];
unsafe { &*(slice as *const [MaybeUninit<u8>] as *const [u8]) }
}
fn advance(&mut self, cnt: usize) {
assert!(cnt <= self.len);
self.begin += cnt;
self.begin %= self.capacity();
self.len -= cnt;
}
}
impl BufMut for RingBuffer {
fn remaining_mut(&self) -> usize {
self.capacity() - self.remaining()
}
fn bytes_mut(&mut self) -> &mut [MaybeUninit<u8>] {
let begin = (self.begin + self.len) % self.capacity();
let end = (begin + self.remaining_mut()).min(self.capacity());
&mut self.buffer[begin..end]
}
unsafe fn advance_mut(&mut self, cnt: usize) {
assert!(cnt <= self.remaining_mut());
self.len += cnt;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ringbuffer_init() {
let buf = RingBuffer::new(16);
assert_eq!(buf.capacity(), 16);
assert_eq!(buf.remaining(), 0);
assert_eq!(buf.remaining_mut(), 16);
}
#[test]
fn ringbuffer_read_write() {
let mut buf = RingBuffer::new(16);
for i in 0..6 {
buf.put_u8(i);
}
assert_eq!(buf.remaining(), 6);
assert_eq!(buf.remaining_mut(), 10);
for i in 0..6 {
assert_eq!(buf.get_u8(), i);
}
for i in 0..16 {
buf.put_u8(i);
}
assert_eq!(buf.remaining(), 16);
assert_eq!(buf.remaining_mut(), 0);
assert_eq!(buf.bytes().len(), 10);
for i in 0..10 {
assert_eq!(buf.get_u8(), i);
}
assert_eq!(buf.bytes().len(), 6);
for i in 10..16 {
assert_eq!(buf.get_u8(), i);
}
}
#[test]
#[should_panic]
fn ringbuffer_read_over_remaining() {
let mut buf = RingBuffer::new(16);
for i in 0..15 {
buf.put_u8(i);
}
for _ in 0..16 {
buf.get_u8();
}
}
#[test]
#[should_panic]
fn ringbuffer_write_over_capacity() {
let mut buf = RingBuffer::new(16);
for i in 0..17 {
buf.put_u8(i);
}
}
}