<commit_before>//! A tree represented via a petgraph graph, used for way-cooler's
//! layout.

use std::iter::Iterator;

use petgraph::EdgeDirection;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex};

use rustwlc::WlcView;

use layout::{Container, ContainerType};

/// Layout tree implemented with petgraph.
#[derive(Debug)]
pub struct Tree {
    graph: Graph<Container, u32>, // Directed graph
    root: NodeIndex
}

impl Tree {
    /// Creates a new layout tree with a root node.
    pub fn new() -> Tree {
        let mut graph = Graph::new();
        let root_ix = graph.add_node(Container::Root);
        Tree { graph: graph, root: root_ix }
    }

    /// Gets the index of the tree's root node
    pub fn root_ix(&self) -> NodeIndex {
        self.root
    }

    /// Gets the weight of a possible edge between two notes
    pub fn get_edge_weight_between(&self, parent_ix: NodeIndex,
                                   child_ix: NodeIndex) -> Option<&u32> {
        self.graph.find_edge(parent_ix, child_ix)
            .and_then(|edge_ix| self.graph.edge_weight(edge_ix))
    }

    /// Gets the edge value of the largest child of the node
    fn largest_child(&self, node: NodeIndex) -> (NodeIndex, u32) {
        use std::cmp::{Ord, Ordering};
        self.graph.edges_directed(node, EdgeDirection::Outgoing)
            .fold((node, 0), |(old_node, old_edge), (new_node, new_edge)|
                  match <u32 as Ord>::cmp(&old_edge, new_edge) {
                      Ordering::Less => (new_node, *new_edge),
                      Ordering::Greater => (old_node, old_edge),
                      Ordering::Equal =>
                          panic!("largest_child: Node {:?} had two equal children {}",
                          node, old_edge)
                  })
    }

    /// Adds a new child to a node at the index, returning the node index
    /// of the new child node.
    pub fn add_child(&mut self, parent_ix: NodeIndex, val: Container) -> NodeIndex {
        let child_ix = self.graph.add_node(val);
        self.attach_child(parent_ix, child_ix);
        child_ix
    }

    /// Add an existing node (detached in the graph) to the tree.
    /// Note that floating nodes shouldn't exist for too long.
    fn attach_child(&mut self, parent_ix: NodeIndex, child_ix: NodeIndex)
                     -> EdgeIndex {
        // Make sure the child doesn't have a parent
        if cfg!(debug_assertions) && self.has_parent(child_ix) {
            panic!("attach_child: child had a parent!")
        }

        let parent_type = self.graph.node_weight(parent_ix)
            .expect("attach_child: parent not found").get_type();
        let child_type = self.graph.node_weight(child_ix)
            .expect("attach_child: child not found").get_type();

        if !parent_type.can_have_child(child_type) {
            panic!("Attempted to give a {:?} a {:?} child!",
                   parent_type, child_type);
        }
        let (_ix, biggest_child) = self.largest_child(parent_ix);
        self.graph.update_edge(parent_ix, child_ix, biggest_child + 1)
    }

    /// Finds the index of the container at the child index's parent,
    /// modifies it so that it's the given child number in the list.
    pub fn set_child_pos(&mut self, child_ix: NodeIndex, mut child_pos: u32) {
        let parent_ix = self.parent_of(child_ix)
            .expect("Child had no parent");
        let siblings = self.children_of(parent_ix);
        if child_pos > siblings.len() as u32 {
            child_pos = siblings.len() as u32;
        }
        let mut counter = child_pos + 1;
        for sibling_ix in siblings {
            let edge_weight = *self.get_edge_weight_between(parent_ix, sibling_ix)
                .expect("Sibling had no edge weight");
            if edge_weight < child_pos {
                continue;
            }
            self.graph.update_edge(parent_ix, sibling_ix, counter);
            counter += 1;
        }
        self.graph.update_edge(parent_ix, child_ix, child_pos);
    }

    /// Detaches a node from the tree (causing there to be two trees).
    /// This should only be done temporarily.
    pub fn detach(&mut self, node_ix: NodeIndex) {
        if let Some(parent_ix) = self.parent_of(node_ix) {
            let edge = self.graph.find_edge(parent_ix, node_ix)
                .expect("detatch: Node has parent but edge cannot be found!");

            self.graph.remove_edge(edge);
        }
        else {
            trace!("detach: Detached a floating node");
        }
    }

    /// Removes a node at the given index. This may invalidate other node
    /// indices.
    ///
    /// From `petgraph`:
    /// Remove a from the graph if it exists, and return its weight.
    ///
    /// If it doesn't exist in the graph, return None.
    ///
    /// Apart from a, this invalidates the last node index in the graph
    /// (that node will adopt the removed node index).
    /// Edge indices are invalidated as they would be following the removal
    /// of each edge with an endpoint in a.
    ///
    /// Computes in O(e') time, where e' is the number of affected edges,
    /// including n calls to .remove_edge() where n is the number of edges
    /// with an endpoint in a, and including the edges with an endpoint in
    /// the displaced node.
    pub fn remove(&mut self, node_ix: NodeIndex) -> Option<Container> {
        self.graph.remove_node(node_ix)
    }

    /// Moves a node between two indices
    pub fn move_node(&mut self, node_ix: NodeIndex, new_parent: NodeIndex) {
        self.detach(node_ix);
        self.attach_child(new_parent, node_ix);
    }

    /// Whether a node has a parent
    #[allow(dead_code)]
    pub fn has_parent(&self, node_ix: NodeIndex) -> bool {
        let neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        match neighbors.count() {
            0 => false,
            1 => true,
            _ => panic!("Node has more than one parent!")
        }
    }

    /// Gets the parent of a node, if the node exists
    pub fn parent_of(&self, node_ix: NodeIndex) -> Option<NodeIndex> {
        let mut neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        if cfg!(debug_assertions) {
            let result = neighbors.next();
            if neighbors.next().is_some() {
                panic!("parent_of: node has multiple parents!")
            }
            result
        }
        else {
            neighbors.next()
        }
    }

    /// Gets an iterator to the children of a node.
    ///
    /// Will return an empty iterator if the node has no children or
    /// if the node does not exist.
    pub fn children_of(&self, node_ix: NodeIndex) -> Vec<NodeIndex> {
        let mut edges = self.graph.edges_directed(node_ix, EdgeDirection::Outgoing)
            .collect::<Vec<(NodeIndex, &u32)>>();
        edges.sort_by_key(|&(ref _ix, ref edge)| *edge);
        edges.into_iter().map(|(ix, _edge)| ix).collect()
    }

    /// Gets the container of the given node.
    pub fn get(&self, node_ix: NodeIndex) -> Option<&Container> {
        self.graph.node_weight(node_ix)
    }

    /// Gets a mutable reference to a given node
    pub fn get_mut(&mut self, node_ix: NodeIndex) -> Option<&mut Container> {
        self.graph.node_weight_mut(node_ix)
    }

    /// Gets the ContainerType of the selected node
    pub fn node_type(&self, node_ix: NodeIndex) -> Option<ContainerType> {
        self.graph.node_weight(node_ix).map(Container::get_type)
    }

    /// Attempts to get an ancestor matching the matching type
    pub fn ancestor_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        let mut curr_ix = node_ix;
        while let Some(parent_ix) = self.parent_of(curr_ix) {
            let parent = self.graph.node_weight(parent_ix)
                .expect("ancestor_of_type: parent_of invalid");
            if parent.get_type() == container_type {
                return Some(parent_ix)
            }
            curr_ix = parent_ix;
        }
        return None;
    }

    /// Attempts to get a descendant of the matching type
    /// Looks down the left side of the tree first
    pub fn descendant_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        if let Some(container) = self.get(node_ix) {
            if container.get_type() == container_type {
                return Some(node_ix)
            }
        }
        for child in self.children_of(node_ix) {
            if let Some(desc) = self.descendant_of_type(child, container_type) {
                return Some(desc)
            }
        }
        return None
    }

    /// Attempts to get a descendant of the matching type.
    /// Looks down the right side of the tree first
    pub fn descendant_of_type_right(&self, node_ix: NodeIndex,
                              container_type: ContainerType) -> Option<NodeIndex> {
        if let Some(container) = self.get(node_ix) {
            if container.get_type() == container_type {
                return Some(node_ix)
            }
        }
        for child in self.children_of(node_ix).iter().rev() {
            if let Some(desc) = self.descendant_of_type(*child, container_type) {
                return Some(desc)
            }
        }
        return None
    }

    /// Finds a node by the view handle.
    pub fn descendant_with_handle(&self, node_ix: NodeIndex, search_handle: &WlcView)
                               -> Option<NodeIndex> {
        self.get(node_ix).and_then(|node| match node {
            &Container::View { ref handle, .. } => {
                if handle == search_handle {
                    return Some(node_ix)
                }
                else {
                    return None
                }
            },
            _ => {
                for child in self.children_of(node_ix) {
                    if let Some(found) = self.descendant_with_handle(child,
                                                              search_handle) {
                        return Some(found)
                    }
                }
                return None
            }
        })
    }

    /// Returns the node indices of any node that is a descendant of a node
    pub fn all_descendants_of(&self, node_ix: &NodeIndex) -> Vec<NodeIndex> {
        let mut index: usize = 0;
        let mut nodes: Vec<NodeIndex> = self.graph.edges_directed(*node_ix,
                                                      EdgeDirection::Outgoing)
            .map(|(ix, _)| ix).collect();
        while index != nodes.len() {
            let cur_node: &NodeIndex = &nodes[index].clone();
            let children = self.graph.edges_directed(*cur_node,
                                                     EdgeDirection::Outgoing);
            let size_hint = children.size_hint();
            nodes.reserve(size_hint.1.unwrap_or(size_hint.0));
            for (ix, _) in children {
                nodes.push(ix);
            }
            index += 1;
        }
        nodes
    }

    /// Sets the node and its children's visibility
    pub fn set_family_visible(&mut self, node_ix: NodeIndex, visible: bool) {
        self.get_mut(node_ix).map(|c| c.set_visibility(visible));
        for child in self.children_of(node_ix) {
            self.set_family_visible(child, visible);
        }
    }

    /// Determines if a Node index is the last one in the adjacency list
    /// (and so will be moved in a removal)
    pub fn is_last_ix(&self, node_ix: NodeIndex) -> bool {
        if self.graph.node_count() == 0 {
            false
        } else {
            self.graph.node_count() - 1 == node_ix.index()
        }
    }
}

use std::ops::{Index, IndexMut};

impl Index<NodeIndex> for Tree {
    type Output = Container;
    #[inline]
    fn index(&self, index: NodeIndex) -> &Self::Output {
        self.get(index).expect("graph_tree: node not found")
    }
}

