ryna/structures/
precedence_cache.rs1use rustc_hash::FxHashMap;
2
3#[derive(Debug)]
4pub struct PrecedenceCache<T> {
5 inner: FxHashMap<usize, (Vec<usize>, Vec<T>)> }
7
8impl<T> Default for PrecedenceCache<T> {
9 fn default() -> Self {
10 Self { inner: Default::default() }
11 }
12}
13
14impl<T> PrecedenceCache<T> {
15 pub fn new() -> Self {
16 PrecedenceCache { inner: FxHashMap::default() }
17 }
18
19 pub fn get(&self, position: usize, precedence: usize) -> Option<&T> {
20 if let Some(v) = self.inner.get(&position) {
21 let (precs, vals) = v;
22
23 return match precs.binary_search(&precedence) {
25 Err(pos) if pos > 0 => Some(&vals[pos - 1]),
26 Ok(pos) => Some(&vals[pos]),
27
28 _ => None
29 }
30 }
31
32 None
33 }
34
35 pub fn set(&mut self, position: usize, precedence: usize, v: T) {
36 let (precs, vals) = self.inner.entry(position).or_default();
37
38 if let Err(pos) = precs.binary_search(&precedence) {
39 precs.insert(pos, precedence);
40 vals.insert(pos, v);
41 }
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::PrecedenceCache;
48
49 #[test]
50 fn precedence_cache() {
51 let mut cache = PrecedenceCache::<&str>::new();
52
53 cache.set(0, 10, "Test 1");
54 cache.set(0, 20, "Test 2");
55 cache.set(0, 15, "Test 3");
56 cache.set(0, 5, "Test 4");
57
58 assert_eq!(cache.get(0, 10), Some(&"Test 1"));
59 assert_eq!(cache.get(0, 14), Some(&"Test 1"));
60 assert_eq!(cache.get(0, 15), Some(&"Test 3"));
61 assert_eq!(cache.get(0, 7), Some(&"Test 4"));
62 assert_eq!(cache.get(0, 2), None);
63 assert_eq!(cache.get(0, 100), Some(&"Test 2"));
64 assert_eq!(cache.get(1, 0), None);
65 }
66}