#[cfg(test)]
#[allow(rustdoc::invalid_codeblock_attributes)]
mod tests;
extern crate queues;
use queues::*;
use std::{error::*, fmt::Display};
type BoxResult<T> = Result<T,Box<dyn Error>>;
#[derive(Debug)]
pub struct EnqueueWhileIteratorIsEmptyError;
impl Display for EnqueueWhileIteratorIsEmptyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"`cache` or `cache_more` called but the iterator was empty!")
}
}
impl Error for EnqueueWhileIteratorIsEmptyError {}
pub struct IteratorCache<T: Clone>
where
Queue<T>: Default, {
queue: Queue<T>,
iterator: Box<dyn Iterator<Item = T>>,
}
impl<T> IteratorCache<T>
where
T: Clone,
{
pub fn new(iter: impl Iterator<Item = T> + 'static) -> Self {
IteratorCache {
queue: Queue::default(),
iterator: Box::new(iter),
}
}
pub fn cache_more(&mut self, quantity: u32) -> BoxResult<()> {
for _ in 0..quantity {
if let Some(item) = self.iterator.next() {
self.queue.add(item)?;
} else {
return Err(Box::new(EnqueueWhileIteratorIsEmptyError {}));
}
}
Ok(())
}
}
impl<T> Iterator for IteratorCache<T>
where
T: Clone,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if let Ok(item) = self.queue.remove() {
return Some(item);
}
return self.iterator.next();
}
}
pub trait IterateIntoCache: Iterator
where Self::Item: Clone
{
fn cache(self, quantity: u32) -> BoxResult<IteratorCache<Self::Item>>;
fn cache_all(self) -> IteratorCache<Self::Item>;
fn cache_or_all(self, quantity: u32) -> IteratorCache<Self::Item>;
}
impl<'a,T> IterateIntoCache for T
where T: Iterator + 'static,
T::Item: Clone
{
fn cache(self, quantity: u32) -> BoxResult<IteratorCache<Self::Item>> {
let mut cache = IteratorCache::new(self);
cache.cache_more(quantity)?;
Ok(cache)
}
fn cache_all(self) -> IteratorCache<Self::Item> {
let mut cache = IteratorCache::new(self);
loop {
if let Err(_) = cache.cache_more(1) { break; }
}
cache
}
fn cache_or_all(self, quantity: u32) -> IteratorCache<Self::Item> {
let mut cache = IteratorCache::new(self);
for _ in 0..quantity {
if let Err(_) = cache.cache_more(1) { break; }
}
cache
}
}