ruyi 0.1.6

An event-driven framework for non-blocking, asynchronous I/O in Rust
Documentation
use std::io::{self, Read};
use std::ptr;

use super::{read, ReadBlock, ByteBuf};

pub struct Reader<'a> {
    inner: &'a mut ByteBuf,
}

#[inline]
pub(super) fn new<'a>(inner: &'a mut ByteBuf) -> Reader<'a> {
    Reader { inner }
}

impl<'a> Iterator for Reader<'a> {
    type Item = ReadBlock<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        while self.inner.pos() < self.inner.num_of_blocks() {
            let i = self.inner.pos();
            let block = unsafe { &mut *self.inner.mut_ptr_at(i) };
            if !block.is_empty() {
                return Some(read::new(block));
            }
            self.inner.inc_pos();
        }
        None
    }
}

impl<'a> Read for Reader<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut n = buf.len();
        let mut dst_ptr = buf.as_mut_ptr();
        for mut block in self {
            let len = block.len();
            let src_off = block.read_pos();
            if len >= n {
                unsafe {
                    ptr::copy_nonoverlapping(block.as_ptr().offset(src_off as isize), dst_ptr, n);
                }
                block.set_read_pos(src_off + n);
                return Ok(buf.len());
            } else {
                unsafe {
                    ptr::copy_nonoverlapping(block.as_ptr().offset(src_off as isize), dst_ptr, len);
                    dst_ptr = dst_ptr.offset(len as isize);
                }
                n -= len;
                let write_pos = block.write_pos();
                block.set_read_pos(write_pos);
            }
        }
        Ok(buf.len() - n)
    }
}