impl IndexMut<NodeIndex> for Tree {
    #[inline]
    fn index_mut(&mut self, index: NodeIndex) -> &mut Self::Output {
        self.get_mut(index).expect("graph_tree: node not found")
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use layout::container::*;
    use rustwlc::*;

    /// Makes a very basic tree.
    /// There is only one output,
    /// Two workspaces,
    /// First workspace has a single view in the root container,
    /// second workspace has a container with two views in it
    /// (the container is a child of the root container).
    ///
    /// The active container is the only view in the first workspace
    #[allow(unused_variables)]
    fn basic_tree() -> Tree {
        let mut tree = Tree::new();
        let fake_view_1 = WlcView::root();
        let fake_output = fake_view_1.clone().as_output();
        let root_ix = tree.root_ix();
        let fake_size = Size { h: 800, w: 600 };
        let fake_geometry = Geometry {
            size: fake_size.clone(),
            origin: Point { x: 0, y: 0 }
        };

        let output_ix = tree.add_child(root_ix, Container::new_output(fake_output));
        let workspace_1_ix = tree.add_child(output_ix,
                                                Container::new_workspace("1".to_string(),
                                                                   fake_size.clone()));
        let root_container_1_ix = tree.add_child(workspace_1_ix,
                                                Container::new_container(fake_geometry.clone()));
        let workspace_2_ix = tree.add_child(output_ix,
                                                Container::new_workspace("2".to_string(),
                                                                     fake_size.clone()));
        let root_container_2_ix = tree.add_child(workspace_2_ix,
                                                Container::new_container(fake_geometry.clone()));
        /* Workspace 1 containers */
        let wkspc_1_view = tree.add_child(root_container_1_ix,
                                                Container::new_view(fake_view_1.clone()));
        /* Workspace 2 containers */
        let wkspc_2_container = tree.add_child(root_container_2_ix,
                                                Container::new_container(fake_geometry.clone()));
        let wkspc_2_sub_view_1 = tree.add_child(wkspc_2_container,
                                                Container::new_view(fake_view_1.clone()));
        let wkspc_2_sub_view_2 = tree.add_child(wkspc_2_container,
                                                Container::new_view(fake_view_1.clone()));
        tree
    }

    #[test]
    fn test_descendents_of() {
        let basic_tree = basic_tree();
        let children_of_root = basic_tree.all_descendants_of(&basic_tree.root);
        assert_eq!(children_of_root.len(), 9);
        let simple_view = basic_tree.descendant_of_type(basic_tree.root,
                                                        ContainerType::View)
            .expect("No view in the basic test tree");
        let children_of_view = basic_tree.all_descendants_of(&simple_view);
        assert_eq!(children_of_view.len(), 0);
    }

}
<commit_msg>Added UUID map so clients can reference containers<commit_after>//! A tree represented via a petgraph graph, used for way-cooler's
//! layout.

use std::iter::Iterator;
use std::collections::HashMap;

use petgraph::EdgeDirection;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex};
use uuid::Uuid;

use rustwlc::WlcView;

use layout::{Container, ContainerType};

/// Layout tree implemented with petgraph.
#[derive(Debug)]
pub struct Tree {
    graph: Graph<Container, u32>, // Directed graph
    id_map: HashMap<Uuid, NodeIndex>,
    root: NodeIndex
}

impl Tree {
    /// Creates a new layout tree with a root node.
    pub fn new() -> Tree {
        let mut graph = Graph::new();
        let root_ix = graph.add_node(Container::Root);
        Tree { graph: graph,
               id_map: HashMap::new(),
               root: root_ix
        }
    }

    /// Gets the index of the tree's root node
    pub fn root_ix(&self) -> NodeIndex {
        self.root
    }

    /// Gets the weight of a possible edge between two notes
    pub fn get_edge_weight_between(&self, parent_ix: NodeIndex,
                                   child_ix: NodeIndex) -> Option<&u32> {
        self.graph.find_edge(parent_ix, child_ix)
            .and_then(|edge_ix| self.graph.edge_weight(edge_ix))
    }

    /// Gets the edge value of the largest child of the node
    fn largest_child(&self, node: NodeIndex) -> (NodeIndex, u32) {
        use std::cmp::{Ord, Ordering};
        self.graph.edges_directed(node, EdgeDirection::Outgoing)
            .fold((node, 0), |(old_node, old_edge), (new_node, new_edge)|
                  match <u32 as Ord>::cmp(&old_edge, new_edge) {
                      Ordering::Less => (new_node, *new_edge),
                      Ordering::Greater => (old_node, old_edge),
                      Ordering::Equal =>
                          panic!("largest_child: Node {:?} had two equal children {}",
                          node, old_edge)
                  })
    }

    /// Adds a new child to a node at the index, returning the node index
    /// of the new child node.
    pub fn add_child(&mut self, parent_ix: NodeIndex, val: Container) -> NodeIndex {
        let id = val.get_id().unwrap();
        let child_ix = self.graph.add_node(val);
        self.attach_child(parent_ix, child_ix);
        self.id_map.insert(id, child_ix);
        child_ix
    }

    /// Add an existing node (detached in the graph) to the tree.
    /// Note that floating nodes shouldn't exist for too long.
    fn attach_child(&mut self, parent_ix: NodeIndex, child_ix: NodeIndex)
                     -> EdgeIndex {
        // Make sure the child doesn't have a parent
        if cfg!(debug_assertions) && self.has_parent(child_ix) {
            panic!("attach_child: child had a parent!")
        }

        let parent_type = self.graph.node_weight(parent_ix)
            .expect("attach_child: parent not found").get_type();
        let child_type = self.graph.node_weight(child_ix)
            .expect("attach_child: child not found").get_type();

        if !parent_type.can_have_child(child_type) {
            panic!("Attempted to give a {:?} a {:?} child!",
                   parent_type, child_type);
        }
        let (_ix, biggest_child) = self.largest_child(parent_ix);
        self.graph.update_edge(parent_ix, child_ix, biggest_child + 1)
    }

    /// Finds the index of the container at the child index's parent,
    /// modifies it so that it's the given child number in the list.
    pub fn set_child_pos(&mut self, child_ix: NodeIndex, mut child_pos: u32) {
        let parent_ix = self.parent_of(child_ix)
            .expect("Child had no parent");
        let siblings = self.children_of(parent_ix);
        if child_pos > siblings.len() as u32 {
            child_pos = siblings.len() as u32;
        }
        let mut counter = child_pos + 1;
        for sibling_ix in siblings {
            let edge_weight = *self.get_edge_weight_between(parent_ix, sibling_ix)
                .expect("Sibling had no edge weight");
            if edge_weight < child_pos {
                continue;
            }
            self.graph.update_edge(parent_ix, sibling_ix, counter);
            counter += 1;
        }
        self.graph.update_edge(parent_ix, child_ix, child_pos);
    }

    /// Detaches a node from the tree (causing there to be two trees).
    /// This should only be done temporarily.
    pub fn detach(&mut self, node_ix: NodeIndex) {
        if let Some(parent_ix) = self.parent_of(node_ix) {
            let edge = self.graph.find_edge(parent_ix, node_ix)
                .expect("detatch: Node has parent but edge cannot be found!");

            self.graph.remove_edge(edge);
        }
        else {
            trace!("detach: Detached a floating node");
        }
    }

    /// Removes a node at the given index. This may invalidate other node
    /// indices.
    ///
    /// From `petgraph`:
    /// Remove a from the graph if it exists, and return its weight.
    ///
    /// If it doesn't exist in the graph, return None.
    ///
    /// Apart from a, this invalidates the last node index in the graph
    /// (that node will adopt the removed node index).
    /// Edge indices are invalidated as they would be following the removal
    /// of each edge with an endpoint in a.
    ///
    /// Computes in O(e') time, where e' is the number of affected edges,
    /// including n calls to .remove_edge() where n is the number of edges
    /// with an endpoint in a, and including the edges with an endpoint in
    /// the displaced node.
    pub fn remove(&mut self, node_ix: NodeIndex) -> Option<Container> {
        let id = self.graph[node_ix].get_id().unwrap();
        self.id_map.remove(&id);
        self.graph.remove_node(node_ix)
    }

    /// Moves a node between two indices
    pub fn move_node(&mut self, node_ix: NodeIndex, new_parent: NodeIndex) {
        self.detach(node_ix);
        self.attach_child(new_parent, node_ix);
    }

    /// Whether a node has a parent
    #[allow(dead_code)]
    pub fn has_parent(&self, node_ix: NodeIndex) -> bool {
        let neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        match neighbors.count() {
            0 => false,
            1 => true,
            _ => panic!("Node has more than one parent!")
        }
    }

    /// Gets the parent of a node, if the node exists
    pub fn parent_of(&self, node_ix: NodeIndex) -> Option<NodeIndex> {
        let mut neighbors = self.graph
            .neighbors_directed(node_ix, EdgeDirection::Incoming);
        if cfg!(debug_assertions) {
            let result = neighbors.next();
            if neighbors.next().is_some() {
                panic!("parent_of: node has multiple parents!")
            }
            result
        }
        else {
            neighbors.next()
        }
    }

    /// Gets an iterator to the children of a node.
    ///
    /// Will return an empty iterator if the node has no children or
    /// if the node does not exist.
    pub fn children_of(&self, node_ix: NodeIndex) -> Vec<NodeIndex> {
        let mut edges = self.graph.edges_directed(node_ix, EdgeDirection::Outgoing)
            .collect::<Vec<(NodeIndex, &u32)>>();
        edges.sort_by_key(|&(ref _ix, ref edge)| *edge);
        edges.into_iter().map(|(ix, _edge)| ix).collect()
    }

    /// Gets the container of the given node.
    pub fn get(&self, node_ix: NodeIndex) -> Option<&Container> {
        self.graph.node_weight(node_ix)
    }

    /// Gets a mutable reference to a given node
    pub fn get_mut(&mut self, node_ix: NodeIndex) -> Option<&mut Container> {
        self.graph.node_weight_mut(node_ix)
    }

    /// Gets the ContainerType of the selected node
    pub fn node_type(&self, node_ix: NodeIndex) -> Option<ContainerType> {
        self.graph.node_weight(node_ix).map(Container::get_type)
    }

