#![forbid(unsafe_code)]
#![warn(missing_docs)]
pub extern crate petgraph;
use petgraph as pg;
pub use petgraph::graph::NodeIndex;
use petgraph::graph::{DefIndex, IndexType};
pub type PetGraph<N, Ix> = pg::Graph<N, (), pg::Directed, Ix>;
#[derive(Clone, Debug)]
pub struct RoseTree<N, Ix: IndexType = DefIndex> {
graph: PetGraph<N, Ix>,
}
pub struct ParentRecursion<'a, N: 'a, Ix: IndexType> {
rose_tree: &'a RoseTree<N, Ix>,
child: NodeIndex<Ix>,
}
pub type Children<'a, Ix> = pg::graph::Neighbors<'a, (), Ix>;
pub struct Siblings<'a, Ix: IndexType> {
child: NodeIndex<Ix>,
maybe_siblings: Option<Children<'a, Ix>>,
}
pub struct WalkChildren<Ix: IndexType> {
walk_edges: pg::graph::WalkEdges<Ix>,
}
pub struct WalkSiblings<Ix: IndexType> {
child: NodeIndex<Ix>,
maybe_walk_children: Option<WalkChildren<Ix>>,
}
pub const ROOT: usize = 0;
impl<N, Ix> RoseTree<N, Ix> where Ix: IndexType {
pub fn new(root: N) -> (Self, NodeIndex<Ix>) {
Self::with_capacity(1, root)
}
pub fn with_capacity(nodes: usize, root: N) -> (Self, NodeIndex<Ix>) {
let mut graph = PetGraph::with_capacity(nodes, nodes);
let root = graph.add_node(root);
(RoseTree { graph: graph }, root)
}
pub fn node_count(&self) -> usize {
self.graph.node_count()
}
pub fn graph(&self) -> &PetGraph<N, Ix> {
&self.graph
}
pub fn into_graph(self) -> PetGraph<N, Ix> {
let RoseTree { graph } = self;
graph
}
pub fn add_child(&mut self, parent: NodeIndex<Ix>, kid: N) -> NodeIndex<Ix> {
let kid = self.graph.add_node(kid);
self.graph.add_edge(parent, kid, ());
kid
}
pub fn node_weight(&self, node: NodeIndex<Ix>) -> Option<&N> {
self.graph.node_weight(node)
}
pub fn node_weight_mut(&mut self, node: NodeIndex<Ix>) -> Option<&mut N> {
self.graph.node_weight_mut(node)
}
pub fn index_twice_mut(&mut self, a: NodeIndex<Ix>, b: NodeIndex<Ix>) -> (&mut N, &mut N) {
self.graph.index_twice_mut(a, b)
}
pub fn remove_all_but_root(&mut self) {
if let Some(root) = self.graph.remove_node(NodeIndex::new(0)) {
self.graph.clear();
self.graph.add_node(root);
}
}
pub fn remove_node(&mut self, node: NodeIndex<Ix>) -> Option<N> {
if node.index() == ROOT || self.graph.node_weight(node).is_none() {
return None;
}
let parent = self.parent(node).expect("No parent node found");
let mut children = self.graph.walk_edges_directed(node, pg::Outgoing);
while let Some((child_edge, child_node)) = children.next_neighbor(&self.graph) {
self.graph.remove_edge(child_edge);
self.graph.add_edge(parent, child_node, ());
}
self.graph.remove_node(node)
}
pub fn remove_node_with_children(&mut self, _node: NodeIndex<Ix>) -> Option<RoseTree<N, Ix>> {
unimplemented!();
}
pub fn parent(&self, child: NodeIndex<Ix>) -> Option<NodeIndex<Ix>> {
self.graph.neighbors_directed(child, pg::Incoming).next()
}
pub fn parent_recursion(&self, child: NodeIndex<Ix>) -> ParentRecursion<N, Ix> {
ParentRecursion { rose_tree: self, child: child }
}
pub fn children(&self, parent: NodeIndex<Ix>) -> Children<Ix> {
self.graph.neighbors_directed(parent, pg::Outgoing)
}
pub fn walk_children(&self, parent: NodeIndex<Ix>) -> WalkChildren<Ix> {
let walk_edges = self.graph.walk_edges_directed(parent, pg::Outgoing);
WalkChildren { walk_edges: walk_edges }
}
pub fn siblings(&self, child: NodeIndex<Ix>) -> Siblings<Ix> {
let maybe_siblings = self.parent(child).map(|parent| self.children(parent));
Siblings { child: child, maybe_siblings: maybe_siblings }
}
pub fn walk_siblings(&self, child: NodeIndex<Ix>) -> WalkSiblings<Ix> {
let maybe_walk_children = self.parent(child).map(|parent| self.walk_children(parent));
WalkSiblings { child: child, maybe_walk_children: maybe_walk_children }
}
}
impl<N, Ix> ::std::ops::Index<NodeIndex<Ix>> for RoseTree<N, Ix> where Ix: IndexType {
type Output = N;
fn index(&self, index: NodeIndex<Ix>) -> &N {
&self.graph[index]
}
}
impl<N, Ix> ::std::ops::IndexMut<NodeIndex<Ix>> for RoseTree<N, Ix> where Ix: IndexType {
fn index_mut(&mut self, index: NodeIndex<Ix>) -> &mut N {
&mut self.graph[index]
}
}
impl<'a, Ix> Iterator for Siblings<'a, Ix> where Ix: IndexType {
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<NodeIndex<Ix>> {
let Siblings { child, ref mut maybe_siblings } = *self;
maybe_siblings.as_mut().and_then(|siblings| {
siblings.next().and_then(|sibling| {
if sibling != child { Some(sibling) } else { siblings.next() }
})
})
}
}
impl<'a, N, Ix> Iterator for ParentRecursion<'a, N, Ix> where Ix: IndexType {
type Item = NodeIndex<Ix>;
fn next(&mut self) -> Option<NodeIndex<Ix>> {
let ParentRecursion { ref mut child, ref rose_tree } = *self;
rose_tree.parent(*child).map(|parent| { *child = parent; parent })
}
}
impl<Ix> WalkChildren<Ix> where Ix: IndexType {
pub fn next<N>(&mut self, tree: &RoseTree<N, Ix>) -> Option<NodeIndex<Ix>> {
self.walk_edges.next_neighbor(&tree.graph).map(|(_, n)| n)
}
}
impl<Ix> WalkSiblings<Ix> where Ix: IndexType {
pub fn next<N>(&mut self, tree: &RoseTree<N, Ix>) -> Option<NodeIndex<Ix>> {
let WalkSiblings { child, ref mut maybe_walk_children } = *self;
maybe_walk_children.as_mut().and_then(|walk_children| {
walk_children.next(tree).and_then(|sibling| if child != sibling {
Some(sibling)
} else {
walk_children.next(tree)
})
})
}
}