use core::iter::FusedIterator;
use core::marker::PhantomPinned;
use core::pin::Pin;
use core::ptr;
use moveit::{new, New};
use super::traits::NtList;
use crate::traits::{NtListElement, NtTypedList};
#[repr(C)]
pub struct NtListHead<E: NtListElement<L>, L: NtTypedList<T = NtList>> {
pub(crate) flink: *mut NtListEntry<E, L>,
pub(crate) blink: *mut NtListEntry<E, L>,
pub(crate) pin: PhantomPinned,
}
impl<E, L> NtListHead<E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
pub fn new() -> impl New<Output = Self> {
new::of(Self {
flink: ptr::null_mut(),
blink: ptr::null_mut(),
pin: PhantomPinned,
})
.with(|this| {
let this = unsafe { this.get_unchecked_mut() };
this.flink = (this as *mut Self).cast();
this.blink = this.flink;
})
}
pub unsafe fn append(mut self: Pin<&mut Self>, other: Pin<&mut Self>) {
if other.as_ref().is_empty() {
return;
}
(*self.blink).flink = other.flink;
(*other.flink).blink = self.blink;
(*other.blink).flink = self.as_mut().end_marker_mut();
self.get_unchecked_mut().blink = other.blink;
other.clear();
}
pub unsafe fn back(self: Pin<&Self>) -> Option<&E> {
(!self.is_empty()).then(|| NtListEntry::containing_record(self.blink))
}
pub unsafe fn back_mut(self: Pin<&mut Self>) -> Option<&mut E> {
(!self.as_ref().is_empty()).then(|| NtListEntry::containing_record_mut(self.blink))
}
pub fn clear(mut self: Pin<&mut Self>) {
let end_marker = self.as_mut().end_marker_mut();
let self_mut = unsafe { self.get_unchecked_mut() };
self_mut.flink = end_marker;
self_mut.blink = end_marker;
}
pub(crate) fn end_marker(self: Pin<&Self>) -> *const NtListEntry<E, L> {
(self.get_ref() as *const Self).cast()
}
pub(crate) fn end_marker_mut(self: Pin<&mut Self>) -> *mut NtListEntry<E, L> {
(unsafe { self.get_unchecked_mut() } as *mut Self).cast()
}
pub(crate) fn entry(element: &mut E) -> *mut NtListEntry<E, L> {
let element_ptr = element as *mut E;
let entry = unsafe { element_ptr.cast::<u8>().add(E::offset()).cast::<E>() };
entry.cast()
}
pub unsafe fn front(self: Pin<&Self>) -> Option<&E> {
(!self.is_empty()).then(|| NtListEntry::containing_record(self.flink))
}
pub unsafe fn front_mut(self: Pin<&mut Self>) -> Option<&mut E> {
(!self.as_ref().is_empty()).then(|| NtListEntry::containing_record_mut(self.flink))
}
pub fn is_empty(self: Pin<&Self>) -> bool {
self.flink as *const NtListEntry<E, L> == (self.get_ref() as *const Self).cast()
}
pub unsafe fn iter(self: Pin<&Self>) -> Iter<E, L> {
let head = self;
let flink = head.flink;
let blink = head.blink;
Iter { head, flink, blink }
}
pub unsafe fn iter_mut(self: Pin<&mut Self>) -> IterMut<E, L> {
let head = self;
let flink = head.flink;
let blink = head.blink;
IterMut { head, flink, blink }
}
pub unsafe fn len(self: Pin<&Self>) -> usize {
self.iter().count()
}
pub unsafe fn pop_back(self: Pin<&mut Self>) -> Option<&mut E> {
(!self.as_ref().is_empty()).then(|| {
let entry = self.blink;
(*entry).remove();
NtListEntry::containing_record_mut(entry)
})
}
pub unsafe fn pop_front(self: Pin<&mut Self>) -> Option<&mut E> {
(!self.as_ref().is_empty()).then(|| {
let entry = self.flink;
(*entry).remove();
NtListEntry::containing_record_mut(entry)
})
}
pub unsafe fn push_back(mut self: Pin<&mut Self>, element: &mut E) {
let entry = Self::entry(element);
let old_blink = self.blink;
(*entry).flink = self.as_mut().end_marker_mut();
(*entry).blink = old_blink;
(*old_blink).flink = entry;
self.get_unchecked_mut().blink = entry;
}
pub unsafe fn push_front(mut self: Pin<&mut Self>, element: &mut E) {
let entry = Self::entry(element);
let old_flink = self.flink;
(*entry).flink = old_flink;
(*entry).blink = self.as_mut().end_marker_mut();
(*old_flink).blink = entry;
self.get_unchecked_mut().flink = entry;
}
pub unsafe fn retain<F>(self: Pin<&mut Self>, mut f: F)
where
F: FnMut(&mut E) -> bool,
{
for element in self.iter_mut() {
if !f(element) {
let entry = Self::entry(element);
(*entry).remove();
}
}
}
}
pub struct Iter<'a, E: NtListElement<L>, L: NtTypedList<T = NtList>> {
head: Pin<&'a NtListHead<E, L>>,
flink: *const NtListEntry<E, L>,
blink: *const NtListEntry<E, L>,
}
impl<'a, E, L> Iter<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
fn terminate(&mut self) {
self.flink = self.head.end_marker();
self.blink = self.flink;
}
}
impl<'a, E, L> Iterator for Iter<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
type Item = &'a E;
fn next(&mut self) -> Option<&'a E> {
if self.flink == self.head.end_marker() {
None
} else {
unsafe {
let element_ptr = self.flink;
if self.flink == self.blink {
self.terminate();
} else {
self.flink = (*self.flink).flink;
}
Some(NtListEntry::containing_record(element_ptr))
}
}
}
fn last(mut self) -> Option<&'a E> {
self.next_back()
}
}
impl<'a, E, L> DoubleEndedIterator for Iter<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
fn next_back(&mut self) -> Option<&'a E> {
if self.blink == self.head.end_marker() {
None
} else {
unsafe {
let element_ptr = self.blink;
if self.blink == self.flink {
self.terminate();
} else {
self.blink = (*self.blink).blink;
}
Some(NtListEntry::containing_record(element_ptr))
}
}
}
}
impl<'a, E, L> FusedIterator for Iter<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
}
pub struct IterMut<'a, E: NtListElement<L>, L: NtTypedList<T = NtList>> {
head: Pin<&'a mut NtListHead<E, L>>,
flink: *mut NtListEntry<E, L>,
blink: *mut NtListEntry<E, L>,
}
impl<'a, E, L> IterMut<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
fn terminate(&mut self) {
self.flink = self.head.as_mut().end_marker_mut();
self.blink = self.flink;
}
}
impl<'a, E, L> Iterator for IterMut<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
type Item = &'a mut E;
fn next(&mut self) -> Option<&'a mut E> {
if self.flink == self.head.as_mut().end_marker_mut() {
None
} else {
unsafe {
let element_ptr = self.flink;
if self.flink == self.blink {
self.terminate();
} else {
self.flink = (*self.flink).flink;
}
Some(NtListEntry::containing_record_mut(element_ptr))
}
}
}
fn last(mut self) -> Option<&'a mut E> {
self.next_back()
}
}
impl<'a, E, L> DoubleEndedIterator for IterMut<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
fn next_back(&mut self) -> Option<&'a mut E> {
if self.blink == self.head.as_mut().end_marker_mut() {
None
} else {
unsafe {
let element_ptr = self.blink;
if self.blink == self.flink {
self.terminate();
} else {
self.blink = (*self.blink).blink;
}
Some(NtListEntry::containing_record_mut(element_ptr))
}
}
}
}
impl<'a, E, L> FusedIterator for IterMut<'a, E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
}
#[derive(Debug)]
#[repr(C)]
pub struct NtListEntry<E: NtListElement<L>, L: NtTypedList<T = NtList>> {
pub(crate) flink: *mut NtListEntry<E, L>,
pub(crate) blink: *mut NtListEntry<E, L>,
pin: PhantomPinned,
}
impl<E, L> NtListEntry<E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
pub fn new() -> Self {
Self {
flink: ptr::null_mut(),
blink: ptr::null_mut(),
pin: PhantomPinned,
}
}
pub(crate) unsafe fn containing_record<'a>(ptr: *const Self) -> &'a E {
let element_ptr = unsafe { ptr.cast::<u8>().sub(E::offset()).cast::<Self>() };
unsafe { &*element_ptr.cast() }
}
pub(crate) unsafe fn containing_record_mut<'a>(ptr: *mut Self) -> &'a mut E {
let element_ptr = unsafe { ptr.cast::<u8>().sub(E::offset()).cast::<Self>() };
unsafe { &mut *element_ptr.cast() }
}
pub(crate) unsafe fn remove(&mut self) {
let old_flink = self.flink;
let old_blink = self.blink;
(*old_flink).blink = old_blink;
(*old_blink).flink = old_flink;
}
}
impl<E, L> Default for NtListEntry<E, L>
where
E: NtListElement<L>,
L: NtTypedList<T = NtList>,
{
fn default() -> Self {
Self::new()
}
}