1#[derive(Copy, Clone)]
2struct Entry {
3    key: u64,
4    count: u64,
5    depth: i16,
6}
7
8pub struct Cache {
9    entries: Box<[Entry]>,
10    mask: usize,
11}
12
13impl Cache {
14    pub fn new(size_bytes: usize) -> Result<Cache, String> {
15        if size_bytes.count_ones() != 1 {
16            return Err("Cache size must be 2^N".to_string());
17        }
18
19        if size_bytes < 1024 {
20            return Err("Cache size must be at least 1024 bytes".to_string());
21        }
22
23        let size = size_bytes / 16;
24
25        let vec = vec![
26            Entry {
27                key: 0,
28                count: 0,
29                depth: -1,
30            };
31            size
32        ];
33
34        Ok(Cache {
35            entries: vec.into_boxed_slice(),
36            mask: size - 1,
37        })
38    }
39
40    pub fn probe(&self, key: u64, depth: usize) -> Option<u64> {
41        let idx = (key as usize) & self.mask;
42        let entry = unsafe { self.entries.get_unchecked(idx) };
43
44        if entry.key == key && entry.depth == (depth as i16) {
45            Some(entry.count)
46        } else {
47            None
48        }
49    }
50
51    pub fn save(&mut self, key: u64, count: u64, depth: i16) {
52        let idx = (key as usize) & self.mask;
53        let entry = unsafe { self.entries.get_unchecked_mut(idx) };
54
55        *entry = Entry { key, count, depth }
56    }
57}