use component::*;
use std::collections::VecDeque;
pub struct Components
{
components: Vec<Component>,
max_log_path: usize,
}
pub struct ComponentsIterator<'a>
{
components: &'a Components,
next: usize,
}
impl Components
{
pub(crate) fn new(max_log_path: usize) -> Components
{
Components {components: Vec::new(), max_log_path}
}
pub fn print(&self)
{
for (index, comp) in self.components.iter().enumerate() {
let id = ComponentID(index);
if comp.parent != NO_COMPONENT {
let parent = self.get(comp.parent);
println!(" {}: {} ({})", comp.name, parent.name, id);
} else {
println!(" {}: <none> ({})", comp.name, id);
}
}
}
pub fn get(&self, id: ComponentID) -> &Component
{
assert!(id != NO_COMPONENT);
let index = id.0;
&self.components[index]
}
pub fn get_root(&self) -> (ComponentID, &Component)
{
for (index, comp) in self.components.iter().enumerate() {
let id = ComponentID(index);
if comp.parent == NO_COMPONENT {
return (id, comp);
}
}
panic!("Failed to find the root");
}
pub fn get_top(&self, id: ComponentID) -> (ComponentID, &Component)
{
assert!(id != NO_COMPONENT);
let mut id = id;
loop {
let c = self.get(id);
if c.parent == NO_COMPONENT {
panic!("Can't find the top component when starting at the root");
}
let d = self.get(c.parent);
if d.parent == NO_COMPONENT {
return (id, c);
}
id = c.parent;
}
}
pub fn find_child<P>(&self, id: ComponentID, predicate: P) -> Option<(ComponentID, &Component)>
where P: Fn (ComponentID, &Component) -> bool
{
assert!(id != NO_COMPONENT);
let mut workset = VecDeque::<ComponentID>::new();
let component = &self.components[id.0];
workset.extend(component.children.iter());
while !workset.is_empty() {
let child_id = workset.pop_back().unwrap();
let child = &self.components[child_id.0];
if predicate(child_id, child) {
return Some((child_id, child));
}
for child_id in child.children.iter() {
workset.push_front(*child_id);
}
}
return None
}
pub fn find_parent<P>(&self, id: ComponentID, predicate: P) -> Option<(ComponentID, &Component)>
where P: Fn (ComponentID, &Component) -> bool
{
assert!(id != NO_COMPONENT);
let mut id = id;
loop {
let child = self.get(id);
if child.parent == NO_COMPONENT {
return None;
}
let parent_id = child.parent;
let parent = self.get(parent_id);
if predicate(parent_id, parent) {
return Some((parent_id, parent));
}
id = parent_id;
}
}
pub fn iter(&self) -> ComponentsIterator
{
ComponentsIterator::new(self)
}
pub fn full_path(&self, mut id: ComponentID) -> String
{
let mut path = Vec::new();
while id != NO_COMPONENT {
let c = self.get(id);
path.insert(0, c.name.clone());
id = c.parent;
}
path.join(".")
}
pub fn display_path(&self, id: ComponentID) -> String
{
let path = self.full_path(id);
format!("{0:<1$}", path, self.max_log_path)
}
pub fn is_empty(&self) -> bool
{
self.components.is_empty()
}
pub(crate) fn append(&mut self, id: ComponentID, component: Component, parent: ComponentID)
{
assert!(id != NO_COMPONENT);
if parent != NO_COMPONENT {
self.check_for_dupes(parent, &component);
}
if parent != NO_COMPONENT {
let mut p = self.components.get_mut(parent.0).unwrap();
p.children.push(id);
}
self.components.push(component);
}
#[cfg(debug_assertions)]
fn check_for_dupes(&self, parent_id: ComponentID, child: &Component)
{
let parent = self.get(parent_id);
for &existing_id in parent.children.iter() {
let existing = self.get(existing_id);
assert!(existing.name != child.name, "{} is already a child of {}", child.name, parent.name);
}
}
}
impl<'a> ComponentsIterator<'a>
{
pub fn new(components: &'a Components) -> ComponentsIterator
{
ComponentsIterator {components: components, next: 0}
}
}
impl<'a> Iterator for ComponentsIterator<'a>
{
type Item = (ComponentID, &'a Component);
fn next(&mut self) -> Option<Self::Item>
{
if self.next < self.components.components.len() {
self.next += 1;
Some((ComponentID(self.next-1), &self.components.components[self.next-1]))
} else {
None
}
}
}