    /// Attempts to get an ancestor matching the matching type
    pub fn ancestor_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        let mut curr_ix = node_ix;
        while let Some(parent_ix) = self.parent_of(curr_ix) {
            let parent = self.graph.node_weight(parent_ix)
                .expect("ancestor_of_type: parent_of invalid");
            if parent.get_type() == container_type {
                return Some(parent_ix)
            }
            curr_ix = parent_ix;
        }
        return None;
    }

    /// Attempts to get a descendant of the matching type
    /// Looks down the left side of the tree first
    pub fn descendant_of_type(&self, node_ix: NodeIndex,
                           container_type: ContainerType) -> Option<NodeIndex> {
        if let Some(container) = self.get(node_ix) {
            if container.get_type() == container_type {
                return Some(node_ix)
            }
        }
        for child in self.children_of(node_ix) {
            if let Some(desc) = self.descendant_of_type(child, container_type) {
                return Some(desc)
            }
        }
        return None
    }

    /// Attempts to get a descendant of the matching type.
    /// Looks down the right side of the tree first
    pub fn descendant_of_type_right(&self, node_ix: NodeIndex,
                              container_type: ContainerType) -> Option<NodeIndex> {
        if let Some(container) = self.get(node_ix) {
            if container.get_type() == container_type {
                return Some(node_ix)
            }
        }
        for child in self.children_of(node_ix).iter().rev() {
            if let Some(desc) = self.descendant_of_type(*child, container_type) {
                return Some(desc)
            }
        }
        return None
    }

    /// Finds a node by the view handle.
    pub fn descendant_with_handle(&self, node_ix: NodeIndex, search_handle: &WlcView)
                               -> Option<NodeIndex> {
        self.get(node_ix).and_then(|node| match node {
            &Container::View { ref handle, .. } => {
                if handle == search_handle {
                    return Some(node_ix)
                }
                else {
                    return None
                }
            },
            _ => {
                for child in self.children_of(node_ix) {
                    if let Some(found) = self.descendant_with_handle(child,
                                                              search_handle) {
                        return Some(found)
                    }
                }
                return None
            }
        })
    }

    /// Returns the node indices of any node that is a descendant of a node
    pub fn all_descendants_of(&self, node_ix: &NodeIndex) -> Vec<NodeIndex> {
        let mut index: usize = 0;
        let mut nodes: Vec<NodeIndex> = self.graph.edges_directed(*node_ix,
                                                      EdgeDirection::Outgoing)
            .map(|(ix, _)| ix).collect();
        while index != nodes.len() {
            let cur_node: &NodeIndex = &nodes[index].clone();
            let children = self.graph.edges_directed(*cur_node,
                                                     EdgeDirection::Outgoing);
            let size_hint = children.size_hint();
            nodes.reserve(size_hint.1.unwrap_or(size_hint.0));
            for (ix, _) in children {
                nodes.push(ix);
            }
            index += 1;
        }
        nodes
    }

    /// Sets the node and its children's visibility
    pub fn set_family_visible(&mut self, node_ix: NodeIndex, visible: bool) {
        self.get_mut(node_ix).map(|c| c.set_visibility(visible));
        for child in self.children_of(node_ix) {
            self.set_family_visible(child, visible);
        }
    }

    /// Determines if a Node index is the last one in the adjacency list
    /// (and so will be moved in a removal)
    pub fn is_last_ix(&self, node_ix: NodeIndex) -> bool {
        if self.graph.node_count() == 0 {
            false
        } else {
            self.graph.node_count() - 1 == node_ix.index()
        }
    }
}

use std::ops::{Index, IndexMut};

impl Index<NodeIndex> for Tree {
    type Output = Container;
    #[inline]
    fn index(&self, index: NodeIndex) -> &Self::Output {
        self.get(index).expect("graph_tree: node not found")
    }
}

