use crate::list::linked_list::state::ListEntry;
use crate::list::linked_list::traits::ListElement;
use crate::util::NonNull;
use std::fmt;
use std::marker::PhantomData;
use std::pin::Pin;
#[cfg(any(test, feature = "linked_list_reachability_assert"))]
use std::ptr;
pub(crate) struct List<Type, Tag>
where
Type: ListElement<Tag, Type = Type> + ?Sized,
{
head: Option<NonNull<Type>>,
tail: Option<NonNull<Type>>,
sz: usize,
tag: PhantomData<Tag>,
}
pub(crate) struct ListIterator<'elem_lifetime, Type, Tag>
where
Type: 'elem_lifetime + ListElement<Tag, Type = Type> + ?Sized,
{
next: Option<NonNull<Type>>,
remaining: usize,
self_lifetime: PhantomData<&'elem_lifetime ()>,
tag: PhantomData<Tag>,
}
pub(crate) struct PopFrontIterator<Type, Tag>
where
Type: 'static + ListElement<Tag, Type = Type> + ?Sized,
{
list: List<Type, Tag>,
}
impl<Type, Tag> Default for List<Type, Tag>
where
Type: ListElement<Tag, Type = Type> + ?Sized,
{
fn default() -> Self {
List {
head: None,
tail: None,
sz: 0,
tag: PhantomData,
}
}
}
impl<Type, Tag> Drop for List<Type, Tag>
where
Type: ListElement<Tag, Type = Type> + ?Sized,
{
fn drop(&mut self) {
self.clear();
assert!(
self.head.is_none() && self.tail.is_none(),
"dropped list must be empty"
);
}
}
impl<Type, Tag> fmt::Debug for List<Type, Tag>
where
Type: fmt::Debug + ListElement<Tag, Type = Type> + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_list().entries(self.iter()).finish()
}
}
impl<Type, Tag> IntoIterator for List<Type, Tag>
where
Type: 'static + ListElement<Tag, Type = Type> + ?Sized,
{
type Item = Pin<&'static Type>;
type IntoIter = PopFrontIterator<Type, Tag>;
fn into_iter(self) -> Self::IntoIter {
PopFrontIterator { list: self }
}
}
unsafe impl<Type, Tag> Send for List<Type, Tag>
where
Type: ListElement<Tag, Type = Type> + Send + ?Sized,
Tag: Send,
{
}
impl<Type, Tag> List<Type, Tag>
where
Type: ListElement<Tag, Type = Type> + ?Sized,
{
const unsafe fn get_ref<'a>(p: NonNull<Type>) -> &'a Type {
unsafe { p.into_ref() }
}
unsafe fn get_entry<'a>(p: NonNull<Type>) -> &'a ListEntry<Type> {
unsafe { Self::get_ref(p).get_entry() }
}
unsafe fn get_entry_mut<'a>(p: NonNull<Type>) -> &'a mut ListEntry<Type> {
unsafe { Self::get_ref(p).get_entry_mut() }
}
fn assert_invariant(&self) {
assert!(
self.head.is_none() == self.tail.is_none(),
"head and tail must agree on if there are some/none elements in the list"
);
}
#[cfg(any(test, feature = "linked_list_reachability_assert"))]
fn reachable(&self, e: &Type) -> bool {
let mut iter = self.head.clone();
while let Some(iter_elem_ref) = iter.map(|ptr| unsafe { Self::get_ref(ptr) }) {
if ptr::eq(iter_elem_ref, e) {
return true;
}
iter = iter_elem_ref.get_entry().succ.clone();
}
false
}
fn link_element(
&mut self,
e: Pin<&Type>,
opt_pred: Option<NonNull<Type>>,
opt_succ: Option<NonNull<Type>>,
) -> NonNull<Type> {
let e_ptr: NonNull<Type> = NonNull::from_ref(e.get_ref());
let e_entry: &mut ListEntry<Type> = unsafe { Self::get_entry_mut(e_ptr.clone()) };
assert!(
!e_entry.linked,
"to-be-inserted element must not be part of a list already"
);
assert!(
e_entry.succ.is_none() && e_entry.pred.is_none(),
"predecessor and successor pointers should be None"
);
self.assert_invariant();
match opt_pred
.clone()
.map(|pred| unsafe { Self::get_entry(pred) })
{
Some(pred_entry) => assert_eq!(
pred_entry.succ, opt_succ,
"pred's successor must match opt_succ"
),
None => assert_eq!(self.head, opt_succ),
}
match opt_succ
.clone()
.map(|succ| unsafe { Self::get_entry(succ) })
{
Some(succ_entry) => assert_eq!(
succ_entry.pred, opt_pred,
"succ's predecessor must match opt_pred"
),
None => assert_eq!(self.tail, opt_pred),
}
#[cfg(feature = "linked_list_reachability_assert")]
if let Some(predecessor_or_successor_ref) = opt_pred
.clone()
.or(opt_succ.clone())
.map(|ptr| unsafe { Self::get_ref(ptr) })
{
debug_assert!(self.reachable(predecessor_or_successor_ref));
}
match opt_pred
.clone()
.map(|ptr| unsafe { Self::get_entry_mut(ptr) })
{
Some(pred_state) => pred_state.succ = Some(e_ptr.clone()),
None => self.head = Some(e_ptr.clone()),
}
match opt_succ
.clone()
.map(|ptr| unsafe { Self::get_entry_mut(ptr) })
{
Some(succ_state) => succ_state.pred = Some(e_ptr.clone()),
None => self.tail = Some(e_ptr.clone()),
}
e_entry.succ = opt_succ;
e_entry.pred = opt_pred;
e_entry.linked = true;
self.sz += 1;
self.assert_invariant(); #[cfg(feature = "linked_list_reachability_assert")]
debug_assert!(self.reachable(unsafe { Self::get_ref(e_ptr.clone()) }));
e_ptr
}
fn unlink_element<'a>(&mut self, e_ptr: NonNull<Type>) -> Pin<&'a Type> {
let e_entry: &mut ListEntry<Type> = unsafe { Self::get_entry_mut(e_ptr.clone()) };
let pred = e_entry.pred.clone();
let succ = e_entry.succ.clone();
self.assert_invariant();
#[cfg(feature = "linked_list_reachability_assert")]
debug_assert!(
self.reachable(unsafe { Self::get_ref(e_ptr.clone()) }),
"unlinked element must be part of this list"
);
match pred.clone().map(|ptr| unsafe { Self::get_entry(ptr) }) {
Some(pred_entry) => assert_eq!(pred_entry.succ, Some(e_ptr.clone())),
None => assert_eq!(self.head, Some(e_ptr.clone())),
}
match succ.clone().map(|ptr| unsafe { Self::get_entry(ptr) }) {
Some(succ_entry) => assert_eq!(succ_entry.pred, Some(e_ptr.clone())),
None => assert_eq!(self.tail, Some(e_ptr.clone())),
}
match pred.clone().map(|ptr| unsafe { Self::get_entry_mut(ptr) }) {
Some(pred_entry) => pred_entry.succ = succ.clone(),
None => self.head = succ.clone(),
}
match succ.clone().map(|ptr| unsafe { Self::get_entry_mut(ptr) }) {
Some(succ_entry) => succ_entry.pred = pred.clone(),
None => self.tail = pred.clone(),
}
e_entry.succ = None;
e_entry.pred = None;
e_entry.linked = false;
self.sz -= 1;
self.assert_invariant(); #[cfg(feature = "linked_list_reachability_assert")]
debug_assert!(!self.reachable(unsafe { Self::get_ref(e_ptr.clone()) }));
unsafe { Pin::new_unchecked(Self::get_ref(e_ptr)) }
}
pub(crate) fn is_empty(&self) -> bool {
self.assert_invariant();
self.head.is_none()
}
pub(crate) fn len(&self) -> usize {
self.assert_invariant();
self.sz
}
pub(crate) fn push_back(&mut self, e: Pin<&Type>) {
self.link_element(e, self.tail.clone(), None);
}
#[cfg(test)]
pub(crate) fn contains(&self, e: &Type) -> bool {
self.assert_invariant();
self.reachable(e)
}
pub(crate) fn remove<'a>(&mut self, e: &'a Type) -> Pin<&'a Type> {
self.unlink_element(NonNull::from_ref(e))
}
pub(crate) fn iter(&self) -> ListIterator<'_, Type, Tag> {
self.assert_invariant();
ListIterator {
next: self.head.clone(),
remaining: self.sz,
self_lifetime: PhantomData,
tag: self.tag,
}
}
pub(crate) fn clear(&mut self) {
while let Some(entry) = self.head.clone() {
self.unlink_element(entry);
}
}
fn pop_front(&mut self) -> Option<Pin<&'static Type>> {
self.head.clone().map(|ptr| self.unlink_element(ptr))
}
pub(crate) fn pop_back<'a>(&mut self) -> Option<Pin<&'a Type>> {
self.tail.clone().map(|ptr| self.unlink_element(ptr))
}
#[cfg(not(all(
feature = "single_generation",
any(feature = "single_generation_mt", not(feature = "multi_thread"))
)))]
pub(crate) fn merge(&mut self, other: &mut Self) {
self.assert_invariant();
other.assert_invariant();
if !other.is_empty() {
if self.is_empty() {
self.head = other.head.take();
self.tail = other.tail.take();
} else {
unsafe {
Self::get_entry_mut(other.head.as_ref().unwrap().clone()).pred =
self.tail.clone();
Self::get_entry_mut(self.tail.as_ref().unwrap().clone()).succ =
other.head.clone();
self.tail = other.tail.take();
other.head = None;
}
}
self.sz += other.sz;
other.sz = 0;
}
self.assert_invariant();
other.assert_invariant();
}
}
impl<'elem_lifetime, Type, Tag> Default for ListIterator<'elem_lifetime, Type, Tag>
where
Type: 'elem_lifetime + ListElement<Tag, Type = Type> + ?Sized,
{
fn default() -> Self {
ListIterator {
next: None,
remaining: 0,
self_lifetime: PhantomData,
tag: PhantomData,
}
}
}
impl<'elem_lifetime, Type, Tag> Clone for ListIterator<'elem_lifetime, Type, Tag>
where
Type: 'elem_lifetime + ListElement<Tag, Type = Type> + ?Sized,
{
fn clone(&self) -> Self {
ListIterator {
next: self.next.clone(),
remaining: self.remaining,
self_lifetime: self.self_lifetime,
tag: self.tag,
}
}
}
impl<'elem_lifetime, Type, Tag> Iterator for ListIterator<'elem_lifetime, Type, Tag>
where
Type: 'elem_lifetime + ListElement<Tag, Type = Type> + ?Sized,
{
type Item = Pin<&'elem_lifetime Type>;
fn next(&mut self) -> Option<Self::Item> {
match self
.next
.clone()
.map(|ptr| unsafe { List::<Type, Tag>::get_ref(ptr) })
{
Some(next_elem) => {
assert!(self.remaining > 0);
self.next = next_elem.get_entry().succ.clone();
self.remaining -= 1;
Some(unsafe { Pin::new_unchecked(next_elem) })
}
None => {
assert_eq!(self.remaining, 0);
None
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}
impl<'elem_lifetime, Type, Tag> ExactSizeIterator for ListIterator<'elem_lifetime, Type, Tag>
where
Type: 'elem_lifetime + ListElement<Tag, Type = Type> + ?Sized,
{
fn len(&self) -> usize {
self.remaining
}
}
impl<Type, Tag> Iterator for PopFrontIterator<Type, Tag>
where
Type: 'static + ListElement<Tag, Type = Type> + ?Sized,
{
type Item = Pin<&'static Type>;
fn next(&mut self) -> Option<Self::Item> {
self.list.pop_front()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.list.len(), Some(self.list.len()))
}
}
impl<Type, Tag> ExactSizeIterator for PopFrontIterator<Type, Tag>
where
Type: 'static + ListElement<Tag, Type = Type> + ?Sized,
{
fn len(&self) -> usize {
self.list.len()
}
}