Skip to main content

wp_knowledge/
cache.rs

1use std::collections::HashMap;
2use std::net::IpAddr;
3use std::num::NonZeroUsize;
4
5use lru::LruCache;
6use wp_model_core::model::{DataField, FValueStr, Value};
7
8#[derive(Debug, Clone)]
9pub struct FieldQueryCache {
10    str_idx: HashMap<FValueStr, usize>,
11    i64_idx: HashMap<i64, usize>,
12    ip_idx: HashMap<IpAddr, usize>,
13    cache_data: LruCache<EnumSizeIndex, Vec<DataField>>,
14    idx_num: usize,
15}
16
17impl Default for FieldQueryCache {
18    fn default() -> Self {
19        Self::with_capacity(100)
20    }
21}
22
23impl FieldQueryCache {
24    pub fn with_capacity(size: usize) -> Self {
25        let size = size.max(1);
26        Self {
27            str_idx: HashMap::new(),
28            i64_idx: HashMap::new(),
29            ip_idx: HashMap::new(),
30            cache_data: LruCache::new(NonZeroUsize::new(size).expect("non-zero cache size")),
31            idx_num: 0,
32        }
33    }
34
35    fn get_idx(&self, param: &DataField) -> Option<usize> {
36        match param.get_value() {
37            Value::Chars(v) => self.str_idx.get(v).copied(),
38            Value::Digit(v) => self.i64_idx.get(v).copied(),
39            Value::IpAddr(v) => self.ip_idx.get(v).copied(),
40            _ => None,
41        }
42    }
43
44    fn try_up_idx(&mut self, param: &DataField) -> Option<usize> {
45        match param.get_value() {
46            Value::Chars(v) => {
47                if let Some(idx) = self.str_idx.get(v) {
48                    Some(*idx)
49                } else {
50                    self.idx_num += 1;
51                    self.str_idx.insert(v.clone(), self.idx_num);
52                    Some(self.idx_num)
53                }
54            }
55            Value::Digit(v) => {
56                if let Some(idx) = self.i64_idx.get(v) {
57                    Some(*idx)
58                } else {
59                    self.idx_num += 1;
60                    self.i64_idx.insert(*v, self.idx_num);
61                    Some(self.idx_num)
62                }
63            }
64            Value::IpAddr(v) => {
65                if let Some(idx) = self.ip_idx.get(v) {
66                    Some(*idx)
67                } else {
68                    self.idx_num += 1;
69                    self.ip_idx.insert(*v, self.idx_num);
70                    Some(self.idx_num)
71                }
72            }
73            _ => None,
74        }
75    }
76}
77
78#[derive(PartialEq, Eq, Hash, Debug, Clone)]
79pub enum EnumSizeIndex {
80    Idx1(usize),
81    Idx2(usize, usize),
82    Idx3(usize, usize, usize),
83    Idx4(usize, usize, usize, usize),
84    Idx5(usize, usize, usize, usize, usize),
85    Idx6(usize, usize, usize, usize, usize, usize),
86}
87
88pub trait CacheAble<P, T, const N: usize> {
89    fn save(&mut self, params: &[P; N], result: T);
90    fn fetch(&self, params: &[P; N]) -> Option<&T>;
91}
92
93impl CacheAble<DataField, Vec<DataField>, 1> for FieldQueryCache {
94    fn save(&mut self, params: &[DataField; 1], result: Vec<DataField>) {
95        if let Some(i0) = self.try_up_idx(&params[0]) {
96            let idxs = EnumSizeIndex::Idx1(i0);
97            self.cache_data.put(idxs, result);
98        }
99    }
100
101    fn fetch(&self, params: &[DataField; 1]) -> Option<&Vec<DataField>> {
102        if let Some(i0) = self.get_idx(&params[0]) {
103            let idxs = EnumSizeIndex::Idx1(i0);
104            return self.cache_data.peek(&idxs);
105        }
106        None
107    }
108}
109
110impl CacheAble<DataField, Vec<DataField>, 2> for FieldQueryCache {
111    fn save(&mut self, params: &[DataField; 2], result: Vec<DataField>) {
112        if let (Some(i0), Some(i1)) = (self.try_up_idx(&params[0]), self.try_up_idx(&params[1])) {
113            let idxs = EnumSizeIndex::Idx2(i0, i1);
114            self.cache_data.put(idxs, result);
115        }
116    }
117
118    fn fetch(&self, params: &[DataField; 2]) -> Option<&Vec<DataField>> {
119        if let (Some(i0), Some(i1)) = (self.get_idx(&params[0]), self.get_idx(&params[1])) {
120            let idxs = EnumSizeIndex::Idx2(i0, i1);
121            return self.cache_data.peek(&idxs);
122        }
123        None
124    }
125}
126
127impl CacheAble<DataField, Vec<DataField>, 3> for FieldQueryCache {
128    fn save(&mut self, params: &[DataField; 3], result: Vec<DataField>) {
129        if let (Some(i0), Some(i1), Some(i2)) = (
130            self.try_up_idx(&params[0]),
131            self.try_up_idx(&params[1]),
132            self.try_up_idx(&params[2]),
133        ) {
134            let idxs = EnumSizeIndex::Idx3(i0, i1, i2);
135            self.cache_data.put(idxs, result);
136        }
137    }
138
139    fn fetch(&self, params: &[DataField; 3]) -> Option<&Vec<DataField>> {
140        if let (Some(i0), Some(i1), Some(i2)) = (
141            self.get_idx(&params[0]),
142            self.get_idx(&params[1]),
143            self.get_idx(&params[2]),
144        ) {
145            let idxs = EnumSizeIndex::Idx3(i0, i1, i2);
146            return self.cache_data.peek(&idxs);
147        }
148        None
149    }
150}
151
152impl CacheAble<DataField, Vec<DataField>, 4> for FieldQueryCache {
153    fn save(&mut self, params: &[DataField; 4], result: Vec<DataField>) {
154        if let (Some(i0), Some(i1), Some(i2), Some(i3)) = (
155            self.try_up_idx(&params[0]),
156            self.try_up_idx(&params[1]),
157            self.try_up_idx(&params[2]),
158            self.try_up_idx(&params[3]),
159        ) {
160            let idxs = EnumSizeIndex::Idx4(i0, i1, i2, i3);
161            self.cache_data.put(idxs, result);
162        }
163    }
164
165    fn fetch(&self, params: &[DataField; 4]) -> Option<&Vec<DataField>> {
166        if let (Some(i0), Some(i1), Some(i2), Some(i3)) = (
167            self.get_idx(&params[0]),
168            self.get_idx(&params[1]),
169            self.get_idx(&params[2]),
170            self.get_idx(&params[3]),
171        ) {
172            let idxs = EnumSizeIndex::Idx4(i0, i1, i2, i3);
173            return self.cache_data.peek(&idxs);
174        }
175        None
176    }
177}
178
179impl CacheAble<DataField, Vec<DataField>, 5> for FieldQueryCache {
180    fn save(&mut self, params: &[DataField; 5], result: Vec<DataField>) {
181        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4)) = (
182            self.try_up_idx(&params[0]),
183            self.try_up_idx(&params[1]),
184            self.try_up_idx(&params[2]),
185            self.try_up_idx(&params[3]),
186            self.try_up_idx(&params[4]),
187        ) {
188            let idxs = EnumSizeIndex::Idx5(i0, i1, i2, i3, i4);
189            self.cache_data.put(idxs, result);
190        }
191    }
192
193    fn fetch(&self, params: &[DataField; 5]) -> Option<&Vec<DataField>> {
194        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4)) = (
195            self.get_idx(&params[0]),
196            self.get_idx(&params[1]),
197            self.get_idx(&params[2]),
198            self.get_idx(&params[3]),
199            self.get_idx(&params[4]),
200        ) {
201            let idxs = EnumSizeIndex::Idx5(i0, i1, i2, i3, i4);
202            return self.cache_data.peek(&idxs);
203        }
204        None
205    }
206}
207
208impl CacheAble<DataField, Vec<DataField>, 6> for FieldQueryCache {
209    fn save(&mut self, params: &[DataField; 6], result: Vec<DataField>) {
210        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4), Some(i5)) = (
211            self.try_up_idx(&params[0]),
212            self.try_up_idx(&params[1]),
213            self.try_up_idx(&params[2]),
214            self.try_up_idx(&params[3]),
215            self.try_up_idx(&params[4]),
216            self.try_up_idx(&params[5]),
217        ) {
218            let idxs = EnumSizeIndex::Idx6(i0, i1, i2, i3, i4, i5);
219            self.cache_data.put(idxs, result);
220        }
221    }
222
223    fn fetch(&self, params: &[DataField; 6]) -> Option<&Vec<DataField>> {
224        if let (Some(i0), Some(i1), Some(i2), Some(i3), Some(i4), Some(i5)) = (
225            self.get_idx(&params[0]),
226            self.get_idx(&params[1]),
227            self.get_idx(&params[2]),
228            self.get_idx(&params[3]),
229            self.get_idx(&params[4]),
230            self.get_idx(&params[5]),
231        ) {
232            let idxs = EnumSizeIndex::Idx6(i0, i1, i2, i3, i4, i5);
233            return self.cache_data.peek(&idxs);
234        }
235        None
236    }
237}