dmoj 0.1.5

A Rust crate for providing helpful methods in online judging
Documentation
use std::ptr;
use std::io::Read;

use io::DEFAULT_BUF_SIZE;

pub struct CopyingBufReader<R> {
    inner: R,
    pub buf: Box<[u8]>,
    pub pos: usize,
    pub amt: usize
}

impl<R: Read> CopyingBufReader<R> {
    pub fn new(inner: R) -> CopyingBufReader<R> {
        CopyingBufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
    }

    pub fn with_capacity(capacity: usize, inner: R) -> CopyingBufReader<R> {
        CopyingBufReader {
            inner: inner,
            buf: vec![0; capacity].into_boxed_slice(),
            pos: 0,
            amt: 0
        }
    }

    pub fn refill(&mut self) {
        let buf_kept = self.amt - self.pos;
        let buf_len = self.buf.len();

        unsafe {
            ptr::copy(
                self.buf.as_ptr().offset(self.pos as isize),
                self.buf.as_mut_ptr(),
                buf_kept
            );
        }

        self.amt = buf_kept + self.inner.read(&mut self.buf[buf_kept..buf_len]).unwrap();
        self.pos = 0;
    }

    pub fn peek(&mut self) -> Option<u8> {
        if self.pos == self.amt {
            self.refill();
        }
        
        if self.amt > 0 {
            Some(unsafe { *self.buf.get_unchecked(self.pos) })
        } else {
            None
        }
    }

    pub fn consume(&mut self, amt: usize) {
        assert!(self.pos + amt <= self.amt);
        self.pos += amt;
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let mut buf = CopyingBufReader::with_capacity(4, &b"abcdefghijkl"[..]);
        assert_eq!(buf.peek().unwrap(), b'a');
        assert_eq!(buf.peek().unwrap(), b'a');
        buf.consume(2);
        assert_eq!(buf.peek().unwrap(), b'c');
        buf.consume(1);
        assert_eq!(buf.peek().unwrap(), b'd');
        buf.consume(1);
        assert_eq!(buf.peek().unwrap(), b'e');
        buf.consume(1);
        assert_eq!(buf.peek().unwrap(), b'f');
        buf.refill();
        assert_eq!(buf.peek().unwrap(), b'f');
    }
}