1#![doc = include_str!("../README.md")]
2
3use std::borrow::Borrow;
4use std::hash::Hash;
5use std::{collections::HashMap, ptr::NonNull};
6
7struct Node<K: Eq + Hash + Clone, V> {
8 key: K,
9 value: V,
10 prev: Option<NonNull<Node<K, V>>>,
11 next: Option<NonNull<Node<K, V>>>,
12 visited: bool,
13}
14
15impl<K: Eq + Hash + Clone, V> Node<K, V> {
16 fn new(key: K, value: V) -> Self {
17 Self {
18 key,
19 value,
20 prev: None,
21 next: None,
22 visited: false,
23 }
24 }
25}
26
27pub struct SieveCache<K: Eq + Hash + Clone, V> {
29 map: HashMap<K, Box<Node<K, V>>>,
30 head: Option<NonNull<Node<K, V>>>,
31 tail: Option<NonNull<Node<K, V>>>,
32 hand: Option<NonNull<Node<K, V>>>,
33 capacity: usize,
34 len: usize,
35}
36
37unsafe impl<K: Eq + Hash + Clone, V> Send for SieveCache<K, V> {}
38
39impl<K: Eq + Hash + Clone, V> SieveCache<K, V> {
40 pub fn new(capacity: usize) -> Result<Self, &'static str> {
42 if capacity == 0 {
43 return Err("capacity must be greater than 0");
44 }
45 Ok(Self {
46 map: HashMap::with_capacity(capacity),
47 head: None,
48 tail: None,
49 hand: None,
50 capacity,
51 len: 0,
52 })
53 }
54
55 #[inline]
57 pub fn capacity(&self) -> usize {
58 self.capacity
59 }
60
61 #[inline]
63 pub fn len(&self) -> usize {
64 self.len
65 }
66
67 #[inline]
69 pub fn is_empty(&self) -> bool {
70 self.len() == 0
71 }
72
73 #[inline]
75 pub fn contains_key<Q>(&mut self, key: &Q) -> bool
76 where
77 Q: Hash + Eq + ?Sized,
78 K: Borrow<Q>,
79 {
80 self.map.contains_key(key)
81 }
82
83 pub fn get<Q>(&mut self, key: &Q) -> Option<&V>
87 where
88 Q: Hash + Eq + ?Sized,
89 K: Borrow<Q>,
90 {
91 let node_ = self.map.get_mut(key)?;
92 node_.visited = true;
93 Some(&node_.value)
94 }
95
96 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
100 where
101 Q: Hash + Eq + ?Sized,
102 K: Borrow<Q>,
103 {
104 let node_ = self.map.get_mut(key)?;
105 node_.visited = true;
106 Some(&mut node_.value)
107 }
108
109 pub fn insert(&mut self, key: K, value: V) -> bool {
114 let node = self.map.get_mut(&key);
115 if let Some(node_) = node {
116 node_.visited = true;
117 node_.value = value;
118 return false;
119 }
120 if self.len >= self.capacity {
121 self.evict();
122 }
123 let node = Box::new(Node::new(key.clone(), value));
124 self.add_node(NonNull::from(node.as_ref()));
125 debug_assert!(!node.visited);
126 self.map.insert(key, node);
127 debug_assert!(self.len < self.capacity);
128 self.len += 1;
129 true
130 }
131
132 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
137 where
138 K: Borrow<Q>,
139 Q: Eq + Hash + ?Sized,
140 {
141 let node_ = self.map.get_mut(key)?;
142 let node__ = NonNull::from(node_.as_ref());
143 if self.hand == Some(node__) {
144 self.hand = node_.as_ref().prev;
145 }
146 let value = self.map.remove(key).map(|node| node.value);
147 self.remove_node(node__);
148 debug_assert!(self.len > 0);
149 self.len -= 1;
150 value
151 }
152
153 fn add_node(&mut self, mut node: NonNull<Node<K, V>>) {
154 unsafe {
155 node.as_mut().next = self.head;
156 node.as_mut().prev = None;
157 if let Some(mut head) = self.head {
158 head.as_mut().prev = Some(node);
159 }
160 }
161 self.head = Some(node);
162 if self.tail.is_none() {
163 self.tail = self.head;
164 }
165 }
166
167 fn remove_node(&mut self, node: NonNull<Node<K, V>>) {
168 unsafe {
169 if let Some(mut prev) = node.as_ref().prev {
170 prev.as_mut().next = node.as_ref().next;
171 } else {
172 self.head = node.as_ref().next;
173 }
174 if let Some(mut next) = node.as_ref().next {
175 next.as_mut().prev = node.as_ref().prev;
176 } else {
177 self.tail = node.as_ref().prev;
178 }
179 }
180 }
181
182 fn evict(&mut self) {
183 let mut node = self.hand.or(self.tail);
184 while node.is_some() {
185 let mut node_ = node.unwrap();
186 unsafe {
187 if !node_.as_ref().visited {
188 break;
189 }
190 node_.as_mut().visited = false;
191 if node_.as_ref().prev.is_some() {
192 node = node_.as_ref().prev;
193 } else {
194 node = self.tail;
195 }
196 }
197 }
198 if let Some(node_) = node {
199 unsafe {
200 self.hand = node_.as_ref().prev;
201 self.map.remove(&node_.as_ref().key);
202 }
203 self.remove_node(node_);
204 debug_assert!(self.len > 0);
205 self.len -= 1;
206 }
207 }
208}
209
210#[test]
211fn test() {
212 let mut cache = SieveCache::new(3).unwrap();
213 assert!(cache.insert("foo".to_string(), "foocontent".to_string()));
214 assert!(cache.insert("bar".to_string(), "barcontent".to_string()));
215 cache.remove("bar");
216 assert!(cache.insert("bar2".to_string(), "bar2content".to_string()));
217 assert!(cache.insert("bar3".to_string(), "bar3content".to_string()));
218 assert_eq!(cache.get("foo"), Some(&"foocontent".to_string()));
219 assert_eq!(cache.get("bar"), None);
220 assert_eq!(cache.get("bar2"), Some(&"bar2content".to_string()));
221 assert_eq!(cache.get("bar3"), Some(&"bar3content".to_string()));
222}
223
224#[test]
225fn test_visited_flag_update() {
226 let mut cache = SieveCache::new(2).unwrap();
227 cache.insert("key1".to_string(), "value1".to_string());
228 cache.insert("key2".to_string(), "value2".to_string());
229 cache.insert("key1".to_string(), "updated".to_string());
231 cache.insert("key3".to_string(), "value3".to_string());
233 assert_eq!(cache.get("key1"), Some(&"updated".to_string()));
234}