1#[cfg(feature = "cache")]
2use std::collections::HashMap;
3#[cfg(feature = "cache")]
4use std::sync::{Arc, Mutex};
5use std::time::{Duration, Instant};
6
7use crate::threat::ThreatType;
8
9#[derive(Debug, Clone)]
11pub struct CacheEntry {
12 pub threat_type: Option<ThreatType>,
13 pub timestamp: Instant,
14 pub ttl: Duration,
15}
16
17impl CacheEntry {
18 pub fn new(threat_type: Option<ThreatType>, ttl: Duration) -> Self {
19 Self {
20 threat_type,
21 timestamp: Instant::now(),
22 ttl,
23 }
24 }
25
26 pub fn is_expired(&self) -> bool {
27 self.timestamp.elapsed() > self.ttl
28 }
29}
30
31#[cfg(feature = "cache")]
32#[derive(Debug, Clone)]
34pub struct Cache {
35 inner: Arc<Mutex<HashMap<String, CacheEntry>>>,
36 default_ttl: Duration,
37}
38
39#[cfg(feature = "cache")]
40impl Cache {
41 pub fn new() -> Self {
42 Self {
43 inner: Arc::new(Mutex::new(HashMap::new())),
44 default_ttl: Duration::from_secs(300), }
46 }
47
48 pub fn with_ttl(ttl: Duration) -> Self {
49 Self {
50 inner: Arc::new(Mutex::new(HashMap::new())),
51 default_ttl: ttl,
52 }
53 }
54
55 pub fn get(&self, key: &str) -> Option<Option<ThreatType>> {
57 let mut cache = self.inner.lock().unwrap();
58
59 if let Some(entry) = cache.get(key) {
60 if !entry.is_expired() {
61 return Some(entry.threat_type.clone());
62 } else {
63 cache.remove(key);
65 }
66 }
67
68 None
69 }
70
71 pub fn set(&self, key: String, threat_type: Option<ThreatType>) {
73 let entry = CacheEntry::new(threat_type, self.default_ttl);
74 let mut cache = self.inner.lock().unwrap();
75 cache.insert(key, entry);
76 }
77
78 pub fn cleanup_expired(&self) {
80 let mut cache = self.inner.lock().unwrap();
81 cache.retain(|_, entry| !entry.is_expired());
82 }
83
84 pub fn size(&self) -> usize {
86 let cache = self.inner.lock().unwrap();
87 cache.len()
88 }
89
90 pub fn clear(&self) {
92 let mut cache = self.inner.lock().unwrap();
93 cache.clear();
94 }
95}
96
97#[cfg(feature = "cache")]
98impl Default for Cache {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104#[cfg(not(feature = "cache"))]
105#[derive(Debug, Clone)]
107pub struct Cache;
108
109#[cfg(not(feature = "cache"))]
110impl Cache {
111 pub fn new() -> Self {
112 Cache
113 }
114
115 pub fn with_ttl(_ttl: Duration) -> Self {
116 Cache
117 }
118
119 pub fn get(&self, _key: &str) -> Option<Option<ThreatType>> {
120 None
121 }
122
123 pub fn set(&self, _key: String, _threat_type: Option<ThreatType>) {
124 }
126
127 pub fn cleanup_expired(&self) {
128 }
130
131 pub fn size(&self) -> usize {
132 0
133 }
134
135 pub fn clear(&self) {
136 }
138}
139
140#[cfg(not(feature = "cache"))]
141impl Default for Cache {
142 fn default() -> Self {
143 Self::new()
144 }
145}