#![allow(box_pointers)]
use ::alloc::{vec, vec::Vec};
#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Cache<I: Iterator> {
iter: I,
vec: Vec<I::Item>,
}
impl<I: Iterator> Cache<I> {
#[inline(always)]
pub fn new<II: IntoIterator<IntoIter = I>>(into_iter: II) -> Self {
Self {
iter: into_iter.into_iter(),
vec: vec![],
}
}
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.vec.is_empty()
}
#[inline]
pub fn get(&mut self, index: usize) -> Option<&I::Item> {
loop {
if let cached @ Some(_) = {
let v: *const _ = &self.vec;
#[allow(unsafe_code)]
unsafe { &*v }.get(index)
} {
return cached;
}
self.vec.push(self.iter.next()?);
}
}
}
#[inline(always)]
#[must_use]
pub fn cached<I: IntoIterator>(iter: I) -> Cache<I::IntoIter> {
Cache::new(iter)
}
pub trait Cached: IntoIterator {
#[must_use]
fn cached(self) -> Cache<Self::IntoIter>;
}
impl<I: IntoIterator> Cached for I {
#[inline(always)]
#[must_use]
fn cached(self) -> Cache<Self::IntoIter> {
cached(self)
}
}