use std::io::Read;
use std::ops::IndexMut;
const RUSTLEX_BUFSIZE: usize = 4096;
pub struct RustLexBuffer {
d: Vec<u8>,
valid: bool
}
impl RustLexBuffer {
#[inline(always)]
pub fn len(&self) -> usize {
self.d.len()
}
#[inline(always)]
pub fn get(&self, idx: usize) -> &u8 {
&self.d[idx]
}
#[inline(always)]
pub fn as_slice(&self) -> &[u8] {
&self.d
}
#[inline(always)]
pub fn slice(&self, from: usize, to: usize) -> &[u8] {
&self.d[from..to]
}
#[inline(always)]
pub fn slice_from(&self, from: usize) -> &[u8] {
&self.d[from..]
}
}
#[derive(Copy,Clone)]
pub struct RustLexPos {
pub buf: usize,
pub off: usize
}
impl PartialEq for RustLexPos {
fn eq(&self, other: &RustLexPos) -> bool {
self.buf == other.buf &&
self.off == other.off
}
}
pub struct RustLexLexer<R : Read> {
pub stream: R,
pub inp: Vec<RustLexBuffer>,
pub advance: RustLexPos,
pub pos: RustLexPos,
pub tok: RustLexPos
}
fn vec_resize<T: Clone>(vec: &mut Vec<T>, new_len: usize, value: T) {
let len = vec.len();
if new_len > len {
vec.extend(::std::iter::repeat(value).take(new_len - len));
} else {
vec.truncate(new_len);
}
}
impl<R: ::std::io::Read> RustLexLexer<R> {
fn fill_buf(&mut self) {
let &mut RustLexBuffer {
ref mut d,
ref mut valid
} = self.inp.index_mut(self.pos.buf);
*valid = true;
if d.len() < RUSTLEX_BUFSIZE {
vec_resize(d, RUSTLEX_BUFSIZE, 0);
}
match self.stream.read(&mut ** d) {
Ok(l) => vec_resize(d, l, 0),
Err(_) => d.clear()
};
self.pos.off = 0;
}
pub fn getchar(&mut self) -> Option<u8> {
if self.pos.off == RUSTLEX_BUFSIZE {
let npos = self.pos.buf + 1;
if self.inp.len() > npos && self.inp[npos].valid {
self.pos.buf = npos;
self.pos.off = 0;
} else {
let unused_buffers_count = self.tok.buf;
for i in (0 .. unused_buffers_count) {
self.inp[i].valid = false;
self.inp[i].d.truncate(0);
self.inp.swap(i + unused_buffers_count, i);
}
self.tok.buf -= unused_buffers_count;
self.pos.buf += 1;
self.pos.buf -= unused_buffers_count;
self.advance.buf -= unused_buffers_count;
while self.pos.buf >= self.inp.len() {
self.inp.push(RustLexBuffer {
d: Vec::with_capacity(RUSTLEX_BUFSIZE),
valid: false
});
}
self.fill_buf();
}
} else if self.pos.off >= self.inp[self.pos.buf].len() {
return None
}
let &ch = self.inp[self.pos.buf].get(self.pos.off);
self.pos.off += 1;
Some(ch)
}
pub fn new(stream: R) -> RustLexLexer<R> {
let mut lex = RustLexLexer {
stream: stream,
inp: vec!(RustLexBuffer{
d: Vec::with_capacity(RUSTLEX_BUFSIZE),
valid: false
}),
advance: RustLexPos {
off: 0,
buf: 0
},
pos: RustLexPos {
off: 0,
buf: 0
},
tok: RustLexPos {
off: 0,
buf: 0
}
};
lex.fill_buf();
lex
}
}