use crate::utils::ptr_ext::PtrExt; use crate::NumCell; use std::cell::Cell; use std::mem::MaybeUninit; use std::ops::Deref; use std::ptr::NonNull; pub struct LinkedList { root: LinkedNode, } 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(3), prev: Cell::new(NonNull::dangling()), next: Cell::new(NonNull::dangling()), data: MaybeUninit::uninit(), })); 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); } } } pub struct LinkedNode { data: NonNull>, } impl Deref for LinkedNode { type Target = T; fn deref(&self) -> &Self::Target { unsafe { self.data.as_ref().data.assume_init_ref() } } } pub struct NodeRef { data: NonNull>, } impl Deref for NodeRef { type Target = T; fn deref(&self) -> &Self::Target { unsafe { self.data.as_ref().data.assume_init_ref() } } } 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 prev(&self) -> NodeRef { unsafe { let data = self.data.as_ref(); let other = data.prev.get(); other.as_ref().rc.fetch_add(1); NodeRef { data: other, } } } #[allow(dead_code)] pub fn next(&self) -> NodeRef { unsafe { let data = self.data.as_ref(); let other = data.next.get(); other.as_ref().rc.fetch_add(1); NodeRef { data: other, } } } } struct NodeData { rc: NumCell, prev: Cell>>, next: Cell>>, data: MaybeUninit, } 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()); } dec_ref_count(self.data, 3); } } } 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(3), prev: Cell::new(dref.prev.get()), next: Cell::new(data), data: MaybeUninit::new(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(3), prev: Cell::new(data), next: Cell::new(dref.next.get()), data: MaybeUninit::new(t), }))); dref.next.get().as_ref().prev.set(node); dref.next.set(node); LinkedNode { data: node } }