use std::rc::{Rc, Weak}; use std::cell::RefCell; use std::ptr; use r9_macro::SharedFromSelf; use r9_macro_derive::SharedFromSelf; #[derive(Default)] #[derive(SharedFromSelf)] pub struct ListHead { prev: Weak::>, next: Weak::>, data: Weak::>, _self_wp: Weak::>, } impl ListHead { fn new(data: Weak::>) -> Rc::> { let this = Rc::new(RefCell::new(Self{ prev: Default::default(), next: Default::default(), data: data, _self_wp: Default::default(), })); this.borrow_mut()._self_wp = Rc::downgrade(&this); this.borrow_mut().init(); return this; } pub fn new_head() -> Rc::> { return Self::new(Default::default()); } pub fn new_node(data: Weak::>) -> Rc::> { return Self::new(data); } fn init(&mut self) { self.prev = Rc::downgrade(&self.shared_from_self()); self.next = Rc::downgrade(&self.shared_from_self()); } pub fn data(&self) -> Weak::> { return self.data.clone(); } pub fn del_init(&mut self) { self.next.upgrade().unwrap().borrow_mut().prev = self.prev.clone(); self.prev.upgrade().unwrap().borrow_mut().next = self.next.clone(); self.init(); } pub fn empty(&self) -> bool { return ptr::eq(self.next.as_ptr(), Rc::as_ptr(&self.shared_from_self())); } pub fn add_tail(head: &Rc::>, pnew: &Rc::>) { let prev = &head.borrow_mut().prev.clone(); let next = head; next.borrow_mut().prev = Rc::downgrade(pnew); pnew.borrow_mut().next = Rc::downgrade(&next); pnew.borrow_mut().prev = prev.clone(); prev.upgrade().unwrap().borrow_mut().next = Rc::downgrade(pnew); } pub fn first_entry(&self) -> Weak::> { if self.empty() { panic!(""); } return self.next.upgrade().unwrap().borrow().data(); } pub fn replace_init(head: &Rc::>, pnew: &Rc::>) { if head.borrow().empty() { return; } pnew.borrow_mut().next = head.borrow().next.clone(); pnew.borrow_mut().next.upgrade().unwrap().borrow_mut().prev = Rc::downgrade(pnew); pnew.borrow_mut().prev = head.borrow().prev.clone(); pnew.borrow_mut().prev.upgrade().unwrap().borrow_mut().next = Rc::downgrade(pnew); head.borrow_mut().init(); } pub fn for_each(&self, cb: fn (&Weak::>) -> bool) { let mut pos = self.next.clone(); let self_weak = Rc::downgrade(&self.shared_from_self()); while !Weak::ptr_eq(&pos, &self_weak) { if !cb(&pos.upgrade().unwrap().borrow().data()) { break; } pos = pos.upgrade().unwrap().borrow().next.clone(); } } }