use core::{ffi::c_void, marker::PhantomData};
use moon_struct::list_entry::ListEntryOffset;
use wdk::println;
use wdk_sys::LIST_ENTRY;
pub struct ListEntrty<T>
where
T: ListEntryOffset,
{
_marker: PhantomData<T>,
head: *mut LIST_ENTRY,
}
pub unsafe fn initialize_list_head(list_head: &mut LIST_ENTRY) {
list_head.Flink = list_head;
list_head.Blink = list_head;
}
pub unsafe fn insert_tail_list(list_head: *mut LIST_ENTRY, entry: *mut LIST_ENTRY) {
let prev_entry = (*list_head).Blink;
if (*prev_entry).Flink != list_head {
println!("insert tail list fault");
panic!();
}
(*entry).Flink = list_head;
(*entry).Blink = prev_entry;
(*prev_entry).Flink = entry;
(*list_head).Blink = entry;
}
pub unsafe fn remove_entry_list(entry: *mut LIST_ENTRY) -> bool {
let node_ref = &mut *entry;
let prev = &mut *node_ref.Blink;
let next = &mut *node_ref.Flink;
if next.Blink != entry || prev.Flink != entry {
println!("remove list fault");
panic!();
}
prev.Flink = next as *mut _;
next.Blink = prev as *mut _;
return prev as *mut _ == next as *mut _;
}
impl<T> ListEntrty<T>
where
T: ListEntryOffset,
{
pub fn from_head(head: *mut LIST_ENTRY) -> Self {
Self {
_marker: PhantomData,
head: head,
}
}
pub fn init(&mut self) {
unsafe { initialize_list_head(&mut *self.head) };
}
pub fn insert_tail(&mut self, entry: *mut LIST_ENTRY) {
unsafe { insert_tail_list(self.head, entry) };
}
pub fn remove_node(&mut self, entry: *mut LIST_ENTRY) {
let _ = unsafe { remove_entry_list(entry) };
}
pub fn into_iter(&mut self) -> ListEntryIterMut<T> {
ListEntryIterMut {
current: Option::None,
head: self.head,
_marker: core::marker::PhantomData,
}
}
pub fn as_ptr(&mut self) -> *mut LIST_ENTRY {
self.head
}
}
pub struct ListEntryIterMut<'a, T>
where
T: ListEntryOffset,
{
current: Option<*mut T>,
head: *mut LIST_ENTRY,
_marker: core::marker::PhantomData<&'a T>,
}
impl<'a, T> Iterator for ListEntryIterMut<'a, T>
where
T: ListEntryOffset,
{
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
let next_list;
if self.current.is_none() {
next_list = unsafe { (*(self.head)).Flink };
} else {
let node = self.current.unwrap();
next_list = unsafe {
(*((node as *mut c_void).add(T::get_list_entry_offset()) as *mut LIST_ENTRY)).Flink
};
}
if next_list == self.head {
return None;
}
let next = unsafe {
(next_list as *mut _ as *mut c_void).add(0 - T::get_list_entry_offset()) as *mut T
};
self.current = Some(next);
let next_item = unsafe { &mut (*next) };
Some(next_item)
}
}