iter_cache.rs

View source code here on GitHub!

Includes

pub struct iter_cache::CachingIterator<I, T> where I: Iterator<Item = T> + 'static, T: Clone + 'static

This struct implements a global cache that maps an iterator-iterated pair to a cache of values. It is mostly intended for use with the prime function generator.

pub fn iter_cache::CachingIterator::new() -> CachingIterator<I, T> where I: Iterator<Item = T> + 'static, T: Clone + 'static
pub fn iter_cache::CachingIterator::default() -> CachingIterator<I, T> where I: Iterator<Item = T> + 'static, T: Clone + 'static
pub fn iter_cache::CachingIterator::next() -> Option<T> where T: Clone + 'static
 1use lazy_static::lazy_static;
 2
 3use std::any::{Any,TypeId};
 4use std::collections::HashMap;
 5use std::sync::{Mutex, RwLock};
 6
 7type CacheVector<T> = Vec<Box<T>>;
 8type CacheMap<T> = HashMap<(TypeId, TypeId), Mutex<CacheVector<T>>>;
 9lazy_static! {
10    static ref CACHE_MAP: RwLock<CacheMap<dyn Any + Send>> = RwLock::new(HashMap::new());
11}
12
13pub fn cache_iterator<I, T>(iterator: I) -> impl Iterator<Item = T>
14where
15    I: Iterator<Item = T> + 'static,
16    T: Copy + Send + 'static
17{
18    return CachingIterator::new(iterator);
19}
20
21#[derive(Clone, Copy, Debug, Hash)]
22pub struct CachingIterator<I, T>
23where
24    I: Iterator<Item = T> + 'static,
25    T: Copy + Send + 'static
26{
27    inner: I,
28    index: usize,
29    inner_index: usize,
30    type_id: (TypeId, TypeId),
31}
32
33impl<I, T> CachingIterator<I, T>
34where
35    I: Iterator<Item = T> + 'static,
36    T: Copy + Send + 'static
37{
38    pub fn new(inner: I) -> Self {
39        CachingIterator {
40            inner,
41            index: 0,
42            inner_index: 0,
43            type_id: (TypeId::of::<I>(), TypeId::of::<T>())
44        }
45    }
46
47    fn initialize_cache(&self) {
48        let mut cache_map = CACHE_MAP.write().unwrap();
49        cache_map.entry(self.type_id)
50            .or_insert_with(|| Mutex::new(Vec::new()));
51    }
52}
53
54impl<I, T> Iterator for CachingIterator<I, T>
55where
56    I: Iterator<Item = T> + 'static,
57    T: Copy + Send + 'static
58{
59    type Item = T;
60
61    fn next(&mut self) -> Option<Self::Item> {
62        self.initialize_cache();
63        let cache_map = CACHE_MAP.read()
64                                 .unwrap();
65        let mut cache = cache_map.get(&self.type_id)
66                                 .expect("Cache for this type should be initialized")
67                                 .lock()
68                                 .unwrap();
69        
70        if self.index < cache.len() {
71            let boxed_item = &cache[self.index];
72            let result = boxed_item.downcast_ref::<T>().unwrap();
73            self.index += 1;
74            return Some(*result);
75        }
76        while self.inner_index < self.index {
77            self.inner.next();
78            self.inner_index += 1;
79        }
80        match self.inner.next() {
81            Some(value) => {
82                cache.push(Box::new(value));
83                self.index += 1;
84                self.inner_index += 1;
85                return Some(value);
86            }
87            None => {
88                return None;
89            }
90        }
91    }
92}