use std::cell::RefCell;
use std::rc::Rc;
pub(crate) enum Step<T, R> {
Value(T),
Done(R),
}
pub(crate) trait Reader<T, R> {
fn next(&mut self) -> Step<T, R>;
}
impl<T, R> Reader<T, R> for Box<dyn Reader<T, R>> {
fn next(&mut self) -> Step<T, R> {
(**self).next()
}
}
pub(crate) type BoxReader<T, R> = Box<dyn Reader<T, R>>;
pub(crate) struct EmptyReader<R> {
value: Option<R>,
}
impl<R: Default> Default for EmptyReader<R> {
fn default() -> Self {
EmptyReader {
value: Some(R::default()),
}
}
}
impl<T, R> Reader<T, R> for EmptyReader<R> {
fn next(&mut self) -> Step<T, R> {
Step::Done(self.value.take().expect("empty reader polled twice"))
}
}
pub(crate) fn empty_reader<T, R: Default + 'static>() -> BoxReader<T, R>
where
T: 'static,
{
Box::new(EmptyReader::<R>::default())
}
pub(crate) struct ArrayReader<T, R> {
items: std::vec::IntoIter<T>,
value: Option<R>,
}
impl<T, R: Default> ArrayReader<T, R> {
pub(crate) fn new(items: Vec<T>) -> Self {
ArrayReader {
items: items.into_iter(),
value: Some(R::default()),
}
}
}
impl<T, R> Reader<T, R> for ArrayReader<T, R> {
fn next(&mut self) -> Step<T, R> {
match self.items.next() {
Some(item) => Step::Value(item),
None => Step::Done(self.value.take().expect("array reader polled past end")),
}
}
}
pub(crate) fn build_array_reader<T: 'static, R: Default + 'static>(
items: Vec<T>,
) -> BoxReader<T, R> {
Box::new(ArrayReader::new(items))
}
pub(crate) struct ChainReader<T> {
readers: std::vec::IntoIter<BoxReader<T, ()>>,
current: Option<BoxReader<T, ()>>,
}
impl<T: 'static> ChainReader<T> {
pub(crate) fn new(readers: Vec<BoxReader<T, ()>>) -> Self {
let mut iter = readers.into_iter();
let current = iter.next();
ChainReader {
readers: iter,
current,
}
}
}
impl<T> Reader<T, ()> for ChainReader<T> {
fn next(&mut self) -> Step<T, ()> {
loop {
match &mut self.current {
Some(reader) => match reader.next() {
Step::Value(value) => return Step::Value(value),
Step::Done(()) => {
self.current = self.readers.next();
}
},
None => return Step::Done(()),
}
}
}
}
pub(crate) fn chain_readers<T: 'static>(readers: Vec<BoxReader<T, ()>>) -> BoxReader<T, ()> {
Box::new(ChainReader::new(readers))
}
struct ForkShared<T, R> {
source: BoxReader<T, R>,
buffer: Vec<T>,
return_value: Option<R>,
}
pub(crate) struct ForkableReader<T: Clone, R: Clone> {
shared: Rc<RefCell<ForkShared<T, R>>>,
cursor: usize,
}
impl<T: Clone, R: Clone> ForkableReader<T, R> {
pub(crate) fn new(source: BoxReader<T, R>) -> Self {
ForkableReader {
shared: Rc::new(RefCell::new(ForkShared {
source,
buffer: Vec::new(),
return_value: None,
})),
cursor: 0,
}
}
pub(crate) fn fork(&self) -> Self {
ForkableReader {
shared: Rc::clone(&self.shared),
cursor: self.cursor,
}
}
}
impl<T: Clone, R: Clone> Reader<T, R> for ForkableReader<T, R> {
fn next(&mut self) -> Step<T, R> {
let mut shared = self.shared.borrow_mut();
if self.cursor < shared.buffer.len() {
let value = shared.buffer[self.cursor].clone();
self.cursor += 1;
return Step::Value(value);
}
if let Some(ret) = &shared.return_value {
return Step::Done(ret.clone());
}
match shared.source.next() {
Step::Value(value) => {
shared.buffer.push(value.clone());
self.cursor += 1;
Step::Value(value)
}
Step::Done(ret) => {
shared.return_value = Some(ret.clone());
Step::Done(ret)
}
}
}
}
pub(crate) fn build_forkable_reader<T: Clone, R: Clone>(
source: BoxReader<T, R>,
) -> ForkableReader<T, R> {
ForkableReader::new(source)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chain_yields_in_order() {
let mut reader = chain_readers(vec![
build_array_reader(vec![0, 1]),
build_array_reader(vec![2, 3]),
]);
assert!(matches!(reader.next(), Step::Value(0)));
assert!(matches!(reader.next(), Step::Value(1)));
assert!(matches!(reader.next(), Step::Value(2)));
assert!(matches!(reader.next(), Step::Value(3)));
assert!(matches!(reader.next(), Step::Done(())));
}
#[test]
fn empty_is_immediately_done() {
let mut reader: BoxReader<i32, ()> = empty_reader();
assert!(matches!(reader.next(), Step::Done(())));
}
#[test]
fn fork_replays() {
let source: BoxReader<i32, ()> = build_array_reader(vec![1, 2, 3]);
let mut a = build_forkable_reader(source);
assert!(matches!(a.next(), Step::Value(1)));
let mut b = a.fork();
assert!(matches!(a.next(), Step::Value(2)));
assert!(matches!(b.next(), Step::Value(2)));
assert!(matches!(b.next(), Step::Value(3)));
assert!(matches!(a.next(), Step::Value(3)));
assert!(matches!(a.next(), Step::Done(())));
assert!(matches!(b.next(), Step::Done(())));
}
}