use super::{SeqRead, SeqWrite};
use crate::os::{map_ring, unmap_ring};
use crate::{Result, Size};
use std::cmp;
use std::io::{self, BufRead, Read, Write};
use std::ops::Deref;
#[derive(Debug)]
pub struct Ring {
ptr: *mut u8,
len: usize,
rpos: u64,
wpos: u64,
}
impl Ring {
pub fn new(hint: usize) -> Result<Self> {
let len = Size::alloc().round(hint);
let ptr = map_ring(len)?;
Ok(Self {
ptr,
len,
rpos: 0,
wpos: 0,
})
}
pub fn clear(&mut self) {
self.rpos = 0;
self.wpos = 0;
}
}
impl Drop for Ring {
fn drop(&mut self) {
unsafe { unmap_ring(self.ptr, self.write_capacity()) }.unwrap_or_default();
}
}
impl SeqRead for Ring {
fn as_read_ptr(&self) -> *const u8 {
self.ptr
}
fn read_offset(&self) -> usize {
self.rpos as usize % self.len
}
fn read_len(&self) -> usize {
(self.wpos - self.rpos) as usize
}
}
impl SeqWrite for Ring {
fn as_write_ptr(&mut self) -> *mut u8 {
self.ptr
}
fn write_offset(&self) -> usize {
self.wpos as usize % self.len
}
fn write_len(&self) -> usize {
self.write_capacity() - self.read_len()
}
fn write_capacity(&self) -> usize {
self.len
}
fn feed(&mut self, len: usize) {
self.wpos += cmp::min(len, self.write_len()) as u64;
}
}
impl BufRead for Ring {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(self.as_read_slice(std::usize::MAX))
}
fn consume(&mut self, len: usize) {
self.rpos += cmp::min(len, self.read_len()) as u64;
}
}
impl Read for Ring {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.read_from(buf)
}
}
impl Write for Ring {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.write_into(buf)
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl Deref for Ring {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_read_slice(usize::MAX)
}
}
impl AsRef<[u8]> for Ring
where
<Ring as Deref>::Target: AsRef<[u8]>,
{
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
#[derive(Debug)]
pub struct InfiniteRing {
ptr: *mut u8,
len: usize,
rlen: u64,
wpos: u64,
}
impl InfiniteRing {
pub fn new(hint: usize) -> Result<Self> {
let len = Size::alloc().round(hint);
let ptr = map_ring(len)?;
Ok(Self {
ptr,
len,
rlen: 0,
wpos: 0,
})
}
}
impl Drop for InfiniteRing {
fn drop(&mut self) {
unsafe { unmap_ring(self.ptr, self.write_capacity()) }.unwrap_or_default()
}
}
impl SeqRead for InfiniteRing {
fn as_read_ptr(&self) -> *const u8 {
self.ptr
}
fn read_offset(&self) -> usize {
(self.wpos - self.rlen) as usize % self.len
}
fn read_len(&self) -> usize {
self.rlen as usize
}
}
impl SeqWrite for InfiniteRing {
fn as_write_ptr(&mut self) -> *mut u8 {
self.ptr
}
fn write_offset(&self) -> usize {
self.wpos as usize % self.len
}
fn write_len(&self) -> usize {
self.write_capacity()
}
fn write_capacity(&self) -> usize {
self.len
}
fn feed(&mut self, len: usize) {
self.wpos += cmp::min(len, self.write_len()) as u64;
self.rlen = cmp::min(self.rlen + len as u64, self.len as u64);
}
}
impl BufRead for InfiniteRing {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
Ok(self.as_read_slice(std::usize::MAX))
}
fn consume(&mut self, len: usize) {
self.rlen -= cmp::min(len, self.read_len()) as u64;
}
}
impl Read for InfiniteRing {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.read_from(buf)
}
}
impl Write for InfiniteRing {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.write_into(buf)
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
let len = {
let dst = self.as_write_slice(buf.len());
let len = dst.len();
let tail = buf.len() - len;
dst.copy_from_slice(&buf[tail..]);
len
};
self.feed(len);
Ok(())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl Deref for InfiniteRing {
type Target = [u8];
#[inline]
fn deref(&self) -> &Self::Target {
self.as_read_slice(usize::MAX)
}
}
impl AsRef<[u8]> for InfiniteRing
where
<InfiniteRing as Deref>::Target: AsRef<[u8]>,
{
fn as_ref(&self) -> &[u8] {
self.deref()
}
}