use wdk_sys::LIST_ENTRY;
use crate::memory::{npp::NPP, AllocationError};
pub fn init_linked_list(list: &mut LIST_ENTRY) {
list.Flink = list;
list.Blink = list;
}
#[repr(C)]
pub struct LinkedList<T> {
head: Option<NPP<Node<T>>>,
size: usize,
}
#[repr(C)]
pub struct Node<T> {
pub val: T,
pub next: Option<NPP<Node<T>>>,
}
impl<T> Default for LinkedList<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Drop for LinkedList<T> {
fn drop(&mut self) {}
}
impl<T> LinkedList<T> {
pub fn new() -> Self {
Self {
head: None,
size: 0,
}
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn len(&self) -> usize {
self.size
}
pub fn push_head(&mut self, data: T) -> Result<&mut Self, AllocationError> {
let node = NPP::new(Node {
val: data,
next: self.head.take(),
})?;
self.head = Some(node);
self.size += 1;
Ok(self)
}
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
current: self.head.as_deref_mut(),
}
}
pub fn iter(&self) -> Iter<'_, T> {
Iter {
current: self.head.as_deref(),
}
}
pub fn remove_if<F>(&mut self, mut predicate: F) -> bool
where
F: FnMut(&mut T) -> bool,
{
let mut current = &mut self.head;
loop {
if current.is_none() {
return false;
}
let should_remove = {
let node = current.as_mut().unwrap();
predicate(&mut node.val)
};
if should_remove {
let mut unlinked_node = current.take().unwrap();
*current = unlinked_node.next.take();
self.size -= 1;
return true;
}
current = &mut current.as_mut().unwrap().next;
}
}
}
pub struct IterMut<'a, T> {
current: Option<&'a mut Node<T>>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.current.take().map(|node| {
self.current = node.next.as_deref_mut();
&mut node.val
})
}
}
pub struct Iter<'a, T> {
current: Option<&'a Node<T>>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.current.map(|node| {
self.current = node.next.as_deref();
&node.val
})
}
}