impl IndexMut<NodeIndex> for Tree {
    #[inline]
    fn index_mut(&mut self, index: NodeIndex) -> &mut Self::Output {
        self.get_mut(index).expect("graph_tree: node not found")
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use layout::container::*;
    use rustwlc::*;

    /// Makes a very basic tree.
    /// There is only one output,
    /// Two workspaces,
    /// First workspace has a single view in the root container,
    /// second workspace has a container with two views in it
    /// (the container is a child of the root container).
    ///
    /// The active container is the only view in the first workspace
    #[allow(unused_variables)]
    fn basic_tree() -> Tree {
        let mut tree = Tree::new();
        let fake_view_1 = WlcView::root();
        let fake_output = fake_view_1.clone().as_output();
        let root_ix = tree.root_ix();
        let fake_size = Size { h: 800, w: 600 };
        let fake_geometry = Geometry {
            size: fake_size.clone(),
            origin: Point { x: 0, y: 0 }
        };

        let output_ix = tree.add_child(root_ix, Container::new_output(fake_output));
        let workspace_1_ix = tree.add_child(output_ix,
                                                Container::new_workspace("1".to_string(),
                                                                   fake_size.clone()));
        let root_container_1_ix = tree.add_child(workspace_1_ix,
                                                Container::new_container(fake_geometry.clone()));
        let workspace_2_ix = tree.add_child(output_ix,
                                                Container::new_workspace("2".to_string(),
                                                                     fake_size.clone()));
        let root_container_2_ix = tree.add_child(workspace_2_ix,
                                                Container::new_container(fake_geometry.clone()));
        /* Workspace 1 containers */
        let wkspc_1_view = tree.add_child(root_container_1_ix,
                                                Container::new_view(fake_view_1.clone()));
        /* Workspace 2 containers */
        let wkspc_2_container = tree.add_child(root_container_2_ix,
                                                Container::new_container(fake_geometry.clone()));
        let wkspc_2_sub_view_1 = tree.add_child(wkspc_2_container,
                                                Container::new_view(fake_view_1.clone()));
        let wkspc_2_sub_view_2 = tree.add_child(wkspc_2_container,
                                                Container::new_view(fake_view_1.clone()));
        tree
    }

    #[test]
    fn test_descendents_of() {
        let basic_tree = basic_tree();
        let children_of_root = basic_tree.all_descendants_of(&basic_tree.root);
        assert_eq!(children_of_root.len(), 9);
        let simple_view = basic_tree.descendant_of_type(basic_tree.root,
                                                        ContainerType::View)
            .expect("No view in the basic test tree");
        let children_of_view = basic_tree.all_descendants_of(&simple_view);
        assert_eq!(children_of_view.len(), 0);
    }

}
<|endoftext|>


<commit_before>use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

extern crate toml;

#[macro_use]
extern crate serde_derive;

// error in rust compiler.  Bugfix requested in Sept. 2017
// these are used, but the compiler is not seeing it for
// some reason
#[allow(unused_imports)]
#[macro_use]
extern crate serde_json;
// error in rust compiler.  Bugfix has been submitted in Sept. 2017
#[allow(unused_imports)]
#[macro_use]
extern crate serde;

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Tomlfile {
    contents: Contents,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Metadata {
    deb: Deb,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Deb {
    revision: Option<String>,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Package {
    name: String,
    version: Option<String>,
    metadata: Metadata,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Contents {
    package: Package,
    dependencies: Option<toml::Value>,
}

fn main() {
    let target = env::var("TARGET").unwrap();
    println!("target={}", target);
    match target.find("-linux-") {
        Some(..) => {
            println!("cargo:rustc-link-lib=indy");
            println!("cargo:rustc-link-search=native=/usr/lib");
        }
        None => {}
    }

    match env::var("CARGO_FEATURE_CI") {
        Ok(_) => {
            println!("injecting version information");
            // Leaving as unwrap, this is in the build script.
            let revision = get_revision().unwrap();
            write_variables(&revision);
        },
        Err(_) => {println!("NOT injecting version information"); },
    };
}

// Writes to the file 'src/utils/version_constants.rs' for use
// in outputing the version dynamically.
fn write_variables(revision:&str) {
    let out_dir = "src/utils/";
    let dest_path = Path::new(&out_dir).join("version_constants.rs");
    let mut f = File::create(&dest_path).unwrap();
    let s = format!("pub const VERSION: &'static str = env!(\"CARGO_PKG_VERSION\");\npub const REVISION: &'static str = \"{}\";\n", revision);
    if let Err(e) = f.write_all(s.as_bytes()) {
       panic!("Error creating version_constants.rs: {}", e);
    };

}

// Gets the revision number from the Cargo.toml file.
pub fn get_revision() -> Option<String> {
    let dir = match  env::var("CARGO_MANIFEST_DIR"){
        Ok(d) => d,
        Err(_) => panic!("Couldn't Manifest Directory"),
    };
    let filename = "Cargo.toml";
    let p = format!("{}/{}",dir,filename);
    let mut input = String::new();
    File::open(p).and_then(|mut f| {
        f.read_to_string(&mut input)}).unwrap();
    let tomlfile:Contents = toml::from_str(&input).unwrap();
    let revision:String = match tomlfile.package.metadata.deb.revision {
        Some(v) => v,
        None => String::from(""),
    };
    Some(format!("+{}", revision))
}

<commit_msg>Fixed build for MacOS<commit_after>use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;

extern crate toml;

#[macro_use]
extern crate serde_derive;

// error in rust compiler.  Bugfix requested in Sept. 2017
// these are used, but the compiler is not seeing it for
// some reason
#[allow(unused_imports)]
#[macro_use]
extern crate serde_json;
// error in rust compiler.  Bugfix has been submitted in Sept. 2017
#[allow(unused_imports)]
#[macro_use]
extern crate serde;

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Tomlfile {
    contents: Contents,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Metadata {
    deb: Deb,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Deb {
    revision: Option<String>,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Package {
    name: String,
    version: Option<String>,
    metadata: Metadata,
}

// used in formatting the Cargo.toml file
#[derive(Deserialize, Debug)]
struct Contents {
    package: Package,
    dependencies: Option<toml::Value>,
}

fn main() {
    let target = env::var("TARGET").unwrap();
    println!("target={}", target);
    if target.contains("darwin"){
        //OSX specific logic
        println!("cargo:rustc-link-lib=indy");
        //OSX does not allow 3rd party libs to be installed in /usr/lib. Instead install it in /usr/local/lib
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }
    if target.contains("linux"){
        //Linux specific logic
        println!("cargo:rustc-link-lib=indy");
        println!("cargo:rustc-link-search=native=/usr/lib");
    }

    match env::var("CARGO_FEATURE_CI") {
        Ok(_) => {
            println!("injecting version information");
            // Leaving as unwrap, this is in the build script.
            let revision = get_revision().unwrap();
            write_variables(&revision);
        },
        Err(_) => {println!("NOT injecting version information"); },
    };
}

// Writes to the file 'src/utils/version_constants.rs' for use
// in outputing the version dynamically.
fn write_variables(revision:&str) {
    let out_dir = "src/utils/";
    let dest_path = Path::new(&out_dir).join("version_constants.rs");
    let mut f = File::create(&dest_path).unwrap();
    let s = format!("pub const VERSION: &'static str = env!(\"CARGO_PKG_VERSION\");\npub const REVISION: &'static str = \"{}\";\n", revision);
    if let Err(e) = f.write_all(s.as_bytes()) {
       panic!("Error creating version_constants.rs: {}", e);
    };

}

// Gets the revision number from the Cargo.toml file.
pub fn get_revision() -> Option<String> {
    let dir = match  env::var("CARGO_MANIFEST_DIR"){
        Ok(d) => d,
        Err(_) => panic!("Couldn't Manifest Directory"),
    };
    let filename = "Cargo.toml";
    let p = format!("{}/{}",dir,filename);
    let mut input = String::new();
    File::open(p).and_then(|mut f| {
        f.read_to_string(&mut input)}).unwrap();
    let tomlfile:Contents = toml::from_str(&input).unwrap();
    let revision:String = match tomlfile.package.metadata.deb.revision {
        Some(v) => v,
        None => String::from(""),
    };
    Some(format!("+{}", revision))
}

<|endoftext|>


<commit_before>//! An implementation of a buddy allocator.

use core::ptr;

use Allocator;

use types::{UnsafeList, PhantomNode};

pub type FreeBlock = PhantomNode;

#[allow(dead_code)]
pub struct Buddy<'a> {
    min_block_size: usize,
    max_order: u32,
    free_lists: &'a mut [UnsafeList<FreeBlock>],
}

impl<'a> Allocator for Buddy<'a> {
    unsafe fn allocate(&mut self, mut _size: usize, _align: usize) -> *mut u8 {
        ptr::null_mut()
    }

    unsafe fn deallocate(&mut self, _ptr: *mut u8, _old_size: usize,
                         _align: usize) {

    }
}
<commit_msg>libheap: Add Buddy::next_power_of_two()<commit_after>//! An implementation of a buddy allocator.

use core::ptr;
use core::mem;

use Allocator;

use types::{UnsafeList, PhantomNode};

pub type FreeBlock = PhantomNode;

#[allow(dead_code)]
pub struct Buddy<'a> {
    min_block_size: usize,
    max_order: u32,
    free_lists: &'a mut [UnsafeList<FreeBlock>],
}

impl<'a> Buddy<'a> {
    #[allow(exceeding_bitshifts)]
    pub fn next_power_of_two(mut num: usize) -> usize {
        if num == 0 {
            return 1;
        }

        num -= 1;

        num |= num >> 1;
        num |= num >> 2;
        num |= num >> 4;
        num |= num >> 8;
        num |= num >> 16;

        if mem::size_of::<usize>() == mem::size_of::<u64>() {
            num |= num >> 32;
        }

        num + 1
    }
}

impl<'a> Allocator for Buddy<'a> {
    unsafe fn allocate(&mut self, mut _size: usize, _align: usize) -> *mut u8 {
        ptr::null_mut()
    }

    unsafe fn deallocate(&mut self, _ptr: *mut u8, _old_size: usize,
                         _align: usize) {

    }
}

#[cfg(test)]
mod test {
    use super::Buddy;

    #[test]
    fn test_buddy_next_power_of_two() {
        assert_eq!(Buddy::next_power_of_two(0), 1);
        assert_eq!(Buddy::next_power_of_two(2), 2);
        assert_eq!(Buddy::next_power_of_two(3), 4);
        assert_eq!(Buddy::next_power_of_two(5678), 8192);
        assert_eq!(Buddy::next_power_of_two(8192), 8192);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rust::{ExtCtxt, Ident, Span};
use front::ast::*;
use std::collections::hashmap::HashMap;

mod lint;
mod visitor;

pub mod clean_ast
{
  use rust::Ident;
  use front::ast::*;

  pub struct Grammar{
    pub name: Ident,
    pub rules: Vec<Rule>,
    pub start_rule_idx: uint,
    pub print_generated: bool
  }

  pub struct Rule{
    pub name: Ident,
    pub def: Box<Expression>
  }
}

pub struct SemanticAnalyser<'a>
{
  cx: &'a ExtCtxt<'a>,
  grammar: &'a Grammar
}

impl<'a> SemanticAnalyser<'a>
{
  pub fn analyse(cx: &'a ExtCtxt, grammar: &'a Grammar) -> Option<clean_ast::Grammar>
  {
    let analyser = SemanticAnalyser {
      cx: cx,
      grammar: grammar
    };
    analyser.check()
  }

  fn check(&self) -> Option<clean_ast::Grammar>
  {
    if !self.at_least_one_rule_declared() {
      return None
    }

    let mut start_rule_idx = self.start_rule();

    let mut ident_to_rule_idx = HashMap::new();
    if self.multiple_rule_declaration(&mut ident_to_rule_idx) {
      return None
    }

    if UndeclaredRule::analyse(self.cx, &self.grammar.rules, &ident_to_rule_idx) {
      return None
    }

    let mut unused_rule_analyser = lint::unused_rule::UnusedRule::new(self.cx, self.grammar,
      &ident_to_rule_idx);
    unused_rule_analyser.analyse(start_rule_idx);

    let mut rules = vec![];
    for (idx, rule) in self.grammar.rules.iter().enumerate() {
      if unused_rule_analyser.is_used[idx] {
        rules.push(clean_ast::Rule{
          name: rule.name.node,
          def: rule.def.clone()
        });
        if idx == start_rule_idx {
          start_rule_idx = rules.len() - 1;
        }
      }
    }
    Some(clean_ast::Grammar{
      name: self.grammar.name,
      rules: rules,
      start_rule_idx: start_rule_idx,
      print_generated: get_attribute(&self.grammar.attributes, "print_generated").is_some()
    })
  }

  fn at_least_one_rule_declared(&self) -> bool
  {
    if self.grammar.rules.len() == 0 {
      self.cx.parse_sess.span_diagnostic.handler.err(
        "At least one rule must be declared.");
      false
    } else {
      true
    }
  }

  fn start_rule(&self) -> uint
  {
    let mut start_rule_idx = None;
    for (idx, rule) in self.grammar.rules.iter().enumerate() {
      if self.can_be_start_attr(start_rule_idx, rule) {
          start_rule_idx = Some(idx);
      }
    }
    match start_rule_idx {
      None => {
        self.cx.parse_sess.span_diagnostic.handler.warn(
          "No rule has been specified as the starting point (attribute `#[start]`). \
          The first rule will be automatically considered as such.");
        0
      },
      Some(idx) => idx
    }
  }

  fn can_be_start_attr(&self, start_rule_idx: Option<uint>, rule: &Rule) -> bool
  {
    match (start_rule_idx, get_attribute(&rule.attributes, "start")) {
      (Some(idx), Some(attr)) => {
        self.span_err(attr.span, format!(
          "Multiple `start` attributes are forbidden. \
          Rules `{}` and `{}` conflict.",
          id_to_string(self.grammar.rules[idx].name.node),
          id_to_string(rule.name.node)).as_slice());
        false
      },
      (None, Some(_)) => true,
      _ => false
    }
  }

  fn multiple_rule_declaration(&self, ident_to_rule_idx: &mut HashMap<Ident, uint>) -> bool
  {
    let mut multiple_decl = false;
    for (idx, rule) in self.grammar.rules.iter().enumerate() {
      let first_rule_def = ident_to_rule_idx.find_copy(&rule.name.node);
      match first_rule_def {
        Some(first_rule_idx) => {
          self.span_err(rule.name.span,
            format!("duplicate definition of rule `{}`",
              id_to_string(rule.name.node)).as_slice());
          let first_rule_name = self.grammar.rules[first_rule_idx].name;
          self.span_note(first_rule_name.span,
            format!("first definition of rule `{}` here",
              id_to_string(first_rule_name.node)).as_slice());
          multiple_decl = true;
        }
        None => { ident_to_rule_idx.insert(rule.name.node, idx); }
      }
    }
    multiple_decl
  }

  fn span_err(&self, sp: Span, m: &str)
  {
    self.cx.parse_sess.span_diagnostic.span_err(sp, m);
  }

  fn span_note(&self, sp: Span, m: &str)
  {
    self.cx.parse_sess.span_diagnostic.span_note(sp, m);
  }
}

pub trait ExprVisitor
{
  fn visit_expr(&mut self, expr: &Box<Expression>)
  {
    let sp = expr.span;
    match &expr.node {
      &StrLiteral(ref lit) => {
        self.visit_str_literal(sp, lit)
      }
      &AnySingleChar => {
        self.visit_any_single_char(sp)
      }
      &NonTerminalSymbol(id) => {
        self.visit_non_terminal_symbol(sp, id)
      }
      &Sequence(ref seq) => {
        self.visit_sequence(sp, seq)
      }
      &Choice(ref choices) => {
        self.visit_choice(sp, choices)
      }
      &ZeroOrMore(ref expr) => {
        self.visit_zero_or_more(sp, expr)
      }
      &OneOrMore(ref expr) => {
        self.visit_one_or_more(sp, expr)
      }
      &Optional(ref expr) => {
        self.visit_optional(sp, expr)
      }
      &NotPredicate(ref expr) => {
        self.visit_not_predicate(sp, expr)
      }
      &AndPredicate(ref expr) => {
        self.visit_and_predicate(sp, expr)
      }
      &CharacterClass(ref charClass) => {
        self.visit_character_class(sp, charClass)
      }
    }
  }

  fn visit_str_literal(&mut self, _sp: Span, _lit: &String) {}
  fn visit_any_single_char(&mut self, _sp: Span) {}
  fn visit_non_terminal_symbol(&mut self, _sp: Span, _id: Ident) {}

  fn visit_sequence(&mut self, _sp: Span, expr: &Vec<Box<Expression>>)
  {
    self.visit_expr_slice(expr.as_slice())
  }

  fn visit_choice(&mut self, _sp: Span, expr: &Vec<Box<Expression>>)
  {
    self.visit_expr_slice(expr.as_slice())
  }

  fn visit_zero_or_more(&mut self, _sp: Span, expr: &Box<Expression>)
  {
    self.visit_expr(expr)
  }

  fn visit_one_or_more(&mut self, _sp: Span, expr: &Box<Expression>)
  {
    self.visit_expr(expr)
  }

  fn visit_optional(&mut self, _sp: Span, expr: &Box<Expression>)
  {
    self.visit_expr(expr)
  }

  fn visit_not_predicate(&mut self, _sp: Span, expr: &Box<Expression>)
  {
    self.visit_expr(expr)
  }

  fn visit_and_predicate(&mut self, _sp: Span, expr: &Box<Expression>)
  {
    self.visit_expr(expr)
  }

  fn visit_character_class(&mut self, _sp: Span, _expr: &CharacterClassExpr) {}

  fn visit_expr_slice<'a>(&mut self, seq: &'a [Box<Expression>])
  {
    assert!(seq.len() > 0);
    for expr in seq.iter() {
      self.visit_expr(expr);
    }
  }
}

struct UndeclaredRule<'a>
{
  cx: &'a ExtCtxt<'a>,
  ident_to_rule_idx: &'a HashMap<Ident, uint>,
  has_undeclared: bool
}

impl<'a> UndeclaredRule<'a>
{
  fn analyse(cx: &'a ExtCtxt<'a>, rules: &Vec<Rule>,
    ident_to_rule_idx: &'a HashMap<Ident, uint>) -> bool
  {
    let mut analyser = UndeclaredRule {
      cx: cx,
      ident_to_rule_idx: ident_to_rule_idx,
      has_undeclared: false
    };
    for rule in rules.iter() {
      analyser.visit_expr(&rule.def);
    }
    analyser.has_undeclared
  }
}

impl<'a> ExprVisitor for UndeclaredRule<'a>
{
  fn visit_non_terminal_symbol(&mut self, sp: Span, id: Ident)
  {
    if self.ident_to_rule_idx.find(&id).is_none() {
      self.cx.parse_sess.span_diagnostic.span_err(sp,
        format!("You try to call the rule `{}` which is not declared.",
          id_to_string(id)).as_slice());
      self.has_undeclared = true;
    }
  }
}
<commit_msg>[Refactor] Remove the expression-only visitor and use the new in undeclared rules checker.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use rust::{ExtCtxt, Ident, Span};
use front::ast::*;
use middle::visitor::Visitor;
use std::collections::hashmap::HashMap;

mod lint;
mod visitor;

pub mod clean_ast
{
  use rust::Ident;
  use front::ast::*;

  pub struct Grammar{
    pub name: Ident,
    pub rules: Vec<Rule>,
    pub start_rule_idx: uint,
    pub print_generated: bool
  }

  pub struct Rule{
    pub name: Ident,
    pub def: Box<Expression>
  }
}

pub struct SemanticAnalyser<'a>
{
  cx: &'a ExtCtxt<'a>,
  grammar: &'a Grammar
}

impl<'a> SemanticAnalyser<'a>
{
  pub fn analyse(cx: &'a ExtCtxt, grammar: &'a Grammar) -> Option<clean_ast::Grammar>
  {
    let analyser = SemanticAnalyser {
      cx: cx,
      grammar: grammar
    };
    analyser.check()
  }

  fn check(&self) -> Option<clean_ast::Grammar>
  {
    if !self.at_least_one_rule_declared() {
      return None
    }

    let mut start_rule_idx = self.start_rule();

    let mut ident_to_rule_idx = HashMap::new();
    if self.multiple_rule_declaration(&mut ident_to_rule_idx) {
      return None
    }

    if UndeclaredRule::analyse(self.cx, self.grammar, &ident_to_rule_idx) {
      return None
    }

    let mut unused_rule_analyser = lint::unused_rule::UnusedRule::new(self.cx, self.grammar,
      &ident_to_rule_idx);
    unused_rule_analyser.analyse(start_rule_idx);

    let mut rules = vec![];
    for (idx, rule) in self.grammar.rules.iter().enumerate() {
      if unused_rule_analyser.is_used[idx] {
        rules.push(clean_ast::Rule{
          name: rule.name.node,
          def: rule.def.clone()
        });
        if idx == start_rule_idx {
          start_rule_idx = rules.len() - 1;
        }
      }
    }
    Some(clean_ast::Grammar{
      name: self.grammar.name,
      rules: rules,
      start_rule_idx: start_rule_idx,
      print_generated: get_attribute(&self.grammar.attributes, "print_generated").is_some()
    })
  }

  fn at_least_one_rule_declared(&self) -> bool
  {
    if self.grammar.rules.len() == 0 {
      self.cx.parse_sess.span_diagnostic.handler.err(
        "At least one rule must be declared.");
      false
    } else {
      true
    }
  }

  fn start_rule(&self) -> uint
  {
    let mut start_rule_idx = None;
    for (idx, rule) in self.grammar.rules.iter().enumerate() {
      if self.can_be_start_attr(start_rule_idx, rule) {
          start_rule_idx = Some(idx);
      }
    }
    match start_rule_idx {
      None => {
        self.cx.parse_sess.span_diagnostic.handler.warn(
          "No rule has been specified as the starting point (attribute `#[start]`). \
          The first rule will be automatically considered as such.");
        0
      },
      Some(idx) => idx
    }
  }

  fn can_be_start_attr(&self, start_rule_idx: Option<uint>, rule: &Rule) -> bool
  {
    match (start_rule_idx, get_attribute(&rule.attributes, "start")) {
      (Some(idx), Some(attr)) => {
        self.span_err(attr.span, format!(
          "Multiple `start` attributes are forbidden. \
          Rules `{}` and `{}` conflict.",
          id_to_string(self.grammar.rules[idx].name.node),
          id_to_string(rule.name.node)).as_slice());
        false
      },
      (None, Some(_)) => true,
      _ => false
    }
  }

  fn multiple_rule_declaration(&self, ident_to_rule_idx: &mut HashMap<Ident, uint>) -> bool
  {
    let mut multiple_decl = false;
    for (idx, rule) in self.grammar.rules.iter().enumerate() {
      let first_rule_def = ident_to_rule_idx.find_copy(&rule.name.node);
      match first_rule_def {
        Some(first_rule_idx) => {
          self.span_err(rule.name.span,
            format!("duplicate definition of rule `{}`",
              id_to_string(rule.name.node)).as_slice());
          let first_rule_name = self.grammar.rules[first_rule_idx].name;
          self.span_note(first_rule_name.span,
            format!("first definition of rule `{}` here",
              id_to_string(first_rule_name.node)).as_slice());
          multiple_decl = true;
        }
        None => { ident_to_rule_idx.insert(rule.name.node, idx); }
      }
    }
    multiple_decl
  }

  fn span_err(&self, sp: Span, m: &str)
  {
    self.cx.parse_sess.span_diagnostic.span_err(sp, m);
  }

  fn span_note(&self, sp: Span, m: &str)
  {
    self.cx.parse_sess.span_diagnostic.span_note(sp, m);
  }
}

struct UndeclaredRule<'a>
{
  cx: &'a ExtCtxt<'a>,
  ident_to_rule_idx: &'a HashMap<Ident, uint>,
  has_undeclared: bool
}

impl<'a> UndeclaredRule<'a>
{
  fn analyse(cx: &'a ExtCtxt<'a>, grammar: &Grammar,
    ident_to_rule_idx: &'a HashMap<Ident, uint>) -> bool
  {
    let mut analyser = UndeclaredRule {
      cx: cx,
      ident_to_rule_idx: ident_to_rule_idx,
      has_undeclared: false
    };
    analyser.visit_grammar(grammar);
    analyser.has_undeclared
  }
}

impl<'a> Visitor for UndeclaredRule<'a>
{
  fn visit_non_terminal_symbol(&mut self, sp: Span, id: Ident)
  {
    if self.ident_to_rule_idx.find(&id).is_none() {
      self.cx.parse_sess.span_diagnostic.span_err(sp,
        format!("You try to call the rule `{}` which is not declared.",
          id_to_string(id)).as_slice());
      self.has_undeclared = true;
    }
  }
}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_id = "rustc_back#0.11.0-pre"]
#![crate_name = "rustc_back"]
#![experimental]
#![comment = "The Rust compiler backend"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://doc.rust-lang.org/")]

#![feature(globs)]
#![feature(phase)]
#![allow(unused_attribute)] // NOTE: remove after stage0

#[phase(plugin, link)]
extern crate log;
extern crate syntax;
extern crate libc;
extern crate flate;

pub mod abi;
pub mod archive;
pub mod arm;
pub mod mips;
pub mod mipsel;
pub mod rpath;
pub mod svh;
pub mod target_strs;
pub mod x86;
pub mod x86_64;
<commit_msg>rustc_back: Update crate docs<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Some stuff used by rustc that doesn't have many dependencies
//!
//! Originally extracted from rustc::back, which was nominally the
//! compiler 'backend', though LLVM is rustc's backend, so rustc_back
//! is really just odds-and-ends relating to code gen and linking.
//! This crate mostly exists to make rustc smaller, so we might put
//! more 'stuff' here in the future.  It does not have a dependency on
//! rustc_llvm.
//!
//! FIXME: Split this into two crates: one that has deps on syntax, and
//! one that doesn't; the one that doesn't might get decent parallel
//! build speedups.

#![crate_id = "rustc_back#0.11.0-pre"]
#![crate_name = "rustc_back"]
#![experimental]
#![comment = "The Rust compiler minimal-dependency dumping-ground"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
      html_root_url = "http://doc.rust-lang.org/")]

#![feature(globs)]
#![feature(phase)]
#![allow(unused_attribute)] // NOTE: remove after stage0

#[phase(plugin, link)]
extern crate log;
extern crate syntax;
extern crate libc;
extern crate flate;

pub mod abi;
pub mod archive;
pub mod arm;
pub mod mips;
pub mod mipsel;
pub mod rpath;
pub mod svh;
pub mod target_strs;
pub mod x86;
pub mod x86_64;
<|endoftext|>


<commit_before>extern crate crossbeam;
extern crate walkdir;

pub mod single_threaded;

use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::fs;
use self::crossbeam::sync::chase_lev;
use self::walkdir::WalkDir;
use regex::{RegexSet, Regex};
use std::path::PathBuf;
use colored::*;
use std::process::exit;
use utils::size;
use std::thread;
use error::*;
use types::FileSize;
use std::path::Path;

pub use walk_parallel::single_threaded::*;

/// Enum for messaging between workers/stealers
pub enum Status<T> {
    Done,
    Data(T),
}

/// The 'Walk' struct contains all the information we need to traverse a directory.
#[derive(Debug)]
pub struct Walk {
    pub path: PathBuf,
    gitignore: Option<RegexSet>,
    hgignore: Option<RegexSet>,
    darcs_boring: Option<RegexSet>,
    excludes: Option<Regex>,
    max_depth: Option<u8>,
    threshold: Option<u64>,
    start_depth: usize,
    nproc: usize,
    show_files: bool,
    get_blocks: bool,
    follow_symlinks: bool,
    artifacts_only: bool,
}

impl Walk {
    /// function to make output from a 'Walk', using one thread. It also takes an 'Arc<AtomicU64>'
    /// and will add the relevant directory sizes to it.
    pub fn print_dir(w: Walk, total: Arc<AtomicU64>) -> () {

        let excludes = match w.excludes {
            Some(ref x) => Some(x),
            _ => None,
        };

        let v = if excludes.is_some() || w.artifacts_only {
            read_all(
                &w.path,
                (w.start_depth as u8),
                w.max_depth,
                excludes,
                &w.gitignore,
                w.artifacts_only,
            )
        } else {
            read_all_fast(&w.path, (w.start_depth as u8), w.max_depth)
        };

        let subdir_size = v.file_size.get();

        total.fetch_add(subdir_size, Ordering::Relaxed);

        let mut to_print = if let Some(m) = w.threshold {
            subdir_size > m
        } else {
            true
        };

        if let Some(0) = w.max_depth {
            to_print = false;
        }

        if to_print {
            // filter by depth
            let mut v_filtered = v.filtered(w.threshold, !w.show_files, w.max_depth);

            v_filtered.display_tree(w.path);
        }
    }

    /// set the maximum depth to display
    pub fn set_depth(&mut self, d: u8) -> () {
        self.max_depth = Some(d);
    }

    /// set the regex for excludes
    pub fn set_regex(&mut self, r: Regex) -> () {
        self.excludes = Some(r);
    }

    /// set the minumum file size
    pub fn set_threshold(&mut self, n: u64) -> () {
        self.threshold = Some(n);
    }

    /// include files when printing
    pub fn with_files(&mut self) -> () {
        self.show_files = true;
    }

    /// include files when printing
    pub fn blocks(&mut self) -> () {
        self.get_blocks = true;
    }

    /// include files when printing
    pub fn artifacts_only(&mut self) -> () {
        self.artifacts_only = true;
    }

    fn get_proc(&self) -> usize {
        self.nproc
    }

    /// Create a new 'Walk' from a 'PathBuf' and the number
    /// of processor cores to be used.
    pub fn new(p: PathBuf, n: usize) -> Walk {
        Walk {
            path: p,
            gitignore: None,
            hgignore: None,
            darcs_boring: None,
            excludes: None,
            max_depth: None,
            threshold: None,
            start_depth: 0,
            nproc: n,
            show_files: false,
            get_blocks: false,
            follow_symlinks: false,
            artifacts_only: false,
        }
    }

    fn bump_depth(&mut self) -> () {
        self.start_depth += 1;
    }

    /// This takes a 'Walk' and a 'Worker<Status<Walk>>' and executes the walk *in parallel*,
    /// creating new work for each subdirectory. It's not the most efficient concurrency
    /// imaginable, but it's fast and easy-ish to use. It *also* takes in an 'Arc<AtomicU64>',
    /// which it updates with any file sizes in the directory.
    pub fn push_subdir(
        w: &Walk,
        worker: &mut chase_lev::Worker<Status<Walk>>,
        total: Arc<AtomicU64>,
    ) {

        let in_paths = &w.path;

        // fill up queue + print out files
        if let Ok(paths) = fs::read_dir(in_paths) {

            // iterate over all the entries in the directory
            for p in paths {
                let val = match p {
                    Ok(x) => x,
                    _ => {
                        eprintln!("{}: path error at {:?}.", "Error".red(), p);
                        exit(0x0001)
                    }
                };

                let exclude_check = if let Some(ref x) = w.excludes {
                    if let Some(r) = val.path().into_os_string().to_str() {
                        !x.is_match(r)
                    } else {
                        eprintln!(
                            "{}: ignoring invalid unicode at: {:?}",
                            "Warning".yellow(),
                            val.path().display()
                        );
                        true
                    }
                } else {
                    true
                };

                if exclude_check {
                    match val.file_type() {
                        Ok(t) => {
                            if t.is_dir() {
                                let mut new_path = w.path.to_owned();
                                new_path.push(val.file_name());
                                let mut new_walk = Walk::new(new_path, w.get_proc());
                                if w.excludes.is_some() {
                                    new_walk.set_regex(w.excludes.clone().unwrap());
                                }
                                if w.show_files {
                                    new_walk.with_files();
                                }
                                new_walk.bump_depth();
                                if let Some(d) = w.max_depth {
                                    new_walk.set_depth(d);
                                }
                                if let Some(b) = w.threshold {
                                    new_walk.set_threshold(b);
                                }
                                worker.push(Status::Data(new_walk)); // pass a vector of Arc's to do 2-level traversals?
                            } else if t.is_file() {
                                if let Ok(l) = val.metadata() {
                                    let size = size(&l, w.get_blocks); // l.len();
                                    total.fetch_add(size, Ordering::Relaxed);
                                    if w.show_files && size != 0 {
                                        let to_formatted = format!("{}", FileSize::new(size));
                                        println!(
                                            "{}\t {}",
                                            &to_formatted.green(),
                                            val.path().display()
                                        );
                                    }
                                } else {
                                    eprintln!(
                                        "{}: could not find filesize for file at {}.",
                                        "Warning".yellow(),
                                        val.path().display()
                                    );
                                }
                            }
                        }
                        _ => {
                            eprintln!(
                                "{}: could not determine file type for: {}",
                                "Warning".yellow(),
                                val.path().display()
                            )
                        }
                    }
                }
            }

            // send "done" messages to all the workers
            let iter = 0..(w.get_proc());
            iter.map(|_| worker.push(Status::Done)).count();

        }
        // if we can't read the directory contents, figure out why
        // 1: check the path exists
        else if !in_paths.exists() {
            eprintln!(
                "{}: path '{}' does not exist, or you do not have permission to enter.",
                "Error".red(),
                &in_paths.display()
            );
        }
        // 2: check the path is actually a directory
        else if !in_paths.is_dir() {
            if w.artifacts_only {
                eprintln!(
                    "{}: {} is not a directory; not searching for artifacts",
                    "Warning".yellow(),
                    &in_paths.display()
                );
            }

            if let Ok(l) = in_paths.metadata() {
                let size = size(&l, w.get_blocks); // l.len();
                let to_formatted = format!("{}", FileSize::new(size));
                println!("{}\t {}", &to_formatted.green(), in_paths.display());
            } else {
                panic!("{}", Internal::IoError);
            }
        }
        // 3: otherwise, give a warning about permissions
        else {
            eprintln!(
                "{}: permission denied for directory: {}",
                "Warning".yellow(),
                &in_paths.display()
            );
        }

    }
}

fn latex_log<P: AsRef<Path>>(p: P) -> bool {

    lazy_static! {
        static ref LOG: Regex =
            Regex::new(r"\.log$")
            .unwrap();
    }

    if LOG.is_match(&p.as_ref().to_string_lossy().to_string()) {
        let mut parent = (&p.as_ref())
            .parent()
            .unwrap()
            .to_string_lossy()
            .to_string();
        parent.push_str("/*.tex");
        glob_exists(&parent)
    } else {
        false
    }

}

// TODO figure out why the unwrap_or is failing?
// FIXME take optional reference to a regex
pub fn clean_project_dirs<P: AsRef<Path>>(p: P, exclude: Option<Regex>) -> () {

    lazy_static! {
        static ref REGEX: Regex =
            Regex::new(r"\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|min\.js|hi|hc|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|go\.(v|teak|xmldef)|p_hi|p_o|prof|hide-cache|tix|synctex\.gz)$")
            .unwrap();
    }

    for dir in WalkDir::new(p)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|p| {
            exclude.clone().map(|e| {
                e.is_match(&p.path().to_string_lossy().to_string())
            }) != Some(false)
        })
        .filter(|p| {
            REGEX.is_match(&p.path().to_string_lossy().to_string()) ||
                is_project_dir(
                    &p.path().to_string_lossy().to_string(),
                    &p.path()
                        .file_name()
                        .map(|x| x.to_string_lossy().to_string())
                        .unwrap_or("".to_string()),
                ) || latex_log(&p.path())
        })
    {
        if dir.file_type().is_file() {
            fs::remove_file(dir.path()).unwrap_or(());
        } else if dir.file_type().is_dir() {
            fs::remove_dir_all(dir.path()).unwrap_or(());
        }
    }
}

/// Given a 'Walk' struct, traverse it concurrently and print out any relevant outputs.
/// Currently, this only works for a depth of two, which is probably bad.
pub fn print_parallel(w: Walk) -> () {

    // initialize the total at 0 and create a reference to it
    let val = AtomicU64::new(0);
    let arc = Arc::new(val);
    let arc_producer = arc.clone();
    let arc_child = arc.clone();
    let path_display = w.path.clone();

    // set up worker & stealer
    let (mut worker, stealer): (chase_lev::Worker<Status<Walk>>,
                                chase_lev::Stealer<Status<Walk>>) = chase_lev::deque();

    // set up our iterator for the workers
    let iter = 0..(&w.get_proc() - 1);

    // create the producer in another thread
    let child_producer = thread::spawn(move || {

        let arc_local = arc_producer.clone();

        // assign work to everyone
        Walk::push_subdir(&w, &mut worker, arc_local.clone());

        // start popping off values in the worker's thread
        loop {
            if let Some(p) = worker.try_pop() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        }

    });

    // create a vector of thread handles so that it doesn't execute
    // everything sequentially.
    let mut threads = Vec::new();

    // set up as many workers as we have threads
    for _ in iter {

        // create a new stealer
        let stealer_clone = stealer.clone();

        let arc_local = arc_child.clone();

        // run the stealer in a new thread
        let child_consumer = thread::spawn(move || loop {

            if let chase_lev::Steal::Data(p) = stealer_clone.steal() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        });

        threads.push(child_consumer);

    }

    // join the child producer to the main thread
    let _ = child_producer.join();

    // join the workers to the main thread
    let _ = threads
        .into_iter()
        .map(|v| {
            let result = v.join();
            if let Ok(exit) = result {
                exit
            } else if let Err(e) = result {
                panic!("{:?}", e)
            }
        })
        .count();

    // get the total size
    let m = arc.load(Ordering::SeqCst); // TODO - check if this works with Relaxed?
    let size = FileSize::new(m);

    // print directory total.
    if size != FileSize::new(0) {
        let to_formatted = format!("{}", size);
        println!("{}\t {}", &to_formatted.green(), path_display.display());
    }

}
<commit_msg>fix overzealous cleaning<commit_after>extern crate crossbeam;
extern crate walkdir;

pub mod single_threaded;

use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::fs;
use self::crossbeam::sync::chase_lev;
use self::walkdir::WalkDir;
use regex::{RegexSet, Regex};
use std::path::PathBuf;
use colored::*;
use std::process::exit;
use utils::size;
use std::thread;
use error::*;
use types::FileSize;
use std::path::Path;

pub use walk_parallel::single_threaded::*;

/// Enum for messaging between workers/stealers
pub enum Status<T> {
    Done,
    Data(T),
}

/// The 'Walk' struct contains all the information we need to traverse a directory.
#[derive(Debug)]
pub struct Walk {
    pub path: PathBuf,
    gitignore: Option<RegexSet>,
    hgignore: Option<RegexSet>,
    darcs_boring: Option<RegexSet>,
    excludes: Option<Regex>,
    max_depth: Option<u8>,
    threshold: Option<u64>,
    start_depth: usize,
    nproc: usize,
    show_files: bool,
    get_blocks: bool,
    follow_symlinks: bool,
    artifacts_only: bool,
}

impl Walk {
    /// function to make output from a 'Walk', using one thread. It also takes an 'Arc<AtomicU64>'
    /// and will add the relevant directory sizes to it.
    pub fn print_dir(w: Walk, total: Arc<AtomicU64>) -> () {

        let excludes = match w.excludes {
            Some(ref x) => Some(x),
            _ => None,
        };

        let v = if excludes.is_some() || w.artifacts_only {
            read_all(
                &w.path,
                (w.start_depth as u8),
                w.max_depth,
                excludes,
                &w.gitignore,
                w.artifacts_only,
            )
        } else {
            read_all_fast(&w.path, (w.start_depth as u8), w.max_depth)
        };

        let subdir_size = v.file_size.get();

        total.fetch_add(subdir_size, Ordering::Relaxed);

        let mut to_print = if let Some(m) = w.threshold {
            subdir_size > m
        } else {
            true
        };

        if let Some(0) = w.max_depth {
            to_print = false;
        }

        if to_print {
            // filter by depth
            let mut v_filtered = v.filtered(w.threshold, !w.show_files, w.max_depth);

            v_filtered.display_tree(w.path);
        }
    }

    /// set the maximum depth to display
    pub fn set_depth(&mut self, d: u8) -> () {
        self.max_depth = Some(d);
    }

    /// set the regex for excludes
    pub fn set_regex(&mut self, r: Regex) -> () {
        self.excludes = Some(r);
    }

    /// set the minumum file size
    pub fn set_threshold(&mut self, n: u64) -> () {
        self.threshold = Some(n);
    }

    /// include files when printing
    pub fn with_files(&mut self) -> () {
        self.show_files = true;
    }

    /// include files when printing
    pub fn blocks(&mut self) -> () {
        self.get_blocks = true;
    }

    /// include files when printing
    pub fn artifacts_only(&mut self) -> () {
        self.artifacts_only = true;
    }

    fn get_proc(&self) -> usize {
        self.nproc
    }

    /// Create a new 'Walk' from a 'PathBuf' and the number
    /// of processor cores to be used.
    pub fn new(p: PathBuf, n: usize) -> Walk {
        Walk {
            path: p,
            gitignore: None,
            hgignore: None,
            darcs_boring: None,
            excludes: None,
            max_depth: None,
            threshold: None,
            start_depth: 0,
            nproc: n,
            show_files: false,
            get_blocks: false,
            follow_symlinks: false,
            artifacts_only: false,
        }
    }

    fn bump_depth(&mut self) -> () {
        self.start_depth += 1;
    }

    /// This takes a 'Walk' and a 'Worker<Status<Walk>>' and executes the walk *in parallel*,
    /// creating new work for each subdirectory. It's not the most efficient concurrency
    /// imaginable, but it's fast and easy-ish to use. It *also* takes in an 'Arc<AtomicU64>',
    /// which it updates with any file sizes in the directory.
    pub fn push_subdir(
        w: &Walk,
        worker: &mut chase_lev::Worker<Status<Walk>>,
        total: Arc<AtomicU64>,
    ) {

        let in_paths = &w.path;

        // fill up queue + print out files
        if let Ok(paths) = fs::read_dir(in_paths) {

            // iterate over all the entries in the directory
            for p in paths {
                let val = match p {
                    Ok(x) => x,
                    _ => {
                        eprintln!("{}: path error at {:?}.", "Error".red(), p);
                        exit(0x0001)
                    }
                };

                let exclude_check = if let Some(ref x) = w.excludes {
                    if let Some(r) = val.path().into_os_string().to_str() {
                        !x.is_match(r)
                    } else {
                        eprintln!(
                            "{}: ignoring invalid unicode at: {:?}",
                            "Warning".yellow(),
                            val.path().display()
                        );
                        true
                    }
                } else {
                    true
                };

                if exclude_check {
                    match val.file_type() {
                        Ok(t) => {
                            if t.is_dir() {
                                let mut new_path = w.path.to_owned();
                                new_path.push(val.file_name());
                                let mut new_walk = Walk::new(new_path, w.get_proc());
                                if w.excludes.is_some() {
                                    new_walk.set_regex(w.excludes.clone().unwrap());
                                }
                                if w.show_files {
                                    new_walk.with_files();
                                }
                                new_walk.bump_depth();
                                if let Some(d) = w.max_depth {
                                    new_walk.set_depth(d);
                                }
                                if let Some(b) = w.threshold {
                                    new_walk.set_threshold(b);
                                }
                                worker.push(Status::Data(new_walk)); // pass a vector of Arc's to do 2-level traversals?
                            } else if t.is_file() {
                                if let Ok(l) = val.metadata() {
                                    let size = size(&l, w.get_blocks); // l.len();
                                    total.fetch_add(size, Ordering::Relaxed);
                                    if w.show_files && size != 0 {
                                        let to_formatted = format!("{}", FileSize::new(size));
                                        println!(
                                            "{}\t {}",
                                            &to_formatted.green(),
                                            val.path().display()
                                        );
                                    }
                                } else {
                                    eprintln!(
                                        "{}: could not find filesize for file at {}.",
                                        "Warning".yellow(),
                                        val.path().display()
                                    );
                                }
                            }
                        }
                        _ => {
                            eprintln!(
                                "{}: could not determine file type for: {}",
                                "Warning".yellow(),
                                val.path().display()
                            )
                        }
                    }
                }
            }

            // send "done" messages to all the workers
            let iter = 0..(w.get_proc());
            iter.map(|_| worker.push(Status::Done)).count();

        }
        // if we can't read the directory contents, figure out why
        // 1: check the path exists
        else if !in_paths.exists() {
            eprintln!(
                "{}: path '{}' does not exist, or you do not have permission to enter.",
                "Error".red(),
                &in_paths.display()
            );
        }
        // 2: check the path is actually a directory
        else if !in_paths.is_dir() {
            if w.artifacts_only {
                eprintln!(
                    "{}: {} is not a directory; not searching for artifacts",
                    "Warning".yellow(),
                    &in_paths.display()
                );
            }

            if let Ok(l) = in_paths.metadata() {
                let size = size(&l, w.get_blocks); // l.len();
                let to_formatted = format!("{}", FileSize::new(size));
                println!("{}\t {}", &to_formatted.green(), in_paths.display());
            } else {
                panic!("{}", Internal::IoError);
            }
        }
        // 3: otherwise, give a warning about permissions
        else {
            eprintln!(
                "{}: permission denied for directory: {}",
                "Warning".yellow(),
                &in_paths.display()
            );
        }

    }
}

fn latex_log<P: AsRef<Path>>(p: P) -> bool {

    lazy_static! {
        static ref LOG: Regex =
            Regex::new(r"\.log$")
            .unwrap();
    }

    if LOG.is_match(&p.as_ref().to_string_lossy().to_string()) {
        let mut parent = (&p.as_ref())
            .parent()
            .unwrap()
            .to_string_lossy()
            .to_string();
        parent.push_str("/*.tex");
        glob_exists(&parent)
    } else {
        false
    }

}

// TODO figure out why the unwrap_or is failing?
// FIXME take optional reference to a regex
pub fn clean_project_dirs<P: AsRef<Path>>(p: P, exclude: Option<Regex>) -> () {

    lazy_static! {
        static ref REGEX: Regex =
            Regex::new(r"\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|hi|hc|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|go\.(v|teak|xmldef)|p_hi|p_o|prof|hide-cache|tix|synctex\.gz)$")
            .unwrap();
    }

    for dir in WalkDir::new(p)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|p| {
            exclude.clone().map(|e| {
                e.is_match(&p.path().to_string_lossy().to_string())
            }) != Some(false)
        })
        .filter(|p| {
            REGEX.is_match(&p.path().to_string_lossy().to_string()) ||
                is_project_dir(
                    &p.path().to_string_lossy().to_string(),
                    &p.path()
                        .file_name()
                        .map(|x| x.to_string_lossy().to_string())
                        .unwrap_or("".to_string()),
                ) || latex_log(&p.path())
        })
    {
        if dir.file_type().is_file() {
            fs::remove_file(dir.path()).unwrap_or(());
        } else if dir.file_type().is_dir() {
            fs::remove_dir_all(dir.path()).unwrap_or(());
        }
    }
}

/// Given a 'Walk' struct, traverse it concurrently and print out any relevant outputs.
/// Currently, this only works for a depth of two, which is probably bad.
pub fn print_parallel(w: Walk) -> () {

    // initialize the total at 0 and create a reference to it
    let val = AtomicU64::new(0);
    let arc = Arc::new(val);
    let arc_producer = arc.clone();
    let arc_child = arc.clone();
    let path_display = w.path.clone();

    // set up worker & stealer
    let (mut worker, stealer): (chase_lev::Worker<Status<Walk>>,
                                chase_lev::Stealer<Status<Walk>>) = chase_lev::deque();

    // set up our iterator for the workers
    let iter = 0..(&w.get_proc() - 1);

    // create the producer in another thread
    let child_producer = thread::spawn(move || {

        let arc_local = arc_producer.clone();

        // assign work to everyone
        Walk::push_subdir(&w, &mut worker, arc_local.clone());

        // start popping off values in the worker's thread
        loop {
            if let Some(p) = worker.try_pop() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        }

    });

    // create a vector of thread handles so that it doesn't execute
    // everything sequentially.
    let mut threads = Vec::new();

    // set up as many workers as we have threads
    for _ in iter {

        // create a new stealer
        let stealer_clone = stealer.clone();

        let arc_local = arc_child.clone();

        // run the stealer in a new thread
        let child_consumer = thread::spawn(move || loop {

            if let chase_lev::Steal::Data(p) = stealer_clone.steal() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        });

        threads.push(child_consumer);

    }

    // join the child producer to the main thread
    let _ = child_producer.join();

    // join the workers to the main thread
    let _ = threads
        .into_iter()
        .map(|v| {
            let result = v.join();
            if let Ok(exit) = result {
                exit
            } else if let Err(e) = result {
                panic!("{:?}", e)
            }
        })
        .count();

    // get the total size
    let m = arc.load(Ordering::SeqCst); // TODO - check if this works with Relaxed?
    let size = FileSize::new(m);

    // print directory total.
    if size != FileSize::new(0) {
        let to_formatted = format!("{}", size);
        println!("{}\t {}", &to_formatted.green(), path_display.display());
    }

}
<|endoftext|>


<commit_before>use std::io::Cursor;
use std::io::prelude::*;
use std::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

#[derive(Debug)]
pub enum GQTPError {
    InvalidProtocol,
    InvalidBodySize,
    StatusError(u16),
}

pub struct GQTPRequest<'a> {
    addr: &'a str,
}

impl<'a> Default for GQTPRequest<'a> {
    fn default() -> GQTPRequest<'a> {
        GQTPRequest { addr: "127.0.0.1:10043" }
    }
}

impl<'a> GQTPRequest<'a> {
    /// Create a GQTP client.
    pub fn new() -> GQTPRequest<'a> {
        GQTPRequest::default()
    }

    /// Set host address for GQTP server.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    ///
    /// groonga::GQTPRequest::new().with_addr("127.0.0.1:20043");
    /// ```
    pub fn with_addr(mut self, addr: &'a str) -> GQTPRequest<'a> {
        self.addr = addr;
        self
    }

    /// Send request and Receive response.
    pub fn call<C>(&self, command: C) -> Result<String, GQTPError>
        where C: AsRef<str>
    {
        // send
        let mut stream = TcpStream::connect(self.addr).unwrap();
        let mut send_buf = vec![];
        send_buf.write_u8(0xc7).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_i16::<BigEndian>(0).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_u8(0x02).unwrap();   // flags
        send_buf.write_u16::<BigEndian>(0).unwrap();
        send_buf.write_u32::<BigEndian>(command.as_ref().len() as u32).unwrap();
        send_buf.write_u32::<BigEndian>(0).unwrap();
        send_buf.write_u64::<BigEndian>(0).unwrap();
        send_buf.extend_from_slice(command.as_ref().as_bytes());
        let _ = stream.write_all(send_buf.as_slice());

        // receive and check protocol header value
        let mut read_buf = vec![0; 8192];
        let _ = stream.read(&mut read_buf);
        let mut buf = Cursor::new(read_buf);

        let protocol = buf.read_u8().unwrap();
        let query_type = buf.read_u8().unwrap();
        if protocol != 0xc7 || query_type > 5 {
            return Err(GQTPError::InvalidProtocol);
        }
        let _ = buf.read_i16::<BigEndian>().unwrap();
        let _ = buf.read_u8().unwrap();

        let flags = buf.read_u8().unwrap();
        if !((flags & 0x01) == 0x01 || (flags & 0x02) == 0x02) {
            return Err(GQTPError::InvalidProtocol);
        }

        let status = buf.read_u16::<BigEndian>().unwrap();
        if status != 0 && status != 1 {
            return Err(GQTPError::StatusError(status));
        }
        let size = buf.read_i32::<BigEndian>().unwrap();
        let _ = buf.read_i32::<BigEndian>().unwrap();    // opaque
        let _ = buf.read_i64::<BigEndian>().unwrap();    // cas

        // read body
        let mut msg = vec![0; size as usize];
        let _ = buf.read(&mut msg).unwrap();

        Ok(String::from_utf8(msg).unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn smoke_gqtp() {
        let req = GQTPRequest::new();
        assert_eq!("127.0.0.1:10043", req.addr)
    }

    #[test]
    fn smoke_gqtp_with_addr() {
        let req = GQTPRequest::new().with_addr("127.0.0.1:20043");
        assert_eq!("127.0.0.1:20043", req.addr)
    }
}
<commit_msg>read large data set<commit_after>use std::io::Cursor;
use std::io::prelude::*;
use std::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

const RECV_BUF_SIZE: usize = 8192;
const GQTP_HEADER_SIZE: usize = 24;

#[derive(Debug)]
pub enum GQTPError {
    InvalidProtocol,
    InvalidBodySize,
    StatusError(u16),
}

pub struct GQTPRequest<'a> {
    addr: &'a str,
}

impl<'a> Default for GQTPRequest<'a> {
    fn default() -> GQTPRequest<'a> {
        GQTPRequest { addr: "127.0.0.1:10043" }
    }
}

impl<'a> GQTPRequest<'a> {
    /// Create a GQTP client.
    pub fn new() -> GQTPRequest<'a> {
        GQTPRequest::default()
    }

    /// Set host address for GQTP server.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate ruroonga_client as groonga;
    ///
    /// groonga::GQTPRequest::new().with_addr("127.0.0.1:20043");
    /// ```
    pub fn with_addr(mut self, addr: &'a str) -> GQTPRequest<'a> {
        self.addr = addr;
        self
    }

    /// Send request and Receive response.
    pub fn call<C>(&self, command: C) -> Result<String, GQTPError>
        where C: AsRef<str>
    {
        // send
        let mut stream = TcpStream::connect(self.addr).unwrap();
        let mut send_buf = vec![];
        send_buf.write_u8(0xc7).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_i16::<BigEndian>(0).unwrap();
        send_buf.write_u8(0).unwrap();
        send_buf.write_u8(0x02).unwrap();   // flags
        send_buf.write_u16::<BigEndian>(0).unwrap();
        send_buf.write_u32::<BigEndian>(command.as_ref().len() as u32).unwrap();
        send_buf.write_u32::<BigEndian>(0).unwrap();
        send_buf.write_u64::<BigEndian>(0).unwrap();
        send_buf.extend_from_slice(command.as_ref().as_bytes());
        let _ = stream.write_all(send_buf.as_slice());

        // receive and check protocol header value
        let mut read_buf = vec![0; RECV_BUF_SIZE];
        let _ = stream.read(&mut read_buf);
        let mut buf = Cursor::new(read_buf);

        let protocol = buf.read_u8().unwrap();
        let query_type = buf.read_u8().unwrap();
        if protocol != 0xc7 || query_type > 5 {
            return Err(GQTPError::InvalidProtocol);
        }
        let _ = buf.read_i16::<BigEndian>().unwrap();
        let _ = buf.read_u8().unwrap();

        let flags = buf.read_u8().unwrap();
        if !((flags & 0x01) == 0x01 || (flags & 0x02) == 0x02) {
            return Err(GQTPError::InvalidProtocol);
        }

        let status = buf.read_u16::<BigEndian>().unwrap();
        if status != 0 && status != 1 {
            return Err(GQTPError::StatusError(status));
        }
        let size = buf.read_i32::<BigEndian>().unwrap();
        let _ = buf.read_i32::<BigEndian>().unwrap();    // opaque
        let _ = buf.read_i64::<BigEndian>().unwrap();    // cas

        // read body
        let mut msg_buf_len = if (size as usize + GQTP_HEADER_SIZE) > RECV_BUF_SIZE {
            RECV_BUF_SIZE - GQTP_HEADER_SIZE
        } else {
            size as usize
        };
        let mut msg = vec![0; msg_buf_len];
        let _ = buf.read(&mut msg).unwrap();
        if (size as usize + GQTP_HEADER_SIZE) > RECV_BUF_SIZE {
            loop {
                let mut read_buf = vec![0; RECV_BUF_SIZE];
                let rsize = stream.read(&mut read_buf).unwrap();
                msg.extend_from_slice(read_buf.as_ref());
                msg_buf_len += rsize;
                println!("msglen={}", msg_buf_len);
                if msg_buf_len >= size as usize {
                    break;
                }
            }
        }

        Ok(String::from_utf8(msg).unwrap())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn smoke_gqtp() {
        let req = GQTPRequest::new();
        assert_eq!("127.0.0.1:10043", req.addr)
    }

    #[test]
    fn smoke_gqtp_with_addr() {
        let req = GQTPRequest::new().with_addr("127.0.0.1:20043");
        assert_eq!("127.0.0.1:20043", req.addr)
    }
}
<|endoftext|>


<commit_before>//! Functions to read and write control registers.

pub use super::model_specific::{Efer, EferFlags};

use PhysAddr;
use structures::paging::PhysFrame;

/// Various control flags modifying the basic operation of the CPU.
pub struct Cr0;

impl Cr0 {
    /// Read the current set of CR0 flags.
    pub fn read() -> Cr0Flags {
        let value: u64;
        unsafe {
            asm!("mov %cr0, $0" : "=r" (value));
        }
        Cr0Flags::from_bits_truncate(value)
    }

    /// Write CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn write(flags: Cr0Flags) {
        let mut value = Self::read();
        value |= flags;
        let value = value.bits();

        asm!("mov $0, %cr0" :: "r" (value) : "memory")
    }
}

bitflags! {
    pub struct Cr0Flags: u64 {
        const PROTECTED_MODE_ENABLE = 1 << 0;
        const MONITOR_COPROCESSOR = 1 << 1;
        const EMULATION = 1 << 2;
        const TASK_SWITCHED = 1 << 3;
        const EXTENSION_TYPE = 1 << 4;
        const NUMERIC_ERROR = 1 << 5;
        const WRITE_PROTECT = 1 << 16;
        const ALIGNMENT_MASK = 1 << 18;
        const NON_WRITE_THROUGH = 1 << 29;
        const CACHE_DISABLE = 1 << 30;
        const PAGING = 1 << 31;
    }
}

/// Contains the physical address of the level 4 page table.
pub struct Cr3;

impl Cr3 {
    /// Read the current P4 table address from the CR3 register.
    pub fn read() -> (PhysFrame, Cr3Flags) {
        let value: u64;
        unsafe {
            asm!("mov %cr3, $0" : "=r" (value));
        }
        let flags = Cr3Flags::from_bits_truncate(value);
        let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
        let frame = PhysFrame::containing_address(addr);
        (frame, flags)
    }

    /// Write a new P4 table address into the CR3 register.
    ///
    /// ## Safety
    /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
    /// changing the page mapping.
    pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
        let addr = frame.start_address();
        let value = addr.as_u64() | flags.bits();
        asm!("mov $0, %cr3" :: "r" (value) : "memory")
    }
}

bitflags! {
    /// Controls cache settings for the level 4 page table.
    pub struct Cr3Flags: u64 {
        /// Use a writethrough cache policy for the P4 table (else a writeback policy is used).
        const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
        /// Disable caching for the P4 table.
        const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
    }
}
<commit_msg>Fix Cr0::write and add Cr0::update<commit_after>//! Functions to read and write control registers.

pub use super::model_specific::{Efer, EferFlags};

use PhysAddr;
use structures::paging::PhysFrame;

/// Various control flags modifying the basic operation of the CPU.
pub struct Cr0;

impl Cr0 {
    /// Read the current set of CR0 flags.
    pub fn read() -> Cr0Flags {
        Cr0Flags::from_bits_truncate(Self::read_raw())
    }

