use crate::utils::numcell::NumCell; use crate::utils::ptr_ext::PtrExt; use std::cell::Cell; use std::fmt::{Debug, Formatter}; use std::mem; use std::ops::Deref; use std::ptr::NonNull; 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 { let node = Box::into_raw(Box::new(NodeData { rc: NumCell::new(1), prev: Cell::new(NonNull::dangling()), next: Cell::new(NonNull::dangling()), data: None, })); unsafe { node.deref().prev.set(NonNull::new_unchecked(node)); node.deref().next.set(NonNull::new_unchecked(node)); Self { root: LinkedNode { data: NonNull::new_unchecked(node), }, } } } 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 last(&self) -> Option> { unsafe { self.endpoint(self.root.data.as_ref().prev.get()) } } #[allow(dead_code)] 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 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)] 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) } } 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) } } struct NodeData { rc: NumCell, prev: Cell>>, next: Cell>>, data: Option, } unsafe fn dec_ref_count(slf: NonNull>, n: usize) { 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 { { 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); } dec_ref_count(self.data, 1); } } } impl LinkedNode { 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 to_ref(&self) -> NodeRef { unsafe { self.data.as_ref().rc.fetch_add(1); NodeRef { data: self.data } } } } unsafe fn prepend(data: NonNull>, t: T) -> LinkedNode { let dref = data.as_ref(); let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData { rc: NumCell::new(1), 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(data: NonNull>, t: T) -> LinkedNode { let dref = data.as_ref(); let node = NonNull::new_unchecked(Box::into_raw(Box::new(NodeData { rc: NumCell::new(1), 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 } }