#![forbid(unsafe_code)]
#![warn(missing_docs)]
pub extern crate petgraph;
use petgraph as pg;
use petgraph::graph::IndexType;
pub use petgraph::graph::NodeIndex;
type DefIndex = u32;
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::WalkNeighbors<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 }, 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.neighbors_directed(node, pg::Outgoing).detach();
while let Some((child_edge, child_node)) = children.next(&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,
}
}
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.neighbors_directed(parent, pg::Outgoing).detach();
WalkChildren { walk_edges }
}
pub fn siblings(&self, child: NodeIndex<Ix>) -> Siblings<Ix> {
let maybe_siblings = self.parent(child).map(|parent| self.children(parent));
Siblings {
child,
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,
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(&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)
}
})
})
}
}