1use core::marker::PhantomPinned;
5use core::pin::Pin;
6use core::ptr;
7
8use alloc::boxed::Box;
9use moveit::{new, New};
10
11use super::base::{Iter, IterMut, NtListEntry, NtListHead};
12use super::traits::NtList;
13use crate::traits::{NtBoxedListElement, NtListElement, NtTypedList};
14
15#[repr(transparent)]
30#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
31pub struct NtBoxingListHead<
32 E: NtBoxedListElement<L = L> + NtListElement<L>,
33 L: NtTypedList<T = NtList>,
34>(NtListHead<E, L>);
35
36impl<E, L> NtBoxingListHead<E, L>
37where
38 E: NtBoxedListElement<L = L> + NtListElement<L>,
39 L: NtTypedList<T = NtList>,
40{
41 pub fn new() -> impl New<Output = Self> {
47 new::of(Self(NtListHead {
48 flink: ptr::null_mut(),
49 blink: ptr::null_mut(),
50 pin: PhantomPinned,
51 }))
52 .with(|this| {
53 let this = unsafe { this.get_unchecked_mut() };
54 this.0.flink = (this as *mut Self).cast();
55 this.0.blink = this.0.flink;
56 })
57 }
58
59 pub fn append(self: Pin<&mut Self>, other: Pin<&mut Self>) {
66 unsafe { self.inner_mut().append(other.inner_mut()) }
67 }
68
69 pub fn back(self: Pin<&Self>) -> Option<&E> {
73 unsafe { self.inner().back() }
74 }
75
76 pub fn back_mut(self: Pin<&mut Self>) -> Option<&mut E> {
80 unsafe { self.inner_mut().back_mut() }
81 }
82
83 pub fn clear(mut self: Pin<&mut Self>) {
88 let end_marker = self.as_mut().inner_mut().end_marker_mut();
89
90 let mut current = self.0.flink;
92
93 self.inner_mut().clear();
104
105 while current != end_marker {
107 unsafe {
108 let element = NtListEntry::containing_record_mut(current);
109 current = (*current).flink;
110 drop(Box::from_raw(element));
111 }
112 }
113 }
114
115 pub fn front(self: Pin<&Self>) -> Option<&E> {
119 unsafe { self.inner().front() }
120 }
121
122 pub fn front_mut(self: Pin<&mut Self>) -> Option<&mut E> {
126 unsafe { self.inner_mut().front_mut() }
127 }
128
129 fn inner(self: Pin<&Self>) -> Pin<&NtListHead<E, L>> {
130 unsafe { Pin::new_unchecked(&self.get_ref().0) }
131 }
132
133 fn inner_mut(self: Pin<&mut Self>) -> Pin<&mut NtListHead<E, L>> {
134 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) }
135 }
136
137 pub fn is_empty(self: Pin<&Self>) -> bool {
145 self.inner().is_empty()
146 }
147
148 pub fn iter(self: Pin<&Self>) -> Iter<E, L> {
150 unsafe { self.inner().iter() }
151 }
152
153 pub fn iter_mut(self: Pin<&mut Self>) -> IterMut<E, L> {
155 unsafe { self.inner_mut().iter_mut() }
156 }
157
158 pub fn len(self: Pin<&Self>) -> usize {
162 unsafe { self.inner().len() }
163 }
164
165 pub fn pop_back(self: Pin<&mut Self>) -> Option<Box<E>> {
173 unsafe {
174 self.inner_mut()
175 .pop_back()
176 .map(|element| Box::from_raw(element))
177 }
178 }
179
180 pub fn pop_front(self: Pin<&mut Self>) -> Option<Box<E>> {
188 unsafe {
189 self.inner_mut()
190 .pop_front()
191 .map(|element| Box::from_raw(element))
192 }
193 }
194
195 pub fn push_back(self: Pin<&mut Self>, element: E) {
203 let boxed_element = Box::new(element);
204 unsafe { self.inner_mut().push_back(Box::leak(boxed_element)) }
205 }
206
207 pub fn push_front(self: Pin<&mut Self>, element: E) {
215 let boxed_element = Box::new(element);
216 unsafe { self.inner_mut().push_front(Box::leak(boxed_element)) }
217 }
218
219 pub fn retain<F>(self: Pin<&mut Self>, mut f: F)
231 where
232 F: FnMut(&mut E) -> bool,
233 {
234 for element in self.iter_mut() {
235 if !f(element) {
236 let entry = NtListHead::entry(element);
237
238 unsafe {
239 (*entry).remove();
240 drop(Box::from_raw(element));
241 }
242 }
243 }
244 }
245}
246
247impl<E, L> Drop for NtBoxingListHead<E, L>
248where
249 E: NtBoxedListElement<L = L> + NtListElement<L>,
250 L: NtTypedList<T = NtList>,
251{
252 fn drop(&mut self) {
253 let pinned = unsafe { Pin::new_unchecked(self) };
254
255 for element in pinned.iter_mut() {
256 unsafe {
259 drop(Box::from_raw(element));
260 }
261 }
262 }
263}
264
265impl<E, L> Extend<Box<E>> for Pin<&mut NtBoxingListHead<E, L>>
266where
267 E: NtBoxedListElement<L = L> + NtListElement<L>,
268 L: NtTypedList<T = NtList>,
269{
270 fn extend<T>(&mut self, iter: T)
271 where
272 T: IntoIterator<Item = Box<E>>,
273 {
274 let end_marker = self.as_mut().inner_mut().end_marker_mut();
275 let mut previous = self.as_ref().inner().blink;
276
277 for element in iter.into_iter() {
278 unsafe {
281 let entry = NtListHead::entry(Box::leak(element));
282
283 (*entry).flink = end_marker;
284 (*entry).blink = previous;
285 (*previous).flink = entry;
286
287 previous = entry;
288 }
289 }
290
291 unsafe {
292 self.as_mut().get_unchecked_mut().0.blink = previous;
293 }
294 }
295}
296
297impl<E, L> Extend<E> for Pin<&mut NtBoxingListHead<E, L>>
298where
299 E: NtBoxedListElement<L = L> + NtListElement<L>,
300 L: NtTypedList<T = NtList>,
301{
302 fn extend<T>(&mut self, iter: T)
303 where
304 T: IntoIterator<Item = E>,
305 {
306 self.extend(iter.into_iter().map(Box::new))
307 }
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313 use crate::list::NtListEntry;
314 use alloc::vec::Vec;
315 use moveit::moveit;
316
317 #[derive(NtList)]
318 enum MyList {}
319
320 #[derive(Default, NtListElement)]
321 #[repr(C)]
322 struct MyElement {
323 value: i32,
324 #[boxed]
325 entry: NtListEntry<Self, MyList>,
326 }
327
328 impl MyElement {
329 fn new(value: i32) -> Self {
330 Self {
331 value,
332 ..Default::default()
333 }
334 }
335 }
336
337 #[test]
338 fn test_append() {
339 moveit! {
341 let mut list1 = NtBoxingListHead::<MyElement, MyList>::new();
342 let mut list2 = NtBoxingListHead::<MyElement, MyList>::new();
343 }
344
345 for i in 0..10 {
346 list1.as_mut().push_back(MyElement::new(i));
347 list2.as_mut().push_back(MyElement::new(i));
348 }
349
350 list1.as_mut().append(list2.as_mut());
351
352 assert_eq!(list1.as_ref().len(), 20);
353 assert_eq!(list2.as_ref().len(), 0);
354
355 for (i, element) in (0..10).chain(0..10).zip(list1.as_ref().iter()) {
356 assert_eq!(i, element.value);
357 }
358
359 verify_all_links(list1.as_ref().inner());
360
361 moveit! {
363 let mut list3 = NtBoxingListHead::<MyElement, MyList>::new();
364 }
365
366 list3.as_mut().append(list1.as_mut());
367
368 assert_eq!(list3.as_ref().len(), 20);
369 assert_eq!(list1.as_ref().len(), 0);
370
371 verify_all_links(list3.as_ref().inner());
372 }
373
374 #[test]
375 fn test_clear_and_append() {
376 moveit! {
378 let mut list1 = NtBoxingListHead::<MyElement, MyList>::new();
379 let mut list2 = NtBoxingListHead::<MyElement, MyList>::new();
380 }
381
382 for i in 0..10 {
383 list1.as_mut().push_back(MyElement::new(i));
384 list2.as_mut().push_back(MyElement::new(i));
385 }
386
387 list1.as_mut().append(list2.as_mut());
388
389 assert_eq!(list1.as_ref().len(), 20);
390 assert_eq!(list2.as_ref().len(), 0);
391
392 for (i, element) in (0..10).chain(0..10).zip(list1.as_ref().iter()) {
393 assert_eq!(i, element.value);
394 }
395
396 verify_all_links(list1.as_ref().inner());
397
398 list1.as_mut().push_back(MyElement::new(21));
400 list1.as_mut().push_front(MyElement::new(22));
401
402 list2.as_mut().push_back(MyElement::new(21));
403 list2.as_mut().push_front(MyElement::new(22));
404
405 moveit! {
407 let mut list3 = NtBoxingListHead::<MyElement, MyList>::new();
408 }
409
410 list3.as_mut().clear();
411 list3.as_mut().append(list1.as_mut());
412
413 assert_eq!(list3.as_ref().len(), 22);
414 assert_eq!(list1.as_ref().len(), 0);
415
416 verify_all_links(list3.as_ref().inner());
417 }
418
419 #[test]
420 fn test_clear_and_push() {
421 moveit! {
422 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
423 }
424
425 list.as_mut().clear();
426
427 for i in 0..=3 {
428 list.as_mut().push_back(MyElement::new(i));
429 }
430 for i in 4..=6 {
431 list.as_mut().push_front(MyElement::new(i));
432 }
433
434 assert_eq!(list.as_ref().back().unwrap().value, 3);
435 assert_eq!(list.as_mut().back_mut().unwrap().value, 3);
436 assert_eq!(list.as_ref().front().unwrap().value, 6);
437 assert_eq!(list.as_mut().front_mut().unwrap().value, 6);
438
439 verify_all_links(list.as_ref().inner());
440 }
441
442 #[test]
443 fn test_back_and_front() {
444 moveit! {
445 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
446 }
447
448 for i in 0..=3 {
449 list.as_mut().push_back(MyElement::new(i));
450 }
451
452 assert_eq!(list.as_ref().back().unwrap().value, 3);
453 assert_eq!(list.as_mut().back_mut().unwrap().value, 3);
454 assert_eq!(list.as_ref().front().unwrap().value, 0);
455 assert_eq!(list.as_mut().front_mut().unwrap().value, 0);
456 }
457
458 #[test]
459 fn test_extend() {
460 let integers = [0, 1, 2, 3, 4, 5];
461
462 moveit! {
463 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
464 }
465
466 list.as_mut()
467 .extend(integers.into_iter().map(MyElement::new));
468
469 for (i, element) in integers.into_iter().zip(list.as_ref().iter()) {
470 assert_eq!(i, element.value);
471 }
472
473 verify_all_links(list.as_ref().inner());
474 }
475
476 #[test]
477 fn test_pop_back() {
478 moveit! {
479 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
480 }
481
482 for i in 0..10 {
483 list.as_mut().push_back(MyElement::new(i));
484 }
485
486 for i in (0..10).rev() {
487 let element = list.as_mut().pop_back().unwrap();
488 assert_eq!(i, element.value);
489 verify_all_links(list.as_ref().inner());
490 }
491
492 assert!(list.as_ref().is_empty());
493 }
494
495 #[test]
496 fn test_pop_front() {
497 moveit! {
498 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
499 }
500
501 for i in 0..10 {
502 list.as_mut().push_back(MyElement::new(i));
503 }
504
505 for i in 0..10 {
506 let element = list.as_mut().pop_front().unwrap();
507 assert_eq!(i, element.value);
508 verify_all_links(list.as_ref().inner());
509 }
510
511 assert!(list.as_ref().is_empty());
512 }
513
514 #[test]
515 fn test_push_back() {
516 moveit! {
517 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
518 }
519
520 for i in 0..10 {
521 list.as_mut().push_back(MyElement::new(i));
522 }
523
524 assert_eq!(list.as_ref().len(), 10);
525
526 for (i, element) in (0..10).zip(list.as_ref().iter()) {
527 assert_eq!(i, element.value);
528 }
529
530 verify_all_links(list.as_ref().inner());
531 }
532
533 #[test]
534 fn test_push_front() {
535 moveit! {
536 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
537 }
538
539 for i in 0..10 {
540 list.as_mut().push_front(MyElement::new(i));
541 }
542
543 assert_eq!(list.as_ref().len(), 10);
544
545 for (i, element) in (0..10).rev().zip(list.as_ref().iter()) {
546 assert_eq!(i, element.value);
547 }
548
549 verify_all_links(list.as_ref().inner());
550 }
551
552 #[test]
553 fn test_retain() {
554 moveit! {
555 let mut list = NtBoxingListHead::<MyElement, MyList>::new();
556 }
557
558 for i in 0..10 {
559 list.as_mut().push_back(MyElement::new(i));
560 }
561
562 list.as_mut().retain(|element| element.value % 2 == 0);
564
565 assert_eq!(list.as_ref().len(), 5);
566
567 for (i, element) in (0..10).step_by(2).zip(list.as_ref().iter()) {
568 assert_eq!(i, element.value);
569 }
570
571 verify_all_links(list.as_ref().inner());
572
573 list.as_mut()
575 .retain(|element| element.value == 0 || element.value == 8);
576
577 let mut iter = list.as_ref().iter();
578 assert_eq!(iter.next().unwrap().value, 0);
579 assert_eq!(iter.next().unwrap().value, 8);
580 assert!(matches!(iter.next(), None));
581 }
582
583 fn verify_all_links<E, L>(head: Pin<&NtListHead<E, L>>)
584 where
585 E: NtListElement<L>,
586 L: NtTypedList<T = NtList>,
587 {
588 let mut current;
589 let end = (head.get_ref() as *const _ as *mut NtListHead<E, L>).cast();
590
591 current = head.flink;
593 let mut forward_entries = Vec::<*mut NtListEntry<E, L>>::new();
594
595 while current != end {
596 if !forward_entries.is_empty() {
597 unsafe {
599 assert_eq!(*forward_entries.last().unwrap(), (*current).blink);
600 }
601 }
602
603 forward_entries.push(current);
604 current = unsafe { (*current).flink };
605 }
606
607 current = head.blink;
609 let mut backward_entries =
610 Vec::<*mut NtListEntry<E, L>>::with_capacity(forward_entries.len());
611
612 while current != end {
613 if !backward_entries.is_empty() {
614 unsafe {
616 assert_eq!(*backward_entries.last().unwrap(), (*current).flink);
617 }
618 }
619
620 backward_entries.push(current);
621 current = unsafe { (*current).blink };
622 }
623
624 assert_eq!(forward_entries.len(), backward_entries.len());
626
627 for (fe, be) in forward_entries.iter().zip(backward_entries.iter().rev()) {
628 assert_eq!(fe, be);
629 }
630 }
631}