nonogrid 0.7.3

Efficient nonogram solver
Documentation
use std::hash::Hash;

use lru::LruCache;

/// The copy of 'cached' crate's trait
/// <https://github.com/jaemk/cached/blob/master/src/stores.rs>
pub trait Cached<K, V> {
    fn cache_get(&mut self, key: &K) -> Option<&V>;
    fn cache_set(&mut self, key: K, val: V);
    fn cache_remove(&mut self, k: &K) -> Option<V>;
    fn cache_clear(&mut self);
    fn cache_size(&self) -> usize;
    fn cache_hits(&self) -> Option<u32>;
    fn cache_misses(&self) -> Option<u32>;
}

#[derive(Debug)]
pub struct GrowableCache<K, V>
where
    K: Eq + Hash,
{
    store: LruCache<K, V>,
    hits: u32,
    misses: u32,
}

impl<K: Hash + Eq, V> GrowableCache<K, V> {
    pub fn with_capacity(size: usize) -> Self {
        Self {
            store: LruCache::new(size),
            hits: 0,
            misses: 0,
        }
    }
}

impl<K: Hash + Eq, V> Cached<K, V> for GrowableCache<K, V> {
    fn cache_get(&mut self, key: &K) -> Option<&V> {
        #![allow(clippy::option_if_let_else)]
        if let Some(v) = self.store.get(key) {
            self.hits += 1;
            Some(v)
        } else {
            self.misses += 1;
            None
        }
    }
    fn cache_set(&mut self, key: K, val: V) {
        let _old_value = self.store.put(key, val);
    }
    fn cache_remove(&mut self, k: &K) -> Option<V> {
        self.store.pop(k)
    }
    fn cache_clear(&mut self) {
        self.store.clear();
    }
    fn cache_size(&self) -> usize {
        self.store.len()
    }
    fn cache_hits(&self) -> Option<u32> {
        Some(self.hits)
    }
    fn cache_misses(&self) -> Option<u32> {
        Some(self.misses)
    }
}

pub fn cache_info<K, V, C>(cache: &C) -> (usize, u32, f64)
where
    C: Cached<K, V>,
{
    if cache.cache_size() > 0 {
        let hits = cache.cache_hits().unwrap_or(0);
        let misses = cache.cache_misses().unwrap_or(0);
        let hit_rate = if hits == 0 {
            0.0
        } else {
            f64::from(hits) / f64::from(hits + misses)
        };

        (cache.cache_size(), hits, hit_rate)
    } else {
        (0, 0, 0.0)
    }
}