use { crate::utils::numcell::NumCell, std::{ cell::Cell, fmt::{Debug, Formatter}, mem, ops::Deref, ptr::NonNull, }, }; const LINKED_NODE_REF_COUNT: usize = !(!0 >> 1); pub struct LinkedList { root: LinkedNode, } impl Debug for LinkedList { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_list().entries(self.iter()).finish() } } impl Default for LinkedList { fn default() -> Self { Self::new() } } impl LinkedList { pub fn new() -> Self { Self { root: LinkedNode::new(None), } } pub fn append_all(&self, other: &LinkedList) { if other.is_empty() || self.root.data == other.root.data { return; } unsafe { let o_root = other.root.data; let o_first = o_root.as_ref().next.get(); let o_last = o_root.as_ref().prev.get(); let s_first = self.root.data; let s_last = s_first.as_ref().prev.get(); o_first.as_ref().prev.set(s_last); s_last.as_ref().next.set(o_first); o_last.as_ref().next.set(s_first); s_first.as_ref().prev.set(o_last); o_root.as_ref().next.set(o_root); o_root.as_ref().prev.set(o_root); } } fn endpoint(&self, ep: NonNull>) -> Option> { unsafe { if ep != self.root.data { ep.as_ref().rc.fetch_add(1); Some(NodeRef { data: ep }) } else { None } } } pub fn is_empty(&self) -> bool { self.last().is_none() } pub fn is_not_empty(&self) -> bool { !self.is_empty() } pub fn last(&self) -> Option> { unsafe { self.endpoint(self.root.data.as_ref().prev.get()) } } pub fn first(&self) -> Option> { unsafe { self.endpoint(self.root.data.as_ref().next.get()) } } pub fn add_last(&self, t: T) -> LinkedNode { self.root.prepend(t) } pub fn add_first(&self, t: T) -> LinkedNode { self.root.append(t) } pub fn add_last_existing(&self, t: &NodeRef) { self.root.prepend_existing(t) } #[expect(dead_code)] pub fn add_first_existing(&self, t: &NodeRef) { self.root.append_existing(t) } pub fn iter(&self) -> LinkedListIter { unsafe { let root = self.root.data.as_ref(); root.rc.fetch_add(1); root.next.get().as_ref().rc.fetch_add(1); LinkedListIter { root: self.root.data, next: root.next.get(), } } } pub fn rev_iter(&self) -> RevLinkedListIter { unsafe { let root = self.root.data.as_ref(); root.rc.fetch_add(1); root.prev.get().as_ref().rc.fetch_add(1); RevLinkedListIter { root: self.root.data, next: root.prev.get(), } } } } pub struct LinkedListIter { root: NonNull>, next: NonNull>, } impl Iterator for LinkedListIter { type Item = NodeRef; fn next(&mut self) -> Option { if self.root == self.next { return None; } unsafe { let old_next = self.next; self.next = old_next.as_ref().next.get(); self.next.as_ref().rc.fetch_add(1); Some(NodeRef { data: old_next }) } } } impl Drop for LinkedListIter { fn drop(&mut self) { unsafe { dec_ref_count(self.root, 1); dec_ref_count(self.next, 1); } } } pub struct RevLinkedListIter { root: NonNull>, next: NonNull>, } impl Iterator for RevLinkedListIter { type Item = NodeRef; fn next(&mut self) -> Option { if self.root == self.next { return None; } unsafe { let old_next = self.next; self.next = old_next.as_ref().prev.get(); self.next.as_ref().rc.fetch_add(1); Some(NodeRef { data: old_next }) } } } impl Drop for RevLinkedListIter { fn drop(&mut self) { unsafe { dec_ref_count(self.root, 1); dec_ref_count(self.next, 1); } } } #[repr(transparent)] #[must_use] pub struct LinkedNode { data: NonNull>, } impl Debug for LinkedNode { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked().fmt(f) } } } impl Deref for LinkedNode { type Target = NodeRef; fn deref(&self) -> &Self::Target { unsafe { mem::transmute(self) } } } #[repr(transparent)] pub struct NodeRef { data: NonNull>, } impl Debug for NodeRef { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked().fmt(f) } } } impl Deref for NodeRef { type Target = T; fn deref(&self) -> &Self::Target { unsafe { self.data.as_ref().data.as_ref().unwrap_unchecked() } } } impl Drop for NodeRef { fn drop(&mut self) { unsafe { dec_ref_count(self.data, 1); } } } impl Clone for NodeRef { fn clone(&self) -> Self { unsafe { self.data.as_ref().rc.fetch_add(1); Self { data: self.data } } } } impl NodeRef { pub fn prepend(&self, t: T) -> LinkedNode { unsafe { prepend(self.data, t) } } pub fn append(&self, t: T) -> LinkedNode { unsafe { append(self.data, t) } } pub fn prepend_existing(&self, t: &NodeRef) { unsafe { prepend_existing(self.data, t) } } pub fn append_existing(&self, t: &NodeRef) { unsafe { append_existing(self.data, t) } } fn peer(&self, peer: F) -> Option> where F: FnOnce(&NodeData) -> &Cell>>, { unsafe { let data = self.data.as_ref(); let other = peer(data).get(); if other.as_ref().data.is_some() { other.as_ref().rc.fetch_add(1); Some(NodeRef { data: other }) } else { None } } } pub fn prev(&self) -> Option> { self.peer(|d| &d.prev) } pub fn next(&self) -> Option> { self.peer(|d| &d.next) } pub fn detach(&self) { unsafe { let data = self.data.as_ref(); data.prev.get().as_ref().next.set(data.next.get()); data.next.get().as_ref().prev.set(data.prev.get()); data.prev.set(self.data); data.next.set(self.data); } } } struct NodeData { rc: NumCell, prev: Cell>>, next: Cell>>, data: Option, } unsafe fn dec_ref_count(slf: NonNull>, n: usize) { unsafe { if slf.as_ref().rc.fetch_sub(n) == n { drop(Box::from_raw(slf.as_ptr())); } } } impl Drop for LinkedNode { fn drop(&mut self) { unsafe { self.detach(); dec_ref_count(self.data, LINKED_NODE_REF_COUNT); } } } impl LinkedNode { fn new(t: Option) -> Self { let node = Box::leak(Box::new(NodeData { rc: NumCell::new(LINKED_NODE_REF_COUNT), prev: Cell::new(NonNull::dangling()), next: Cell::new(NonNull::dangling()), data: t, })); let ptr = NonNull::from(&mut *node); node.prev.set(ptr); node.next.set(ptr); LinkedNode { data: node.into() } } pub fn detached(t: T) -> Self { Self::new(Some(t)) } pub fn to_ref(&self) -> NodeRef { unsafe { self.data.as_ref().rc.fetch_add(1); NodeRef { data: self.data } } } } unsafe fn prepend_existing(data: NonNull>, t: &NodeRef) { unsafe { let dref = data.as_ref(); let tref = t.data.as_ref(); if tref.rc.get() < LINKED_NODE_REF_COUNT { log::error!("Trying to prepend a node whose linked node has already been dropped"); return; } t.detach(); tref.prev.set(dref.prev.get()); tref.next.set(data); dref.prev.get().as_ref().next.set(t.data); dref.prev.set(t.data); } } unsafe fn prepend(data: NonNull>, t: T) -> LinkedNode { unsafe { let dref = data.as_ref(); let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData { rc: NumCell::new(LINKED_NODE_REF_COUNT), prev: Cell::new(dref.prev.get()), next: Cell::new(data), data: Some(t), }))); dref.prev.get().as_ref().next.set(node); dref.prev.set(node); LinkedNode { data: node } } } unsafe fn append_existing(data: NonNull>, t: &NodeRef) { unsafe { let dref = data.as_ref(); let tref = t.data.as_ref(); if tref.rc.get() < LINKED_NODE_REF_COUNT { log::error!("Trying to append a node whose linked node has already been dropped"); return; } t.detach(); tref.prev.set(data); tref.next.set(dref.next.get()); dref.next.get().as_ref().prev.set(t.data); dref.next.set(t.data); } } unsafe fn append(data: NonNull>, t: T) -> LinkedNode { unsafe { let dref = data.as_ref(); let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData { rc: NumCell::new(LINKED_NODE_REF_COUNT), prev: Cell::new(data), next: Cell::new(dref.next.get()), data: Some(t), }))); dref.next.get().as_ref().prev.set(node); dref.next.set(node); LinkedNode { data: node } } }