use crate::kit::{ReadExtFully, WIDE};
use crate::ops::{Len, PeekData, Pos, Skip};
use crate::types::{ByteReader, Idx};
use super::object::Ring;
use super::ring_block::RingBlock;
use super::ring_size::RingSize;
use super::ring_view::RingView;
use std::io::{self, Read};
use std::ptr;
pub struct RingReader<'a, I, T> {
ring: Ring<'a, T>,
inner: I,
head: Idx,
tail: Idx,
is_eof: bool,
}
impl<'a, I, T: RingBlock> RingReader<'a, I, T> {
#[inline(always)]
pub fn new(ring: Ring<'a, T>, inner: I) -> Self {
assert!(0x0100 <= T::RING_BLK_SIZE);
assert!(T::RING_BLK_SIZE <= T::RING_SIZE / 4);
assert!(WIDE <= T::RING_LIMIT as usize);
Self { ring, inner, head: Idx::default(), tail: Idx::default(), is_eof: false }
}
pub fn into_inner(self) -> I {
self.inner
}
#[inline(always)]
fn fill_blk_len(&self) -> usize {
(self.fill_len() / T::RING_BLK_SIZE as usize) * T::RING_BLK_SIZE as usize
}
#[inline(always)]
fn fill_len(&self) -> usize {
debug_assert!((self.tail - self.head) as u32 <= T::RING_SIZE);
(self.head + T::RING_SIZE - self.tail) as usize
}
}
impl<'a, I, T: RingSize> PeekData for RingReader<'a, I, T> {
#[inline(always)]
unsafe fn peek_data(&self, dst: &mut [u8]) {
debug_assert!(dst.len() <= WIDE);
debug_assert!(self.head <= self.tail);
let index = self.head % T::RING_SIZE as usize;
let len = dst.len();
let src = self.ring.as_ptr().add(index);
let dst = dst.as_mut_ptr();
ptr::copy_nonoverlapping(src, dst, len);
}
}
impl<'a, 'b, I: Read, T: 'a + Copy + RingBlock> ByteReader<'a> for RingReader<'b, I, T> {
const VIEW_LIMIT: usize = T::RING_SIZE as usize - T::RING_BLK_SIZE as usize;
type View = RingView<'a, T>;
fn fill(&mut self) -> io::Result<()> {
let mut len = self.fill_blk_len();
while len != 0 && !self.is_eof {
debug_assert_eq!(self.tail % T::RING_BLK_SIZE, 0);
let index = self.tail % T::RING_SIZE as usize;
let limit = T::RING_SIZE as usize - index;
let m = len.min(limit);
debug_assert_eq!(m % T::RING_BLK_SIZE as usize, 0);
let buf = &mut self.ring[index..index + m];
let n = self.inner.read_fully(buf)?;
if index == 0 {
self.ring.head_copy_out();
}
len -= n;
self.tail += n as u32;
self.is_eof = n != m;
}
debug_assert!(self.ring.head_shadowed());
Ok(())
}
#[inline(always)]
fn view(&'a self) -> Self::View {
RingView::new(&self.ring, self.head, self.tail)
}
#[inline(always)]
fn is_eof(&self) -> bool {
self.is_eof
}
#[inline(always)]
fn is_full(&self) -> bool {
self.is_eof || self.fill_blk_len() == 0
}
}
impl<'a, I, T> Pos for RingReader<'a, I, T> {
#[inline(always)]
fn pos(&self) -> Idx {
self.head
}
}
impl<'a, I, T> Skip for RingReader<'a, I, T> {
#[inline(always)]
unsafe fn skip_unchecked(&mut self, len: usize) {
debug_assert!(len <= self.len());
self.head += len as u32;
}
}
impl<'a, I, T> Len for RingReader<'a, I, T> {
#[inline(always)]
fn len(&self) -> usize {
debug_assert!(self.head <= self.tail);
(self.tail - self.head) as usize
}
}
#[cfg(test)]
mod tests {
use crate::ring::{RingBlock, RingBox, RingSize, RingType};
use crate::types::ShortBuffer;
use test_kit::Seq;
use super::*;
#[derive(Copy, Clone)]
pub struct T;
unsafe impl RingSize for T {
const RING_SIZE: u32 = 0x4000;
}
unsafe impl RingType for T {
const RING_LIMIT: u32 = 0x0100;
}
unsafe impl RingBlock for T {
const RING_BLK_SIZE: u32 = 0x1000;
}
#[test]
fn fill_len() {
let mut core = RingBox::<T>::default();
let mut rdr = RingReader::new((&mut core).into(), ());
assert_eq!(rdr.fill_len(), T::RING_SIZE as usize);
assert_eq!(rdr.fill_blk_len(), T::RING_SIZE as usize);
rdr.tail += 1;
assert_eq!(rdr.fill_len(), T::RING_SIZE as usize - 1);
assert_eq!(rdr.fill_blk_len(), T::RING_SIZE as usize - T::RING_BLK_SIZE as usize);
}
#[test]
#[ignore = "expensive"]
fn seq_u8_1() -> io::Result<()> {
let mut core = RingBox::<T>::default();
let seq = Seq::default();
let mut rdr = RingReader::new((&mut core).into(), seq);
let mut seq = Seq::default();
for _ in 0..0x10 {
rdr.fill()?;
let mut view = rdr.view();
let view_len = view.len();
assert_eq!(rdr.len(), view.len());
assert!(RingReader::<Seq, T>::VIEW_LIMIT <= view_len);
while view.len() != 0 {
let bytes = view.short_bytes();
let bytes_len = bytes.len();
for &b in bytes.iter() {
assert_eq!(seq.next().unwrap(), b);
}
view.skip(bytes_len);
}
rdr.skip(view_len);
}
Ok(())
}
#[test]
#[ignore = "expensive"]
fn seq_u8_2() -> io::Result<()> {
let mut core = RingBox::<T>::default();
let seq = Seq::default();
let mut rdr = RingReader::new((&mut core).into(), seq);
let mut seq = Seq::default();
for _ in 0..T::RING_SIZE * 2 {
rdr.fill()?;
let view = rdr.view();
let view_len = view.len();
assert_eq!(rdr.len(), view.len());
assert!(RingReader::<Seq, T>::VIEW_LIMIT <= view_len);
let bytes = view.short_bytes();
let bytes_len = bytes.len();
assert_eq!(bytes_len, T::RING_LIMIT as usize);
for &b in bytes.iter() {
assert_eq!(seq.next().unwrap(), b);
}
rdr.skip(bytes_len);
}
Ok(())
}
#[test]
#[ignore = "expensive"]
fn seq_u8_3() -> io::Result<()> {
let mut core = RingBox::<T>::default();
let seq = Seq::default();
let mut rdr = RingReader::new((&mut core).into(), seq);
let mut seq = Seq::default();
for _ in 0..T::RING_SIZE * 2 {
rdr.fill()?;
let view = rdr.view();
let view_len = view.len();
assert_eq!(rdr.len(), view.len());
assert!(RingReader::<Seq, T>::VIEW_LIMIT <= view_len);
let buf = view.short_bytes();
let buf_len = buf.len();
assert_eq!(buf_len, T::RING_LIMIT as usize);
{
let mut seq = seq;
for &b in buf.iter() {
assert_eq!(seq.next().unwrap(), b);
}
}
seq.next().unwrap();
rdr.skip(1);
}
Ok(())
}
#[test]
#[ignore = "expensive"]
fn seq_u8_4() -> io::Result<()> {
let mut core = RingBox::<T>::default();
for n in 0..T::RING_SIZE as usize * 2 {
let seq = Read::take(Seq::default(), n as u64);
let mut rdr = RingReader::new((&mut core).into(), seq);
let mut seq = Seq::default();
rdr.fill()?;
assert_eq!(rdr.len(), n.min(T::RING_SIZE as usize));
let mut view = rdr.view();
assert_eq!(rdr.len(), view.len());
while view.len() != 0 {
let buf = view.short_bytes();
let buf_len = buf.len();
for &b in buf.iter() {
assert_eq!(seq.next().unwrap(), b);
}
view.skip(buf_len);
}
}
Ok(())
}
}