portfu_core 1.3.3

Portfu Core Types and Definitions Library
Documentation
use std::hash::{DefaultHasher, Hash, Hasher};
use std::mem::swap;

pub struct CircularCache<K: Eq + PartialEq + Hash, V, const N: usize> {
    keys: [Option<K>; N],
    hashes: [Option<u64>; N],
    values: [Option<V>; N],
    index: Option<usize>,
}
impl<K: Eq + PartialEq + Hash, V, const N: usize> Default for CircularCache<K, V, N> {
    fn default() -> Self {
        Self::new()
    }
}
impl<K: Eq + PartialEq + Hash, V, const N: usize> CircularCache<K, V, N> {
    const KEY_REPEAT_VALUE: Option<K> = None;
    const HASH_REPEAT_VALUE: Option<u64> = None;
    const VAL_REPEAT_VALUE: Option<V> = None;

    pub fn new() -> Self {
        Self {
            keys: [Self::KEY_REPEAT_VALUE; N],
            hashes: [Self::HASH_REPEAT_VALUE; N],
            values: [Self::VAL_REPEAT_VALUE; N],
            index: None,
        }
    }
    pub fn keys(&self) -> &[Option<K>] {
        &self.keys
    }
    pub fn values(&self) -> &[Option<V>] {
        &self.values
    }
    pub fn first(&self, key: &K) -> Option<&V> {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        let search_hash = hasher.finish();
        for (i, k) in self.hashes.iter().enumerate() {
            if *k == Some(search_hash) {
                return self.values[i].as_ref();
            }
        }
        None
    }
    pub fn get(&self, key: &K) -> Vec<&Option<V>> {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        let search_hash = hasher.finish();
        let mut slices = vec![];
        for (i, k) in self.hashes.iter().enumerate() {
            if *k == Some(search_hash) {
                slices.push(&self.values[i])
            }
        }
        slices
    }
    pub fn get_all(&self, key: &K) -> Vec<&Option<V>> {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        let search_hash = hasher.finish();
        let mut slices = vec![];
        for (i, k) in self.hashes.iter().enumerate() {
            if *k == Some(search_hash) {
                slices.push(&self.values[i])
            }
        }
        slices
    }
    pub fn contains(&self, key: &K) -> bool {
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        let search_hash = hasher.finish();
        self.hashes.contains(&Some(search_hash))
    }
    pub fn insert(&mut self, key: K, value: V) -> (Option<K>, Option<V>) {
        let index = if let Some(index) = &mut self.index {
            *index = index.wrapping_add(1);
            *index
        } else {
            self.index = Some(0);
            0
        };
        let mut hasher = DefaultHasher::new();
        key.hash(&mut hasher);
        let mut hash = Some(hasher.finish());
        let mut key = Some(key);
        let mut value = Some(value);
        swap(&mut self.keys[index % N], &mut key);
        swap(&mut self.hashes[index % N], &mut hash);
        swap(&mut self.values[index % N], &mut value);
        (key, value)
    }
    pub fn replace(&mut self, key: K, value: V) -> Option<V> {
        let key = Some(key);
        for (i, k) in self.keys.iter().enumerate() {
            if *k == key {
                let mut value = Some(value);
                swap(&mut self.values[i], &mut value);
                return value;
            }
        }
        None
    }
    pub fn slice(&self) -> &[Option<V>] {
        match self.index {
            None => &[],
            Some(index) => {
                if index < N {
                    &self.values[0..index]
                } else {
                    &self.values
                }
            }
        }
    }
}