    /// Read the current raw CR0 value.
    pub fn read_raw() -> u64 {
        let value: u64;
        unsafe {
            asm!("mov %cr0, $0" : "=r" (value));
        }
        value
    }

    /// Write CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn write(flags: Cr0Flags) {
        let mut value = Self::read_raw();
        value |= flags.bits();

        asm!("mov $0, %cr0" :: "r" (value) : "memory")
    }

    /// Updates CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn update<F>(f: F) where F: FnOnce(&mut Cr0Flags) {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    pub struct Cr0Flags: u64 {
        const PROTECTED_MODE_ENABLE = 1 << 0;
        const MONITOR_COPROCESSOR = 1 << 1;
        const EMULATION = 1 << 2;
        const TASK_SWITCHED = 1 << 3;
        const EXTENSION_TYPE = 1 << 4;
        const NUMERIC_ERROR = 1 << 5;
        const WRITE_PROTECT = 1 << 16;
        const ALIGNMENT_MASK = 1 << 18;
        const NON_WRITE_THROUGH = 1 << 29;
        const CACHE_DISABLE = 1 << 30;
        const PAGING = 1 << 31;
    }
}

/// Contains the physical address of the level 4 page table.
pub struct Cr3;

impl Cr3 {
    /// Read the current P4 table address from the CR3 register.
    pub fn read() -> (PhysFrame, Cr3Flags) {
        let value: u64;
        unsafe {
            asm!("mov %cr3, $0" : "=r" (value));
        }
        let flags = Cr3Flags::from_bits_truncate(value);
        let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
        let frame = PhysFrame::containing_address(addr);
        (frame, flags)
    }

    /// Write a new P4 table address into the CR3 register.
    ///
    /// ## Safety
    /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
    /// changing the page mapping.
    pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
        let addr = frame.start_address();
        let value = addr.as_u64() | flags.bits();
        asm!("mov $0, %cr3" :: "r" (value) : "memory")
    }
}

bitflags! {
    /// Controls cache settings for the level 4 page table.
    pub struct Cr3Flags: u64 {
        /// Use a writethrough cache policy for the P4 table (else a writeback policy is used).
        const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
        /// Disable caching for the P4 table.
        const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
    }
}
<|endoftext|>