wraith/structures/
list_entry.rs1use core::marker::PhantomData;
4use core::ptr::NonNull;
5
6#[repr(C)]
8#[derive(Debug)]
9pub struct ListEntry {
10 pub flink: *mut ListEntry,
11 pub blink: *mut ListEntry,
12}
13
14impl ListEntry {
15 pub fn is_empty(&self) -> bool {
17 core::ptr::eq(self.flink, self as *const _ as *mut _)
18 }
19
20 pub fn next(&self, head: *const ListEntry) -> Option<NonNull<ListEntry>> {
24 if core::ptr::eq(self.flink, head as *mut _) {
25 None
26 } else {
27 NonNull::new(self.flink)
28 }
29 }
30
31 pub fn prev(&self, head: *const ListEntry) -> Option<NonNull<ListEntry>> {
33 if core::ptr::eq(self.blink, head as *mut _) {
34 None
35 } else {
36 NonNull::new(self.blink)
37 }
38 }
39}
40
41pub struct ListEntryIter<'a, T> {
43 head: *const ListEntry,
44 current: *const ListEntry,
45 offset: usize,
46 _marker: PhantomData<&'a T>,
47}
48
49impl<'a, T> ListEntryIter<'a, T> {
50 pub unsafe fn new(head: *const ListEntry, offset: usize) -> Self {
56 let first = unsafe { (*head).flink };
57 Self {
58 head,
59 current: first,
60 offset,
61 _marker: PhantomData,
62 }
63 }
64}
65
66impl<'a, T> Iterator for ListEntryIter<'a, T> {
67 type Item = &'a T;
68
69 fn next(&mut self) -> Option<Self::Item> {
70 if core::ptr::eq(self.current, self.head) {
72 return None;
73 }
74
75 let container = unsafe {
77 let entry_addr = self.current as usize;
78 let container_addr = entry_addr - self.offset;
79 &*(container_addr as *const T)
80 };
81
82 self.current = unsafe { (*self.current).flink };
84
85 Some(container)
86 }
87}
88
89pub struct ListEntryIterMut<'a, T> {
91 head: *mut ListEntry,
92 current: *mut ListEntry,
93 offset: usize,
94 _marker: PhantomData<&'a mut T>,
95}
96
97impl<'a, T> ListEntryIterMut<'a, T> {
98 pub unsafe fn new(head: *mut ListEntry, offset: usize) -> Self {
105 let first = unsafe { (*head).flink };
106 Self {
107 head,
108 current: first,
109 offset,
110 _marker: PhantomData,
111 }
112 }
113}
114
115impl<'a, T> Iterator for ListEntryIterMut<'a, T> {
116 type Item = &'a mut T;
117
118 fn next(&mut self) -> Option<Self::Item> {
119 if core::ptr::eq(self.current, self.head) {
120 return None;
121 }
122
123 let container = unsafe {
124 let entry_addr = self.current as usize;
125 let container_addr = entry_addr - self.offset;
126 &mut *(container_addr as *mut T)
127 };
128
129 self.current = unsafe { (*self.current).flink };
130
131 Some(container)
132 }
133}
134
135pub unsafe fn unlink_entry(entry: *mut ListEntry) {
141 unsafe {
142 let flink = (*entry).flink;
143 let blink = (*entry).blink;
144 (*blink).flink = flink;
145 (*flink).blink = blink;
146 (*entry).flink = entry;
148 (*entry).blink = entry;
149 }
150}
151
152pub unsafe fn link_entry_after(entry: *mut ListEntry, after: *mut ListEntry) {
158 unsafe {
159 let next = (*after).flink;
160 (*entry).flink = next;
161 (*entry).blink = after;
162 (*after).flink = entry;
163 (*next).blink = entry;
164 }
165}