use std::cmp::min;
pub struct Stream<'a, T> {
index: usize,
data: &'a [T],
}
impl<'a, T: Copy> Stream<'a, T> {
pub fn current_copied(&self) -> Option<T> {
self.data.get(self.index).copied()
}
pub fn current_unchecked(&self) -> T {
self.data[self.index]
}
pub fn next_copied(&mut self) -> Option<T> {
self.skip();
self.data.get(self.index).copied()
}
pub fn peek_back_copied(&self) -> Option<T> {
self.data.get(self.position() - 1).copied()
}
}
impl<'a, T: Eq + Copy> Stream<'a, T> {
pub fn next_if_current_is(&mut self, expect: T) -> Option<T> {
self.next_if_current_present_in(&[expect])
}
pub fn next_if_current_present_in(&mut self, expect: &[T]) -> Option<T> {
let c = self.current_copied()?;
if expect.contains(&c) {
self.skip();
return Some(c);
}
None
}
pub fn skip_if_current_is(&mut self, expect: T) -> bool {
self.next_if_current_is(expect)
.map(|c| c == expect)
.unwrap_or(false)
}
}
impl<'a, T> Stream<'a, T> {
pub fn new(data: &'a [T]) -> Stream<T> {
Self { data, index: 0 }
}
pub fn current(&self) -> Option<&T> {
self.data.get(self.index)
}
pub fn is_eof(&self) -> bool {
self.index >= self.data.len()
}
pub fn length(&self) -> usize {
self.data.len()
}
pub fn next_entry(&mut self) -> Option<&T> {
self.data.get(self.index + 1).map(|c| {
self.skip();
c
})
}
pub fn next_unchecked(&mut self) -> &T {
self.skip();
self.data.get(self.index).unwrap()
}
pub fn peek(&self) -> Option<&T> {
self.data.get(self.position() + 1)
}
pub fn peek_back(&self) -> Option<&T> {
self.data.get(self.position() - 1)
}
pub fn position(&self) -> usize {
self.index
}
pub fn skip(&mut self) {
self.index += 1;
}
pub fn skip_n(&mut self, n: usize) {
self.index += n;
}
pub fn unskip(&mut self) {
self.index -= 1;
}
pub fn slice(&self, from: usize, to: usize) -> &'a [T] {
&self.data[from..min(self.data.len(), to)]
}
pub fn slice_unchecked(&self, from: usize, to: usize) -> &'a [T] {
&self.data[from..to]
}
pub fn slice_len(&self, from: usize, len: usize) -> &'a [T] {
self.slice(from, self.index + len)
}
}