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}