use std::fmt::Debug; use std::rc::Rc; #[derive(Debug)] pub struct List { head: Option>>, } impl Clone for List { fn clone(&self) -> Self { List { head: self.head.clone(), } } } #[derive(Debug, Clone)] pub struct Node { data: T, parent: Option>>, } impl Node { pub fn get_data(&self) -> &T { &self.data } } // TODO: This Debug is only needed because of the try_unwrap+expect impl List { pub fn new() -> Self { List { head: None } } pub fn push_front(&self, data: T) -> List { List { head: Some(Rc::new(Node { data: data, parent: self.head.clone(), })), } } pub fn pop_front(&mut self) -> (Option, List) { match self.head.take() { None => (None, List::new()), Some(popped_node) => { let extracted_node = Rc::try_unwrap(popped_node).expect("TODO I should handle this better"); ( Some(extracted_node.data), List { head: extracted_node.parent, }, ) } } } pub fn without_front(&self) -> List { List { head: self.head.as_ref().map(|node| node.parent.clone()).flatten(), } } pub fn get_data(&self) -> Option<&T> { self.head.as_ref().map(|rc_node| &rc_node.data) } pub fn is_empty(&self) -> bool { self.head.is_none() } pub fn ptr_eq(&self, other: &List) -> bool { match (self.head.as_ref(), other.head.as_ref()) { (None, None) => true, (None, Some(_)) | (Some(_), None) => false, (Some(me), Some(them)) => Rc::ptr_eq(me, them), } } pub fn iter(&self) -> impl Iterator>> { NodeIter { position: &self.head, } } pub fn iter_until<'a>(&'a self, other: &'a List) -> impl Iterator>> { NodeIterUntil { position: &self.head, stop: &other.head, } } } pub struct NodeIter<'a, T> { position: &'a Option>>, } impl<'a, T> Iterator for NodeIter<'a, T> { type Item = &'a Rc>; fn next(&mut self) -> Option { let (return_value, next_position) = match &self.position { None => return None, Some(rc_node) => { let next_position = &rc_node.parent; let return_value = rc_node; (return_value, next_position) } }; self.position = next_position; Some(return_value) } } pub struct NodeIterUntil<'a, T> { position: &'a Option>>, stop: &'a Option>>, } impl<'a, T> Iterator for NodeIterUntil<'a, T> { type Item = &'a Rc>; fn next(&mut self) -> Option { match (self.position, self.stop) { (_, None) => {} (None, _) => {} (Some(this_rc), Some(stop_rc)) => { if Rc::ptr_eq(this_rc, stop_rc) { return None; } } }; let (return_value, next_position) = match &self.position { None => return None, Some(rc_node) => { let next_position = &rc_node.parent; let return_value = rc_node; (return_value, next_position) } }; self.position = next_position; Some(return_value) } }