I've wasted so much time on this. Yes, I know that the standard library has a double linked list. I don't plan on actually using this code, it's just for learning.
Here is my code (the relevant function is get_at, everything else works):
use std::cell::{Ref, RefCell};
use std::fmt::{Display, Formatter};
use std::rc::{Rc, Weak};
pub struct Node<T> {
data: T,
before: Option<Weak<RefCell<Node<T>>>>,
after: Option<Rc<RefCell<Node<T>>>>
}
impl<T> Node<T> {
pub fn new(data: T) -> Self {
Self {
data, before: None, after: None
}
}
}
pub struct DoubleLinkedList<T> {
first: Option<Rc<RefCell<Node<T>>>>,
last: Option<Weak<RefCell<Node<T>>>>
}
impl<T> DoubleLinkedList<T> {
pub fn new() -> Self {
Self {
first: None, last: None
}
}
pub fn append(&mut self, data: T) {
if self.last.is_some() {
let last_node_ref = self.last.as_ref().unwrap();
let mut new_node = Node::new(data);
new_node.before = Some(last_node_ref.clone());
let new_node_ref = Rc::new(RefCell::new(new_node));
last_node_ref.upgrade().unwrap().borrow_mut().after = Some(new_node_ref.clone());
self.last = Some(Rc::downgrade(&new_node_ref));
} else {
let new_node = Node::new(data);
let rc = Rc::new(RefCell::new(new_node));
self.first = Some(rc.clone());
self.last = Some(Rc::downgrade(&rc));
}
}
pub fn get_at(&self, index: usize) -> Option<Rc<RefCell<Node<T>>>> {
let mut cnt = index;
let mut node = self.first.as_ref().unwrap();
while true {
if cnt != 0 {
node = node.borrow().after.as_ref().unwrap();
cnt -= 1;
} else {
return Some(node.clone());
}
}
None
}
}
impl<T: Display> DoubleLinkedList<T> {
fn fmt_node(node_ref: &Rc<RefCell<Node<T>>>, f: &mut Formatter<'_>) {
let node = node_ref.borrow();
write!(f, "node: {{ val: {}, prev: {}, next: {} }}", node.data,
match node.before {
Some(ref n) => n.upgrade().unwrap().borrow().data.to_string(),
None => "(empty)".to_string()
}, match node.after {
Some(ref n) => n.borrow().data.to_string(),
None => "(empty)".to_string()
}).expect("y no work");
match node.after {
Some(ref next) => Self::fmt_node(next, f),
None => ()
}
}
}
impl<T: Display> Display for DoubleLinkedList<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.first.is_some() {
DoubleLinkedList::fmt_node(self.first.as_ref().unwrap(), f);
write!(f, "")
} else {
write!(f, "(empty list)")
}
}
}
I'm getting the error "temporary value dropped while borrowed" and "returns a reference to a value owned by the current function." From my understanding, this should be possible because the Nodes are all owned by DoubleLinkedList, which should stay alive.
Thanks in advance.