1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/**
Goals:
 - limit global memory use
 - minimize computation time
 
Track globally:
  - average value
  - average age

Track for each entry:
 - age: time since last use
 - count: how often it was used
 - amout of memory used
 - time required to compute the value

 use = count / (age)
 value = time / memory

Don't add:
 - values lower than average

Don't evict:
 - newer values
**/

use std::sync::{Arc};
use async_trait::async_trait;

#[cfg(feature="sync")]
pub mod sync;

#[cfg(feature="async")]
pub mod r#async;

#[cfg(feature="global")]
pub mod global;

#[cfg(not(feature="global"))]
pub mod global {
    use std::sync::Weak;
    use super::CacheControl;

    pub struct GlobalCache;
    impl GlobalCache {
        pub fn register(_: Weak<impl CacheControl>) {}
    }
}

#[async_trait]
pub trait CacheControl: Sync + Send + 'static {
    fn name(&self) -> Option<&str>;
    async fn clean(&self, threshold: f64, time_scale: f64) -> (usize, f64);
}
pub trait ValueSize {
    fn size(&self) -> usize;
}
impl<T: ValueSize, E: ValueSize> ValueSize for Result<T, E> {
    #[inline]
    fn size(&self) -> usize {
        match self {
            &Ok(ref t) => t.size(),
            &Err(ref e) => e.size(),
        }
    }
}
impl<T: ?Sized + ValueSize> ValueSize for Arc<T> {
    #[inline]
    fn size(&self) -> usize {
        ValueSize::size(&**self)
    }
}
impl ValueSize for [u8] {
    #[inline]
    fn size(&self) -> usize {
        self.len()
    }
}
impl<T: ValueSize> ValueSize for Option<T> {
    #[inline]
    fn size(&self) -> usize {
        match *self {
            None => 0,
            Some(ref val) => val.size()
        }
    }
}
impl ValueSize for () {
    #[inline]
    fn size(&self) -> usize {
        0
    }
}
impl ValueSize for String {
    #[inline]
    fn size(&self) -> usize {
        self.capacity()
    }
}