1use core::alloc::Layout;
9use core::marker::PhantomData;
10use core::mem;
11use core::ptr::{self, NonNull};
12
13use nginx_sys::{
14 ngx_queue_data, ngx_queue_empty, ngx_queue_init, ngx_queue_insert_after,
15 ngx_queue_insert_before, ngx_queue_remove, ngx_queue_t,
16};
17
18use crate::allocator::{AllocError, Allocator};
19
20pub unsafe trait NgxQueueEntry {
31 fn from_queue(queue: NonNull<ngx_queue_t>) -> NonNull<Self>;
33 fn to_queue(&mut self) -> &mut ngx_queue_t;
35}
36
37unsafe impl NgxQueueEntry for ngx_queue_t {
38 fn from_queue(queue: NonNull<ngx_queue_t>) -> NonNull<Self> {
39 queue
40 }
41
42 fn to_queue(&mut self) -> &mut ngx_queue_t {
43 self
44 }
45}
46
47#[derive(Debug)]
81#[repr(transparent)]
82pub struct NgxQueue<T> {
83 head: ngx_queue_t,
84 _type: PhantomData<T>,
85}
86
87impl<T> NgxQueue<T>
88where
89 T: NgxQueueEntry,
90{
91 pub unsafe fn from_ptr<'a>(head: *const ngx_queue_t) -> &'a Self {
98 &*head.cast()
99 }
100
101 pub unsafe fn from_ptr_mut<'a>(head: *mut ngx_queue_t) -> &'a mut Self {
108 &mut *head.cast()
109 }
110
111 pub fn is_empty(&self) -> bool {
113 self.head.prev.is_null() || unsafe { ngx_queue_empty(&self.head) }
114 }
115
116 pub fn push_back(&mut self, entry: &mut T) {
118 if self.head.prev.is_null() {
119 unsafe { ngx_queue_init(&mut self.head) }
120 }
121
122 unsafe { ngx_queue_insert_before(&mut self.head, entry.to_queue()) }
123 }
124
125 pub fn push_front(&mut self, entry: &mut T) {
127 if self.head.prev.is_null() {
128 unsafe { ngx_queue_init(&mut self.head) }
129 }
130
131 unsafe { ngx_queue_insert_after(&mut self.head, entry.to_queue()) }
132 }
133
134 pub fn iter(&self) -> NgxQueueIter<'_, T> {
136 NgxQueueIter::new(&self.head)
137 }
138
139 pub fn iter_mut(&mut self) -> NgxQueueIterMut<'_, T> {
141 NgxQueueIterMut::new(&mut self.head)
142 }
143}
144
145pub struct NgxQueueIter<'a, T> {
147 head: NonNull<ngx_queue_t>,
148 current: NonNull<ngx_queue_t>,
149 _lifetime: PhantomData<&'a T>,
150}
151
152impl<'a, T> NgxQueueIter<'a, T>
153where
154 T: NgxQueueEntry,
155{
156 pub fn new(head: &'a ngx_queue_t) -> Self {
158 let head = NonNull::from(head);
159 NgxQueueIter {
160 head,
161 current: head,
162 _lifetime: PhantomData,
163 }
164 }
165}
166
167impl<'a, T> Iterator for NgxQueueIter<'a, T>
168where
169 T: NgxQueueEntry + 'a,
170{
171 type Item = &'a T;
172
173 fn next(&mut self) -> Option<Self::Item> {
174 unsafe {
175 let next = NonNull::new(self.current.as_ref().next)?;
176 if next == self.head {
177 return None;
178 }
179
180 self.current = next;
181 Some(T::from_queue(self.current).as_ref())
182 }
183 }
184}
185
186pub struct NgxQueueIterMut<'a, T> {
188 head: NonNull<ngx_queue_t>,
189 current: NonNull<ngx_queue_t>,
190 _lifetime: PhantomData<&'a T>,
191}
192
193impl<'a, T> NgxQueueIterMut<'a, T>
194where
195 T: NgxQueueEntry,
196{
197 pub fn new(head: &'a mut ngx_queue_t) -> Self {
199 let head = NonNull::from(head);
200 NgxQueueIterMut {
201 head,
202 current: head,
203 _lifetime: PhantomData,
204 }
205 }
206}
207
208impl<'a, T> Iterator for NgxQueueIterMut<'a, T>
209where
210 T: NgxQueueEntry + 'a,
211{
212 type Item = &'a mut T;
213
214 fn next(&mut self) -> Option<Self::Item> {
215 unsafe {
216 let next = NonNull::new(self.current.as_ref().next)?;
217 if next == self.head {
218 return None;
219 }
220
221 self.current = next;
222 Some(T::from_queue(self.current).as_mut())
223 }
224 }
225}
226
227#[derive(Debug)]
229pub struct Queue<T, A>
230where
231 A: Allocator,
232{
233 raw: NonNull<NgxQueue<QueueEntry<T>>>,
236 len: usize,
237 alloc: A,
238}
239
240impl<T, A> Drop for Queue<T, A>
241where
242 A: Allocator,
243{
244 fn drop(&mut self) {
245 while self.pop_front().is_some() {}
246
247 let layout = Layout::for_value(unsafe { self.raw.as_ref() });
248 unsafe { self.allocator().deallocate(self.raw.cast(), layout) };
249 }
250}
251
252unsafe impl<T, A> Send for Queue<T, A>
253where
254 A: Send + Allocator,
255 T: Send,
256{
257}
258
259unsafe impl<T, A> Sync for Queue<T, A>
260where
261 A: Sync + Allocator,
262 T: Sync,
263{
264}
265
266impl<T, A: Allocator> Queue<T, A> {
267 pub fn try_new_in(alloc: A) -> Result<Self, AllocError> {
269 let raw = NgxQueue {
270 head: unsafe { mem::zeroed() },
271 _type: PhantomData,
272 };
273 let raw = crate::allocator::allocate(raw, &alloc)?;
274 Ok(Self { raw, len: 0, alloc })
275 }
276
277 pub fn allocator(&self) -> &A {
279 &self.alloc
280 }
281
282 pub fn is_empty(&self) -> bool {
284 self.raw().is_empty()
285 }
286
287 pub fn len(&self) -> usize {
289 self.len
290 }
291
292 pub fn iter(&self) -> QueueIter<'_, T> {
294 QueueIter::new(&self.raw().head)
295 }
296
297 pub fn iter_mut(&mut self) -> QueueIterMut<'_, T> {
299 QueueIterMut::new(&mut self.raw_mut().head)
300 }
301
302 pub fn pop_back(&mut self) -> Option<T> {
304 if self.is_empty() {
305 return None;
306 }
307 let node = NonNull::new(self.raw_mut().head.prev)?;
308 Some(unsafe { self.remove(node) })
309 }
310
311 pub fn pop_front(&mut self) -> Option<T> {
313 if self.is_empty() {
314 return None;
315 }
316 let node = NonNull::new(self.raw_mut().head.next)?;
317 Some(unsafe { self.remove(node) })
318 }
319
320 pub fn push_back(&mut self, item: T) -> Result<&mut T, AllocError> {
322 let mut entry = QueueEntry::new_in(item, self.allocator())?;
323 let entry = unsafe { entry.as_mut() };
324 self.raw_mut().push_back(entry);
325 self.len += 1;
326 Ok(&mut entry.item)
327 }
328
329 pub fn push_front(&mut self, item: T) -> Result<&mut T, AllocError> {
331 let mut entry = QueueEntry::new_in(item, self.allocator())?;
332 let entry = unsafe { entry.as_mut() };
333 self.raw_mut().push_front(entry);
334 self.len += 1;
335 Ok(&mut entry.item)
336 }
337
338 fn raw(&self) -> &NgxQueue<QueueEntry<T>> {
339 unsafe { self.raw.as_ref() }
341 }
342
343 fn raw_mut(&mut self) -> &mut NgxQueue<QueueEntry<T>> {
344 unsafe { self.raw.as_mut() }
346 }
347
348 unsafe fn remove(&mut self, node: NonNull<ngx_queue_t>) -> T {
354 ngx_queue_remove(node.as_ptr());
355 self.len -= 1;
356
357 let entry = QueueEntry::<T>::from_queue(node);
358 let copy = entry.read();
359 self.allocator()
361 .deallocate(entry.cast(), Layout::for_value(entry.as_ref()));
362 copy.item
363 }
364}
365
366#[derive(Debug)]
367struct QueueEntry<T> {
368 queue: ngx_queue_t,
369 item: T,
370}
371
372unsafe impl<T> NgxQueueEntry for QueueEntry<T> {
373 fn from_queue(queue: NonNull<ngx_queue_t>) -> NonNull<Self> {
374 unsafe { ngx_queue_data!(queue, Self, queue) }
375 }
376
377 fn to_queue(&mut self) -> &mut ngx_queue_t {
378 &mut self.queue
379 }
380}
381
382impl<T> QueueEntry<T> {
383 pub fn new_in(item: T, alloc: &impl Allocator) -> Result<NonNull<Self>, AllocError> {
384 let p: NonNull<Self> = alloc.allocate(Layout::new::<Self>())?.cast();
385
386 unsafe {
387 let u = p.cast::<mem::MaybeUninit<Self>>().as_mut();
388 ngx_queue_init(&mut u.assume_init_mut().queue);
390 ptr::write(&mut u.assume_init_mut().item, item);
391 }
392
393 Ok(p)
394 }
395}
396
397pub struct QueueIter<'a, T>(NgxQueueIter<'a, QueueEntry<T>>);
399
400impl<'a, T> QueueIter<'a, T> {
401 pub fn new(head: &'a ngx_queue_t) -> Self {
403 Self(NgxQueueIter::new(head))
404 }
405}
406
407impl<'a, T> Iterator for QueueIter<'a, T> {
408 type Item = &'a T;
409
410 fn next(&mut self) -> Option<Self::Item> {
411 Some(&self.0.next()?.item)
412 }
413}
414
415pub struct QueueIterMut<'a, T>(NgxQueueIterMut<'a, QueueEntry<T>>);
417
418impl<'a, T> QueueIterMut<'a, T> {
419 pub fn new(head: &'a mut ngx_queue_t) -> Self {
421 Self(NgxQueueIterMut::new(head))
422 }
423}
424
425impl<'a, T> Iterator for QueueIterMut<'a, T> {
426 type Item = &'a mut T;
427
428 fn next(&mut self) -> Option<Self::Item> {
429 Some(&mut self.0.next()?.item)
430 }
431}