use std::rc::Rc;
use std::mem::{self, MaybeUninit};
#[derive(Clone)]
pub struct GraphNode<T> {
item: T,
previous: Option<Rc<GraphNode<T>>>,
}
impl<T> GraphNode<T> {
pub fn new(item: T, previous: Option<Rc<GraphNode<T>>>) -> GraphNode<T> {
GraphNode {
item,
previous,
}
}
fn take(mut self) -> (T, Option<Rc<GraphNode<T>>>) {
let item = mem::replace(&mut self.item, unsafe { MaybeUninit::zeroed().assume_init() });
let previous = mem::replace(&mut self.previous, None);
mem::forget(self);
(item, previous)
}
#[cfg(debug_assertions)]
pub fn borrow_item<'a>(&'a self) -> &'a T {
&self.item
}
pub fn borrow_previous<'a>(&'a self) -> &'a Option<Rc<GraphNode<T>>> {
&self.previous
}
}
impl<T> Drop for GraphNode<T> {
fn drop(&mut self) {
let mut previous = mem::replace(&mut self.previous, None);
loop {
previous = match previous {
Some(l) => {
match Rc::try_unwrap(l) {
Ok(mut l) => mem::replace(&mut l.previous, None),
Err(_) => break,
}
},
None => break
}
}
}
}
impl<T> IntoIterator for GraphNode<T> {
type Item = T;
type IntoIter = GraphNodeIterator<T>;
fn into_iter(self) -> Self::IntoIter {
GraphNodeIterator {
node: Some(self),
}
}
}
pub struct GraphNodeIterator<T> {
node: Option<GraphNode<T>>,
}
impl<T> GraphNodeIterator<T> {
pub fn empty() -> GraphNodeIterator<T> {
GraphNodeIterator {
node: None,
}
}
}
impl<T> Iterator for GraphNodeIterator<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
let node = mem::replace(&mut self.node, None);
match node {
Some(node) => {
let (item, previous) = node.take();
self.node = previous.map(
|x| Rc::try_unwrap(x).ok()
.expect("Need to drop the other reference before iterating over the final iterator.")
);
Some(item)
},
None => None
}
}
}