1use core::alloc::Layout;
9use core::cmp::Ordering;
10use core::hash::{self, BuildHasher, Hash};
11use core::marker::PhantomData;
12use core::ptr::{self, NonNull};
13use core::{borrow, mem};
14
15use nginx_sys::{
16 ngx_rbt_red, ngx_rbtree_data, ngx_rbtree_delete, ngx_rbtree_init, ngx_rbtree_insert,
17 ngx_rbtree_key_t, ngx_rbtree_min, ngx_rbtree_next, ngx_rbtree_node_t, ngx_rbtree_t,
18};
19
20use crate::allocator::{self, AllocError, Allocator};
21
22pub struct NgxRbTreeIter<'a> {
29 tree: NonNull<ngx_rbtree_t>,
30 node: *mut ngx_rbtree_node_t,
31 _lifetime: PhantomData<&'a ()>,
32}
33
34impl<'a> NgxRbTreeIter<'a> {
35 pub unsafe fn new(tree: NonNull<ngx_rbtree_t>) -> Self {
41 let t = unsafe { tree.as_ref() };
42 let node = if ptr::addr_eq(t.root, t.sentinel) {
43 ptr::null_mut()
45 } else {
46 unsafe { ngx_rbtree_min(t.root, t.sentinel) }
47 };
48
49 Self {
50 tree,
51 node,
52 _lifetime: PhantomData,
53 }
54 }
55}
56
57impl<'a> Iterator for NgxRbTreeIter<'a> {
58 type Item = NonNull<ngx_rbtree_node_t>;
59
60 fn next(&mut self) -> Option<Self::Item> {
61 let item = NonNull::new(self.node)?;
62 self.node = unsafe { ngx_rbtree_next(self.tree.as_mut(), self.node) };
64 Some(item)
65 }
66}
67
68#[allow(deprecated)]
69type BuildMapHasher = core::hash::BuildHasherDefault<hash::SipHasher>;
70
71#[derive(Debug)]
78pub struct RbTreeMap<K, V, A>
79where
80 A: Allocator,
81{
82 tree: ngx_rbtree_t,
83 sentinel: NonNull<ngx_rbtree_node_t>,
84 alloc: A,
85 _kv_type: PhantomData<(K, V)>,
86}
87
88struct MapEntry<K, V> {
92 node: ngx_rbtree_node_t,
93 key: K,
94 value: V,
95}
96
97impl<K, V> MapEntry<K, V>
98where
99 K: Hash,
100{
101 fn new(key: K, value: V) -> Self {
102 let mut node: ngx_rbtree_node_t = unsafe { mem::zeroed() };
103 node.key = BuildMapHasher::default().hash_one(&key) as ngx_rbtree_key_t;
104
105 Self { node, key, value }
106 }
107
108 fn into_kv(self) -> (K, V) {
109 (self.key, self.value)
110 }
111}
112
113pub struct Iter<'a, K: 'a, V: 'a>(NgxRbTreeIter<'a>, PhantomData<(K, V)>);
115
116impl<'a, K: 'a, V: 'a> Iter<'a, K, V> {
117 pub fn new<A: Allocator>(tree: &'a RbTreeMap<K, V, A>) -> Self {
119 let rbtree = NonNull::from(&tree.tree);
121 Self(unsafe { NgxRbTreeIter::new(rbtree) }, Default::default())
123 }
124}
125
126impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> {
127 type Item = (&'a K, &'a V);
128
129 fn next(&mut self) -> Option<Self::Item> {
130 let item = self.0.next()?;
131 let item = unsafe { ngx_rbtree_data!(item, MapEntry<K, V>, node).as_ref() };
132 Some((&item.key, &item.value))
133 }
134}
135
136pub struct IterMut<'a, K: 'a, V: 'a>(NgxRbTreeIter<'a>, PhantomData<(K, V)>);
138
139impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> {
140 pub fn new<A: Allocator>(tree: &'a mut RbTreeMap<K, V, A>) -> Self {
142 let rbtree = NonNull::from(&mut tree.tree);
144 Self(unsafe { NgxRbTreeIter::new(rbtree) }, Default::default())
146 }
147}
148
149impl<'a, K: 'a, V: 'a> Iterator for IterMut<'a, K, V> {
150 type Item = (&'a K, &'a mut V);
151
152 fn next(&mut self) -> Option<Self::Item> {
153 let item = self.0.next()?;
154 let item = unsafe { ngx_rbtree_data!(item, MapEntry<K, V>, node).as_mut() };
155 Some((&item.key, &mut item.value))
156 }
157}
158
159impl<K, V, A> RbTreeMap<K, V, A>
160where
161 A: Allocator,
162{
163 pub fn allocator(&self) -> &A {
165 &self.alloc
166 }
167
168 pub fn clear(&mut self) {
170 let iter = unsafe { NgxRbTreeIter::new(NonNull::from(&self.tree)) };
172 let layout = Layout::new::<MapEntry<K, V>>();
173
174 for node in iter {
175 unsafe {
176 let mut data = ngx_rbtree_data!(node, MapEntry<K, V>, node);
177
178 ngx_rbtree_delete(&mut self.tree, &mut data.as_mut().node);
179 ptr::drop_in_place(data.as_mut());
180 self.allocator().deallocate(data.cast(), layout)
181 }
182 }
183 }
184
185 pub fn is_empty(&self) -> bool {
187 ptr::addr_eq(self.tree.root, self.tree.sentinel)
188 }
189
190 #[inline]
192 pub fn iter(&self) -> Iter<'_, K, V> {
193 Iter::new(self)
194 }
195
196 #[inline]
198 pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
199 IterMut::new(self)
200 }
201}
202
203impl<K, V, A> RbTreeMap<K, V, A>
204where
205 A: Allocator,
206 K: Hash + Ord,
207{
208 pub fn try_new_in(alloc: A) -> Result<Self, AllocError> {
210 let layout = Layout::new::<ngx_rbtree_node_t>();
211 let sentinel: NonNull<ngx_rbtree_node_t> = alloc.allocate_zeroed(layout)?.cast();
212
213 let mut this = RbTreeMap {
214 tree: unsafe { mem::zeroed() },
215 sentinel,
216 alloc,
217 _kv_type: PhantomData,
218 };
219
220 unsafe { ngx_rbtree_init(&mut this.tree, this.sentinel.as_ptr(), Some(Self::insert)) };
221
222 Ok(this)
223 }
224
225 pub fn get<Q>(&self, key: &Q) -> Option<&V>
227 where
228 K: borrow::Borrow<Q>,
229 Q: Hash + Ord + ?Sized,
230 {
231 self.lookup(key).map(|x| unsafe { &x.as_ref().value })
232 }
233
234 pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
236 where
237 K: borrow::Borrow<Q>,
238 Q: Hash + Ord + ?Sized,
239 {
240 self.lookup(key)
241 .map(|mut x| unsafe { &mut x.as_mut().value })
242 }
243
244 pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
247 where
248 K: borrow::Borrow<Q>,
249 Q: Hash + Ord + ?Sized,
250 {
251 self.remove_entry(key).map(|(_, v)| v)
252 }
253
254 pub fn remove_entry<Q>(&mut self, key: &Q) -> Option<(K, V)>
257 where
258 K: borrow::Borrow<Q>,
259 Q: Hash + Ord + ?Sized,
260 {
261 let mut node = self.lookup(key)?;
262 unsafe {
263 ngx_rbtree_delete(&mut self.tree, &mut node.as_mut().node);
264 let layout = Layout::for_value(node.as_ref());
265 let copy = node.as_ptr().read();
268 self.allocator().deallocate(node.cast(), layout);
269 Some(copy.into_kv())
270 }
271 }
272
273 pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, AllocError> {
275 let mut node = if let Some(mut node) = self.lookup(&key) {
276 unsafe { node.as_mut().value = value };
277 node
278 } else {
279 let node = MapEntry::new(key, value);
280 let mut node = allocator::allocate(node, self.allocator())?;
281 unsafe { ngx_rbtree_insert(&mut self.tree, &mut node.as_mut().node) };
282 node
283 };
284
285 Ok(unsafe { &mut node.as_mut().value })
286 }
287
288 extern "C" fn insert(
289 mut temp: *mut ngx_rbtree_node_t,
290 node: *mut ngx_rbtree_node_t,
291 sentinel: *mut ngx_rbtree_node_t,
292 ) {
293 let n = unsafe { &mut *ngx_rbtree_data!(node, MapEntry<K, V>, node) };
294
295 loop {
296 let t = unsafe { &mut *ngx_rbtree_data!(temp, MapEntry<K, V>, node) };
297 let p = match Ord::cmp(&n.node.key, &t.node.key) {
298 Ordering::Less => &mut t.node.left,
299 Ordering::Greater => &mut t.node.right,
300 Ordering::Equal => match Ord::cmp(&n.key, &t.key) {
301 Ordering::Less => &mut t.node.left,
302 Ordering::Greater => &mut t.node.right,
303 Ordering::Equal => &mut t.node.right,
305 },
306 };
307
308 if ptr::addr_eq(*p, sentinel) {
309 *p = node;
310 break;
311 }
312
313 temp = *p;
314 }
315
316 n.node.parent = temp;
317 n.node.left = sentinel;
318 n.node.right = sentinel;
319 unsafe { ngx_rbt_red(node) };
320 }
321
322 fn lookup<Q>(&self, key: &Q) -> Option<NonNull<MapEntry<K, V>>>
323 where
324 K: borrow::Borrow<Q>,
325 Q: Hash + Ord + ?Sized,
326 {
327 let mut node = self.tree.root;
328 let hash = BuildMapHasher::default().hash_one(key) as ngx_rbtree_key_t;
329
330 while !ptr::addr_eq(node, self.tree.sentinel) {
331 let n = unsafe { NonNull::new_unchecked(ngx_rbtree_data!(node, MapEntry<K, V>, node)) };
332 let nr = unsafe { n.as_ref() };
333
334 node = match Ord::cmp(&hash, &nr.node.key) {
335 Ordering::Less => nr.node.left,
336 Ordering::Greater => nr.node.right,
337 Ordering::Equal => match Ord::cmp(key, nr.key.borrow()) {
338 Ordering::Less => nr.node.left,
339 Ordering::Greater => nr.node.right,
340 Ordering::Equal => return Some(n),
341 },
342 }
343 }
344
345 None
346 }
347}
348
349impl<K, V, A> Drop for RbTreeMap<K, V, A>
350where
351 A: Allocator,
352{
353 fn drop(&mut self) {
354 self.clear();
355
356 unsafe {
357 self.allocator().deallocate(
358 self.sentinel.cast(),
359 Layout::for_value(self.sentinel.as_ref()),
360 )
361 };
362 }
363}
364
365unsafe impl<K, V, A> Send for RbTreeMap<K, V, A>
366where
367 A: Send + Allocator,
368 K: Send,
369 V: Send,
370{
371}
372
373unsafe impl<K, V, A> Sync for RbTreeMap<K, V, A>
374where
375 A: Sync + Allocator,
376 K: Sync,
377 V: Sync,
378{
379}