<commit_before>// Copyright 2012-2014 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.

/*!

A graph module for use in dataflow, region resolution, and elsewhere.

# Interface details

You customize the graph by specifying a "node data" type `N` and an
"edge data" type `E`. You can then later gain access (mutable or
immutable) to these "user-data" bits. Currently, you can only add
nodes or edges to the graph. You cannot remove or modify them once
added. This could be changed if we have a need.

# Implementation details

The main tricky thing about this code is the way that edges are
stored. The edges are stored in a central array, but they are also
threaded onto two linked lists for each node, one for incoming edges
and one for outgoing edges. Note that every edge is a member of some
incoming list and some outgoing list.  Basically you can load the
first index of the linked list from the node data structures (the
field `first_edge`) and then, for each edge, load the next index from
the field `next_edge`). Each of those fields is an array that should
be indexed by the direction (see the type `Direction`).

*/

#![allow(dead_code)] // still WIP

use std::uint;

pub struct Graph<N,E> {
    nodes: Vec<Node<N>> ,
    edges: Vec<Edge<E>> ,
}

pub struct Node<N> {
    first_edge: [EdgeIndex, ..2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex, ..2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

#[deriving(Eq)]
pub struct NodeIndex(pub uint);
pub static InvalidNodeIndex: NodeIndex = NodeIndex(uint::MAX);

#[deriving(Eq)]
pub struct EdgeIndex(pub uint);
pub static InvalidEdgeIndex: EdgeIndex = EdgeIndex(uint::MAX);

// Use a private field here to guarantee no more instances are created:
pub struct Direction { repr: uint }
pub static Outgoing: Direction = Direction { repr: 0 };
pub static Incoming: Direction = Direction { repr: 1 };

impl NodeIndex {
    fn get(&self) -> uint { let NodeIndex(v) = *self; v }
}

impl EdgeIndex {
    fn get(&self) -> uint { let EdgeIndex(v) = *self; v }
}

impl<N,E> Graph<N,E> {
    pub fn new() -> Graph<N,E> {
        Graph {
            nodes: Vec::new(),
            edges: Vec::new(),
        }
    }

    pub fn with_capacity(num_nodes: uint,
                         num_edges: uint) -> Graph<N,E> {
        Graph {
            nodes: Vec::with_capacity(num_nodes),
            edges: Vec::with_capacity(num_edges),
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Simple accessors

    #[inline]
    pub fn all_nodes<'a>(&'a self) -> &'a [Node<N>] {
        let nodes: &'a [Node<N>] = self.nodes.as_slice();
        nodes
    }

    #[inline]
    pub fn all_edges<'a>(&'a self) -> &'a [Edge<E>] {
        let edges: &'a [Edge<E>] = self.edges.as_slice();
        edges
    }

    ///////////////////////////////////////////////////////////////////////////
    // Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [InvalidEdgeIndex, InvalidEdgeIndex],
            data: data
        });
        idx
    }

    pub fn mut_node_data<'a>(&'a mut self, idx: NodeIndex) -> &'a mut N {
        &mut self.nodes.get_mut(idx.get()).data
    }

    pub fn node_data<'a>(&'a self, idx: NodeIndex) -> &'a N {
        &self.nodes.get(idx.get()).data
    }

    pub fn node<'a>(&'a self, idx: NodeIndex) -> &'a Node<N> {
        self.nodes.get(idx.get())
    }

    ///////////////////////////////////////////////////////////////////////////
    // Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self,
                    source: NodeIndex,
                    target: NodeIndex,
                    data: E) -> EdgeIndex {
        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes.get(source.get())
                                     .first_edge[Outgoing.repr];
        let target_first = self.nodes.get(target.get())
                                     .first_edge[Incoming.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data
        });

        // adjust the firsts for each node target be the next object.
        self.nodes.get_mut(source.get()).first_edge[Outgoing.repr] = idx;
        self.nodes.get_mut(target.get()).first_edge[Incoming.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data<'a>(&'a mut self, idx: EdgeIndex) -> &'a mut E {
        &mut self.edges.get_mut(idx.get()).data
    }

    pub fn edge_data<'a>(&'a self, idx: EdgeIndex) -> &'a E {
        &self.edges.get(idx.get()).data
    }

    pub fn edge<'a>(&'a self, idx: EdgeIndex) -> &'a Edge<E> {
        self.edges.get(idx.get())
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes.get(node.get()).first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges.get(edge.get()).next_edge[dir.repr]
    }

    ///////////////////////////////////////////////////////////////////////////
    // Iterating over nodes, edges

    pub fn each_node(&self, f: |NodeIndex, &Node<N>| -> bool) -> bool {
        //! Iterates over all edges defined in the graph.
        self.nodes.iter().enumerate().advance(|(i, node)| f(NodeIndex(i), node))
    }

    pub fn each_edge(&self, f: |EdgeIndex, &Edge<E>| -> bool) -> bool {
        //! Iterates over all edges defined in the graph
        self.edges.iter().enumerate().advance(|(i, edge)| f(EdgeIndex(i), edge))
    }

    pub fn each_outgoing_edge(&self,
                              source: NodeIndex,
                              f: |EdgeIndex, &Edge<E>| -> bool)
                              -> bool {
        //! Iterates over all outgoing edges from the node `from`

        self.each_adjacent_edge(source, Outgoing, f)
    }

    pub fn each_incoming_edge(&self,
                              target: NodeIndex,
                              f: |EdgeIndex, &Edge<E>| -> bool)
                              -> bool {
        //! Iterates over all incoming edges to the node `target`

        self.each_adjacent_edge(target, Incoming, f)
    }

    pub fn each_adjacent_edge(&self,
                              node: NodeIndex,
                              dir: Direction,
                              f: |EdgeIndex, &Edge<E>| -> bool)
                              -> bool {
        //! Iterates over all edges adjacent to the node `node`
        //! in the direction `dir` (either `Outgoing` or `Incoming)

        let mut edge_idx = self.first_adjacent(node, dir);
        while edge_idx != InvalidEdgeIndex {
            let edge = self.edges.get(edge_idx.get());
            if !f(edge_idx, edge) {
                return false;
            }
            edge_idx = edge.next_edge[dir.repr];
        }
        return true;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constaint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point(&self,
                                     op: |iter_index: uint,
                                          edge_index: EdgeIndex,
                                          edge: &Edge<E>|
                                          -> bool) {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (i, edge) in self.edges.iter().enumerate() {
                changed |= op(iteration, EdgeIndex(i), edge);
            }
        }
    }
}

pub fn each_edge_index(max_edge_index: EdgeIndex, f: |EdgeIndex| -> bool) {
    let mut i = 0;
    let n = max_edge_index.get();
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

    pub fn target(&self) -> NodeIndex {
        self.target
    }
}

#[cfg(test)]
mod test {
    use middle::graph::*;

    type TestNode = Node<&'static str>;
    type TestEdge = Edge<&'static str>;
    type TestGraph = Graph<&'static str, &'static str>;

    fn create_graph() -> TestGraph {
        let mut graph = Graph::new();

        // Create a simple graph
        //
        //    A -+> B --> C
        //       |  |     ^
        //       |  v     |
        //       F  D --> E

        let a = graph.add_node("A");
        let b = graph.add_node("B");
        let c = graph.add_node("C");
        let d = graph.add_node("D");
        let e = graph.add_node("E");
        let f = graph.add_node("F");

        graph.add_edge(a, b, "AB");
        graph.add_edge(b, c, "BC");
        graph.add_edge(b, d, "BD");
        graph.add_edge(d, e, "DE");
        graph.add_edge(e, c, "EC");
        graph.add_edge(f, b, "FB");

        return graph;
    }

    #[test]
    fn each_node() {
        let graph = create_graph();
        let expected = ["A", "B", "C", "D", "E", "F"];
        graph.each_node(|idx, node| {
            assert_eq!(&expected[idx.get()], graph.node_data(idx));
            assert_eq!(expected[idx.get()], node.data);
            true
        });
    }

    #[test]
    fn each_edge() {
        let graph = create_graph();
        let expected = ["AB", "BC", "BD", "DE", "EC", "FB"];
        graph.each_edge(|idx, edge| {
            assert_eq!(&expected[idx.get()], graph.edge_data(idx));
            assert_eq!(expected[idx.get()], edge.data);
            true
        });
    }

    fn test_adjacent_edges<N:Eq,E:Eq>(graph: &Graph<N,E>,
                                      start_index: NodeIndex,
                                      start_data: N,
                                      expected_incoming: &[(E,N)],
                                      expected_outgoing: &[(E,N)]) {
        assert!(graph.node_data(start_index) == &start_data);

        let mut counter = 0;
        graph.each_incoming_edge(start_index, |edge_index, edge| {
            assert!(graph.edge_data(edge_index) == &edge.data);
            assert!(counter < expected_incoming.len());
            debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
                   counter, expected_incoming[counter], edge_index, edge);
            match expected_incoming[counter] {
                (ref e, ref n) => {
                    assert!(e == &edge.data);
                    assert!(n == graph.node_data(edge.source));
                    assert!(start_index == edge.target);
                }
            }
            counter += 1;
            true
        });
        assert_eq!(counter, expected_incoming.len());

        let mut counter = 0;
        graph.each_outgoing_edge(start_index, |edge_index, edge| {
            assert!(graph.edge_data(edge_index) == &edge.data);
            assert!(counter < expected_outgoing.len());
            debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
                   counter, expected_outgoing[counter], edge_index, edge);
            match expected_outgoing[counter] {
                (ref e, ref n) => {
                    assert!(e == &edge.data);
                    assert!(start_index == edge.source);
                    assert!(n == graph.node_data(edge.target));
                }
            }
            counter += 1;
            true
        });
        assert_eq!(counter, expected_outgoing.len());
    }

    #[test]
    fn each_adjacent_from_a() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(0), "A",
                            [],
                            [("AB", "B")]);
    }

    #[test]
    fn each_adjacent_from_b() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(1), "B",
                            [("FB", "F"), ("AB", "A"),],
                            [("BD", "D"), ("BC", "C"),]);
    }

    #[test]
    fn each_adjacent_from_c() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(2), "C",
                            [("EC", "E"), ("BC", "B")],
                            []);
    }

    #[test]
    fn each_adjacent_from_d() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(3), "D",
                            [("BD", "B")],
                            [("DE", "E")]);
    }
}
<commit_msg>rustc::middle::graph API revisions.<commit_after>// Copyright 2012-2014 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.

/*!

A graph module for use in dataflow, region resolution, and elsewhere.

# Interface details

You customize the graph by specifying a "node data" type `N` and an
"edge data" type `E`. You can then later gain access (mutable or
immutable) to these "user-data" bits. Currently, you can only add
nodes or edges to the graph. You cannot remove or modify them once
added. This could be changed if we have a need.

# Implementation details

The main tricky thing about this code is the way that edges are
stored. The edges are stored in a central array, but they are also
threaded onto two linked lists for each node, one for incoming edges
and one for outgoing edges. Note that every edge is a member of some
incoming list and some outgoing list.  Basically you can load the
first index of the linked list from the node data structures (the
field `first_edge`) and then, for each edge, load the next index from
the field `next_edge`). Each of those fields is an array that should
be indexed by the direction (see the type `Direction`).

*/

#![allow(dead_code)] // still WIP

use std::uint;

pub struct Graph<N,E> {
    nodes: Vec<Node<N>> ,
    edges: Vec<Edge<E>> ,
}

pub struct Node<N> {
    first_edge: [EdgeIndex, ..2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex, ..2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

#[deriving(Eq)]
pub struct NodeIndex(pub uint);
pub static InvalidNodeIndex: NodeIndex = NodeIndex(uint::MAX);

#[deriving(Eq)]
pub struct EdgeIndex(pub uint);
pub static InvalidEdgeIndex: EdgeIndex = EdgeIndex(uint::MAX);

// Use a private field here to guarantee no more instances are created:
pub struct Direction { repr: uint }
pub static Outgoing: Direction = Direction { repr: 0 };
pub static Incoming: Direction = Direction { repr: 1 };

impl NodeIndex {
    fn get(&self) -> uint { let NodeIndex(v) = *self; v }
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> uint { self.get() }
}

impl EdgeIndex {
    fn get(&self) -> uint { let EdgeIndex(v) = *self; v }
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> uint { self.get() }
}

impl<N,E> Graph<N,E> {
    pub fn new() -> Graph<N,E> {
        Graph {
            nodes: Vec::new(),
            edges: Vec::new(),
        }
    }

    pub fn with_capacity(num_nodes: uint,
                         num_edges: uint) -> Graph<N,E> {
        Graph {
            nodes: Vec::with_capacity(num_nodes),
            edges: Vec::with_capacity(num_edges),
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // Simple accessors

    #[inline]
    pub fn all_nodes<'a>(&'a self) -> &'a [Node<N>] {
        let nodes: &'a [Node<N>] = self.nodes.as_slice();
        nodes
    }

    #[inline]
    pub fn all_edges<'a>(&'a self) -> &'a [Edge<E>] {
        let edges: &'a [Edge<E>] = self.edges.as_slice();
        edges
    }

    ///////////////////////////////////////////////////////////////////////////
    // Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [InvalidEdgeIndex, InvalidEdgeIndex],
            data: data
        });
        idx
    }

    pub fn mut_node_data<'a>(&'a mut self, idx: NodeIndex) -> &'a mut N {
        &mut self.nodes.get_mut(idx.get()).data
    }

    pub fn node_data<'a>(&'a self, idx: NodeIndex) -> &'a N {
        &self.nodes.get(idx.get()).data
    }

    pub fn node<'a>(&'a self, idx: NodeIndex) -> &'a Node<N> {
        self.nodes.get(idx.get())
    }

    ///////////////////////////////////////////////////////////////////////////
    // Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self,
                    source: NodeIndex,
                    target: NodeIndex,
                    data: E) -> EdgeIndex {
        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes.get(source.get())
                                     .first_edge[Outgoing.repr];
        let target_first = self.nodes.get(target.get())
                                     .first_edge[Incoming.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data
        });

        // adjust the firsts for each node target be the next object.
        self.nodes.get_mut(source.get()).first_edge[Outgoing.repr] = idx;
        self.nodes.get_mut(target.get()).first_edge[Incoming.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data<'a>(&'a mut self, idx: EdgeIndex) -> &'a mut E {
        &mut self.edges.get_mut(idx.get()).data
    }

    pub fn edge_data<'a>(&'a self, idx: EdgeIndex) -> &'a E {
        &self.edges.get(idx.get()).data
    }

    pub fn edge<'a>(&'a self, idx: EdgeIndex) -> &'a Edge<E> {
        self.edges.get(idx.get())
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes.get(node.get()).first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges.get(edge.get()).next_edge[dir.repr]
    }

    ///////////////////////////////////////////////////////////////////////////
    // Iterating over nodes, edges

    pub fn each_node<'a>(&'a self, f: |NodeIndex, &'a Node<N>| -> bool) -> bool {
        //! Iterates over all edges defined in the graph.
        self.nodes.iter().enumerate().advance(|(i, node)| f(NodeIndex(i), node))
    }

    pub fn each_edge<'a>(&'a self, f: |EdgeIndex, &'a Edge<E>| -> bool) -> bool {
        //! Iterates over all edges defined in the graph
        self.edges.iter().enumerate().advance(|(i, edge)| f(EdgeIndex(i), edge))
    }

    pub fn each_outgoing_edge<'a>(&'a self,
                                  source: NodeIndex,
                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
                                  -> bool {
        //! Iterates over all outgoing edges from the node `from`

        self.each_adjacent_edge(source, Outgoing, f)
    }

    pub fn each_incoming_edge<'a>(&'a self,
                                  target: NodeIndex,
                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
                                  -> bool {
        //! Iterates over all incoming edges to the node `target`

        self.each_adjacent_edge(target, Incoming, f)
    }

    pub fn each_adjacent_edge<'a>(&'a self,
                                  node: NodeIndex,
                                  dir: Direction,
                                  f: |EdgeIndex, &'a Edge<E>| -> bool)
                                  -> bool {
        //! Iterates over all edges adjacent to the node `node`
        //! in the direction `dir` (either `Outgoing` or `Incoming)

        let mut edge_idx = self.first_adjacent(node, dir);
        while edge_idx != InvalidEdgeIndex {
            let edge = self.edges.get(edge_idx.get());
            if !f(edge_idx, edge) {
                return false;
            }
            edge_idx = edge.next_edge[dir.repr];
        }
        return true;
    }

    ///////////////////////////////////////////////////////////////////////////
    // Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constaint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point<'a>(&'a self,
                                         op: |iter_index: uint,
                                              edge_index: EdgeIndex,
                                              edge: &'a Edge<E>|
                                              -> bool) {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (i, edge) in self.edges.iter().enumerate() {
                changed |= op(iteration, EdgeIndex(i), edge);
            }
        }
    }
}

pub fn each_edge_index(max_edge_index: EdgeIndex, f: |EdgeIndex| -> bool) {
    let mut i = 0;
    let n = max_edge_index.get();
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

    pub fn target(&self) -> NodeIndex {
        self.target
    }
}

#[cfg(test)]
mod test {
    use middle::graph::*;

    type TestNode = Node<&'static str>;
    type TestEdge = Edge<&'static str>;
    type TestGraph = Graph<&'static str, &'static str>;

    fn create_graph() -> TestGraph {
        let mut graph = Graph::new();

        // Create a simple graph
        //
        //    A -+> B --> C
        //       |  |     ^
        //       |  v     |
        //       F  D --> E

        let a = graph.add_node("A");
        let b = graph.add_node("B");
        let c = graph.add_node("C");
        let d = graph.add_node("D");
        let e = graph.add_node("E");
        let f = graph.add_node("F");

        graph.add_edge(a, b, "AB");
        graph.add_edge(b, c, "BC");
        graph.add_edge(b, d, "BD");
        graph.add_edge(d, e, "DE");
        graph.add_edge(e, c, "EC");
        graph.add_edge(f, b, "FB");

        return graph;
    }

    #[test]
    fn each_node() {
        let graph = create_graph();
        let expected = ["A", "B", "C", "D", "E", "F"];
        graph.each_node(|idx, node| {
            assert_eq!(&expected[idx.get()], graph.node_data(idx));
            assert_eq!(expected[idx.get()], node.data);
            true
        });
    }

    #[test]
    fn each_edge() {
        let graph = create_graph();
        let expected = ["AB", "BC", "BD", "DE", "EC", "FB"];
        graph.each_edge(|idx, edge| {
            assert_eq!(&expected[idx.get()], graph.edge_data(idx));
            assert_eq!(expected[idx.get()], edge.data);
            true
        });
    }

    fn test_adjacent_edges<N:Eq,E:Eq>(graph: &Graph<N,E>,
                                      start_index: NodeIndex,
                                      start_data: N,
                                      expected_incoming: &[(E,N)],
                                      expected_outgoing: &[(E,N)]) {
        assert!(graph.node_data(start_index) == &start_data);

        let mut counter = 0;
        graph.each_incoming_edge(start_index, |edge_index, edge| {
            assert!(graph.edge_data(edge_index) == &edge.data);
            assert!(counter < expected_incoming.len());
            debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
                   counter, expected_incoming[counter], edge_index, edge);
            match expected_incoming[counter] {
                (ref e, ref n) => {
                    assert!(e == &edge.data);
                    assert!(n == graph.node_data(edge.source));
                    assert!(start_index == edge.target);
                }
            }
            counter += 1;
            true
        });
        assert_eq!(counter, expected_incoming.len());

        let mut counter = 0;
        graph.each_outgoing_edge(start_index, |edge_index, edge| {
            assert!(graph.edge_data(edge_index) == &edge.data);
            assert!(counter < expected_outgoing.len());
            debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}",
                   counter, expected_outgoing[counter], edge_index, edge);
            match expected_outgoing[counter] {
                (ref e, ref n) => {
                    assert!(e == &edge.data);
                    assert!(start_index == edge.source);
                    assert!(n == graph.node_data(edge.target));
                }
            }
            counter += 1;
            true
        });
        assert_eq!(counter, expected_outgoing.len());
    }

    #[test]
    fn each_adjacent_from_a() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(0), "A",
                            [],
                            [("AB", "B")]);
    }

    #[test]
    fn each_adjacent_from_b() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(1), "B",
                            [("FB", "F"), ("AB", "A"),],
                            [("BD", "D"), ("BC", "C"),]);
    }

    #[test]
    fn each_adjacent_from_c() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(2), "C",
                            [("EC", "E"), ("BC", "B")],
                            []);
    }

    #[test]
    fn each_adjacent_from_d() {
        let graph = create_graph();
        test_adjacent_edges(&graph, NodeIndex(3), "D",
                            [("BD", "B")],
                            [("DE", "E")]);
    }
}
<|endoftext|>


<commit_before>use crate::ffi::{CStr, OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::wasi::ffi::OsStrExt;
use crate::vec;

pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}

pub unsafe fn cleanup() {}

pub struct Args {
    iter: vec::IntoIter<OsString>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

/// Returns the command line arguments
pub fn args() -> Args {
    Args {
        iter: maybe_args().unwrap_or(Vec::new()).into_iter(),
        _dont_send_or_sync_me: PhantomData,
    }
}

fn maybe_args() -> Option<Vec<OsString>> {
    unsafe {
        let (argc, buf_size) = wasi::args_sizes_get().ok()?;
        let mut argv = Vec::with_capacity(argc);
        let mut buf = Vec::with_capacity(buf_size);
        wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
        let mut ret = Vec::with_capacity(argc);
        for ptr in argv {
            let s = CStr::from_ptr(ptr.cast());
            ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
        }
        Some(ret)
    }
}

impl Args {
    pub fn inner_debug(&self) -> &[OsString] {
        self.iter.as_slice()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        self.iter.next()
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> {
        self.iter.next_back()
    }
}
<commit_msg>Fix fetching arguments on the wasm32-wasi target<commit_after>use crate::ffi::{CStr, OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::wasi::ffi::OsStrExt;
use crate::vec;

pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}

pub unsafe fn cleanup() {}

pub struct Args {
    iter: vec::IntoIter<OsString>,
    _dont_send_or_sync_me: PhantomData<*mut ()>,
}

/// Returns the command line arguments
pub fn args() -> Args {
    Args {
        iter: maybe_args().unwrap_or(Vec::new()).into_iter(),
        _dont_send_or_sync_me: PhantomData,
    }
}

fn maybe_args() -> Option<Vec<OsString>> {
    unsafe {
        let (argc, buf_size) = wasi::args_sizes_get().ok()?;
        let mut argv = Vec::with_capacity(argc);
        let mut buf = Vec::with_capacity(buf_size);
        wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
        argv.set_len(argc);
        let mut ret = Vec::with_capacity(argc);
        for ptr in argv {
            let s = CStr::from_ptr(ptr.cast());
            ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
        }
        Some(ret)
    }
}

impl Args {
    pub fn inner_debug(&self) -> &[OsString] {
        self.iter.as_slice()
    }
}

impl Iterator for Args {
    type Item = OsString;
    fn next(&mut self) -> Option<OsString> {
        self.iter.next()
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl ExactSizeIterator for Args {
    fn len(&self) -> usize {
        self.iter.len()
    }
}

impl DoubleEndedIterator for Args {
    fn next_back(&mut self) -> Option<OsString> {
        self.iter.next_back()
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{
    Complex32,
    Complex64,
};
use linear_equations::ll;
use matrix::Matrix;
use pointer::CPtr;
use scalar::Scalar;
use types::{
    CLPK_integer,
};

pub trait Gesv {
    fn gesv(a: &mut Matrix<Self>, b: &mut Matrix<Self>, p: &mut Matrix<CLPK_integer>);
}

macro_rules! gesv_impl(
    ($t: ty, $ll: ident) => (
        impl Gesv for $t {
            fn gesv(a: &mut Matrix<$t>, b: &mut Matrix<$t>, p: &mut Matrix<CLPK_integer>) {
                unsafe {
                    let mut info: CLPK_integer = 0;

                    ll::$ll(a.cols().as_const(), b.cols().as_const(),
                        a.as_mut_ptr().as_c_ptr(), a.rows().as_const(),
                        p.as_mut_ptr().as_c_ptr(),
                        b.as_mut_ptr().as_c_ptr(), b.rows().as_const(),
                        &mut info as *mut CLPK_integer);
                }
            }
        }
    );
)

gesv_impl!(f32,         sgesv_)
gesv_impl!(f64,         dgesv_)
gesv_impl!(Complex32,   cgesv_)
gesv_impl!(Complex64,   zgesv_)
<commit_msg>Test Gesv<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

extern crate num;

use self::num::complex::{
    Complex32,
    Complex64,
};
use linear_equations::ll;
use matrix::Matrix;
use pointer::CPtr;
use scalar::Scalar;
use types::{
    CLPK_integer,
};

pub trait Gesv {
    fn gesv(a: &mut Matrix<Self>, b: &mut Matrix<Self>, p: &mut Matrix<CLPK_integer>);
}

macro_rules! gesv_impl(
    ($t: ty, $ll: ident) => (
        impl Gesv for $t {
            fn gesv(a: &mut Matrix<$t>, b: &mut Matrix<$t>, p: &mut Matrix<CLPK_integer>) {
                unsafe {
                    let mut info: CLPK_integer = 0;

                    ll::$ll(a.cols().as_const(), b.cols().as_const(),
                        a.as_mut_ptr().as_c_ptr(), a.rows().as_const(),
                        p.as_mut_ptr().as_c_ptr(),
                        b.as_mut_ptr().as_c_ptr(), b.rows().as_const(),
                        &mut info as *mut CLPK_integer);
                }
            }
        }
    );
)

gesv_impl!(f32,         sgesv_)
gesv_impl!(f64,         dgesv_)
gesv_impl!(Complex32,   cgesv_)
gesv_impl!(Complex64,   zgesv_)

#[cfg(test)]
mod gesv_tests {

    use linear_equations::ops::Gesv;

    #[test]
    fn real() {
        let mut a = (2i32, 2i32, vec![1.0f64, 4.0, 1.0, 2.0]);
        let mut b = (2i32, 1i32, vec![-2.0f64, 2.0]);
        let mut p = (2i32, 2i32, vec![0i32, 0]);

        Gesv::gesv(&mut a, &mut b, &mut p);

        let (_, _, x) = b;
        assert_eq!(x, vec![3.0f64, -5.0]);
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "unstable", feature(const_fn, drop_types_in_const))]
#![cfg_attr(feature = "serde_derive", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

extern crate inflector;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate hyper;

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;
#[cfg(not(feature = "serde_derive"))]
extern crate serde_codegen;

use std::fs::File;
use std::io::{Write, BufReader, BufWriter};
use std::path::Path;

use botocore::Service as BotocoreService;
use generator::generate_source;

mod botocore;
mod generator;
mod serialization;
mod util;

const BOTOCORE_DIR: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/botocore/botocore/data/");

pub struct Service {
    name: String,
    protocol_date: String,
}

impl Service {
    pub fn new<S>(name: S, protocol_date: S) -> Self
        where S: Into<String>
    {
        Service {
            name: name.into(),
            protocol_date: protocol_date.into(),
        }
    }
}

pub fn generate(service: Service, output_path: &Path) -> i32 {
    let botocore_destination_path = output_path.join(format!("{}_botocore.rs", service.name));
    let serde_destination_path = output_path.join(format!("{}.rs", service.name));
    let botocore_service_data_path = Path::new(BOTOCORE_DIR)
        .join(format!("{}/{}/service-2.json", service.name, service.protocol_date));

    botocore_generate(botocore_service_data_path.as_path(),
                      botocore_destination_path.as_path());
    serde_generate(botocore_destination_path.as_path(),
                   serde_destination_path.as_path());

    return 1;
}

fn botocore_generate(input_path: &Path, output_path: &Path) {
    let input_file = File::open(input_path).expect(&format!(
        "{:?} not found",
        input_path,
    ));

    let service_data_as_reader = BufReader::new(input_file);

    let service: BotocoreService = serde_json::from_reader(service_data_as_reader).expect(&format!(
        "Could not convert JSON in {:?} to Service",
        input_path,
    ));

    let source_code = generate_source(&service);

    let output_file = File::create(output_path).expect(&format!(
        "Couldn't open file for writing: {:?}",
        output_path,
    ));

    let mut output_bufwriter = BufWriter::new(output_file);

    output_bufwriter.write_all(source_code.as_bytes()).expect(&format!(
        "Failed to write generated source code to {:?}",
        output_path,
    ));
}

#[cfg(not(feature = "serde_derive"))]
fn serde_generate(source: &Path, destination: &Path) {
    ::serde_codegen::expand(&source, &destination).unwrap();
}

#[cfg(feature = "serde_derive")]
fn serde_generate(source: &Path, destination: &Path) {
    ::std::fs::copy(source, destination).expect(&format!(
        "Failed to copy {:?} to {:?}",
        source,
        destination,
    ));
}
<commit_msg>only run serde codegen on services that require json serialization<commit_after>#![cfg_attr(feature = "unstable", feature(const_fn, drop_types_in_const))]
#![cfg_attr(feature = "serde_derive", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

extern crate inflector;
#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate serde;
extern crate serde_json;
extern crate hyper;

#[cfg(feature = "serde_derive")]
#[macro_use]
extern crate serde_derive;
#[cfg(not(feature = "serde_derive"))]
extern crate serde_codegen;

use std::fs::{File, rename};
use std::io::{Write, BufReader, BufWriter};
use std::path::Path;

use botocore::Service as BotocoreService;
use generator::generate_source;

mod botocore;
mod generator;
mod serialization;
mod util;

const BOTOCORE_DIR: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/botocore/botocore/data/");

pub struct Service {
    name: String,
    protocol_date: String,
}

impl Service {
    pub fn new<S>(name: S, protocol_date: S) -> Self
        where S: Into<String>
    {
        Service {
            name: name.into(),
            protocol_date: protocol_date.into(),
        }
    }
}

pub fn generate(service: Service, output_path: &Path) -> i32 {
    let botocore_destination_path = output_path.join(format!("{}_botocore.rs", service.name));
    let serde_destination_path = output_path.join(format!("{}.rs", service.name));
    let botocore_service_data_path = Path::new(BOTOCORE_DIR)
        .join(format!("{}/{}/service-2.json", service.name, service.protocol_date));

    let needs_serde = botocore_generate(botocore_service_data_path.as_path(),
                      botocore_destination_path.as_path());

    // only pass the generated code through serde if we actually need JSON serialization
    if needs_serde {
        serde_generate(botocore_destination_path.as_path(),
                       serde_destination_path.as_path());
    } else {
        rename(botocore_destination_path, serde_destination_path).unwrap();
    }

    return 1;

}

fn botocore_generate(input_path: &Path, output_path: &Path) -> bool {
    let input_file = File::open(input_path).expect(&format!(
        "{:?} not found",
        input_path,
    ));

    let service_data_as_reader = BufReader::new(input_file);

    let service: BotocoreService = serde_json::from_reader(service_data_as_reader).expect(&format!(
        "Could not convert JSON in {:?} to Service",
        input_path,
    ));

    let source_code = generate_source(&service);

    let output_file = File::create(output_path).expect(&format!(
        "Couldn't open file for writing: {:?}",
        output_path,
    ));

    let mut output_bufwriter = BufWriter::new(output_file);

    output_bufwriter.write_all(source_code.as_bytes()).expect(&format!(
        "Failed to write generated source code to {:?}",
        output_path,
    ));

    match &service.metadata.protocol[..] {
        "json" | "rest-json" => true,
        _ => false
    }
}

#[cfg(not(feature = "serde_derive"))]
fn serde_generate(source: &Path, destination: &Path) {
    ::serde_codegen::expand(&source, &destination).unwrap();
}

#[cfg(feature = "serde_derive")]
fn serde_generate(source: &Path, destination: &Path) {
    ::std::fs::copy(source, destination).expect(&format!(
        "Failed to copy {:?} to {:?}",
        source,
        destination,
    ));
}
<|endoftext|>


<commit_before>extern crate handlebars;
extern crate itertools;
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

use handlebars::Handlebars;
use itertools::Itertools;
use serde_json::Value;
use std::collections::BTreeMap;

trait Codegen {
    fn codegen(&self, handlebars: &Handlebars) -> String;
}

#[derive(Debug, Deserialize)]
pub struct AMQProtocolDefinition {
    pub name:          String,
    #[serde(rename="major-version")]
    pub major_version: u8,
    #[serde(rename="minor-version")]
    pub minor_version: u8,
    pub revision:      u8,
    pub port:          u32,
    pub copyright:     Vec<String>,
    pub domains:       Vec<AMQPDomain>,
    pub constants:     Vec<AMQPConstant>,
    pub classes:       Vec<AMQPClass>,
}

impl AMQProtocolDefinition {
    pub fn codegen(&self, templates: &AMQPTemplates) -> String {
        let handlebars = register_templates(templates);
        let mut data   = BTreeMap::new();

        data.insert("name".to_string(),          self.name.clone());
        data.insert("major_version".to_string(), format!("{}", self.major_version));
        data.insert("minor_version".to_string(), format!("{}", self.minor_version));
        data.insert("revision".to_string(),      format!("{}", self.revision));
        data.insert("port".to_string(),          format!("{}", self.port));
        data.insert("copyright".to_string(),     self.copyright.iter().join("\n"));
        data.insert("domains".to_string(),       self.domains.iter().map(|domain| domain.codegen(&handlebars)).join("\n"));
        data.insert("constants".to_string(),     self.constants.iter().map(|constant| constant.codegen(&handlebars)).join("\n"));
        data.insert("classes".to_string(),       self.classes.iter().map(|klass| klass.codegen(&handlebars)).join("\n"));

        handlebars.render("main", &data).expect("Failed to render main template")
    }
}

fn register_templates(templates: &AMQPTemplates) -> Handlebars {
    let mut handlebars = Handlebars::new();

    handlebars.register_template_string("main",     &templates.main).expect("Failed to register main template");
    handlebars.register_template_string("domain",   &templates.main).expect("Failed to register domain template");
    handlebars.register_template_string("constant", &templates.constant).expect("Failed to register constant template");
    handlebars.register_template_string("class",    &templates.klass).expect("Failed to register class template");
    handlebars.register_template_string("method",   &templates.method).expect("Failed to register method template");
    handlebars.register_template_string("argument", &templates.argument).expect("Failed to register argument template");
    handlebars.register_template_string("property", &templates.property).expect("Failed to register property template");

    handlebars
}

pub struct AMQPTemplates {
    pub main:     String,
    pub domain:   String,
    pub constant: String,
    pub klass:    String,
    pub method:   String,
    pub argument: String,
    pub property: String,
}

#[derive(Debug, Deserialize)]
pub enum AMQPType {
    #[serde(rename="bit")]
    Bit,
    #[serde(rename="octet")]
    Octet,
    #[serde(rename="short")]
    Short,
    #[serde(rename="long")]
    Long,
    #[serde(rename="longlong")]
    LongLong,
    #[serde(rename="shortstr")]
    ShortStr,
    #[serde(rename="longstr")]
    LongStr,
    #[serde(rename="table")]
    Table,
    #[serde(rename="timestamp")]
    Timestamp,
}

impl AMQPType {
    fn to_string(&self) -> String {
        match *self {
            AMQPType::Bit       => "bit",
            AMQPType::Octet     => "octet",
            AMQPType::Short     => "short",
            AMQPType::Long      => "long",
            AMQPType::LongLong  => "longlong",
            AMQPType::ShortStr  => "shortstr",
            AMQPType::LongStr   => "longstr",
            AMQPType::Table     => "table",
            AMQPType::Timestamp => "timestamp",
        }.to_string()
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPDomain(String, AMQPType);

impl Codegen for AMQPDomain {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("name".to_string(), self.0.clone());
        data.insert("type".to_string(), self.1.to_string());

        handlebars.render("domain", &data).expect("Failed to render domain template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPConstant {
    pub name:  String,
    pub value: u16,
    #[serde(rename="class")]
    pub klass: Option<String>,
}

impl Codegen for AMQPConstant {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("name".to_string(),  self.name.clone());
        data.insert("value".to_string(), format!("{}", self.value));
        if let Some(ref klass) = self.klass {
            data.insert("class".to_string(), klass);
        }

        handlebars.render("constant", &data).expect("Failed to render constant template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPClass {
    pub id:         u8,
    pub methods:    Vec<AMQPMethod>,
    pub name:       String,
    pub properties: Option<Vec<AMQPProperty>>,
}

impl Codegen for AMQPClass {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("id".to_string(),      format!("{}", self.id));
        data.insert("methods".to_string(), self.methods.iter().map(|method| method.codegen(&handlebars)).join("\n"));
        data.insert("name".to_string(),    self.name.clone());
        if let Some(ref properties) = self.properties {
            data.insert("properties".to_string(), properties.iter().map(|prop| prop.codegen(&handlebars)).join("\n"));
        }

        handlebars.render("class", &data).expect("Failed to render class template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPMethod {
    pub id:          u8,
    pub arguments:   Vec<AMQPArgument>,
    pub name:        String,
    pub synchronous: Option<bool>,
}

impl Codegen for AMQPMethod {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("id".to_string(),          format!("{}", self.id));
        data.insert("arguments".to_string(),   self.arguments.iter().map(|arg| arg.codegen(&handlebars)).join("\n"));
        data.insert("name".to_string(),        self.name.clone());
        data.insert("synchronous".to_string(), format!("{}", self.synchronous.unwrap_or(false)));

        handlebars.render("method", &data).expect("Failed to render method template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPArgument {
    #[serde(rename="type")]
    pub amqp_type:     Option<AMQPType>,
    pub name:          String,
    #[serde(rename="default-value")]
    pub default_value: Option<Value>,
    pub domain:        Option<String>,
}

impl Codegen for AMQPArgument {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        if let Some(ref amqp_type) = self.amqp_type {
            data.insert("type".to_string(), amqp_type.to_string());
        }
        if let Some(ref default_value) = self.default_value {
            data.insert("default_value".to_string(), default_value.to_string());
        }
        data.insert("name".to_string(),   self.name.clone());
        if let Some(ref domain) = self.domain {
            data.insert("domain".to_string(), domain.clone());
        }

        handlebars.render("domain", &data).expect("Failed to render domain template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPProperty {
    #[serde(rename="type")]
    pub amqp_type: AMQPType,
    pub name:      String,
}

impl Codegen for AMQPProperty {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("type".to_string(), self.amqp_type.to_string());
        data.insert("name".to_string(), self.name.clone());

        handlebars.render("domain", &data).expect("Failed to render domain template")
    }
}

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

    fn specs() -> AMQProtocolDefinition {
        AMQProtocolDefinition {
            name:          "AMQP".to_string(),
            major_version: 0,
            minor_version: 9,
            revision:      1,
            port:          5672,
            copyright:     Vec::new(),
            domains:       Vec::new(),
            constants:     Vec::new(),
            classes:       Vec::new(),
        }
    }

    fn templates() -> AMQPTemplates {
        AMQPTemplates {
            main:     "{{name}} - {{major_version}}.{{minor_version}}.{{revision}}".to_string(),
            domain:   String::new(),
            constant: String::new(),
            klass:    String::new(),
            method:   String::new(),
            argument: String::new(),
            property: String::new(),
        }
    }

    #[test]
    fn main_template() {
        assert_eq!(specs().codegen(&templates()), "AMQP - 0.9.1");
    }
}
<commit_msg>codegen: fix build<commit_after>extern crate handlebars;
extern crate itertools;
extern crate serde;
#[macro_use] extern crate serde_derive;
extern crate serde_json;

use handlebars::Handlebars;
use itertools::Itertools;
use serde_json::Value;
use std::collections::BTreeMap;

trait Codegen {
    fn codegen(&self, handlebars: &Handlebars) -> String;
}

#[derive(Debug, Deserialize)]
pub struct AMQProtocolDefinition {
    pub name:          String,
    #[serde(rename="major-version")]
    pub major_version: u8,
    #[serde(rename="minor-version")]
    pub minor_version: u8,
    pub revision:      u8,
    pub port:          u32,
    pub copyright:     Vec<String>,
    pub domains:       Vec<AMQPDomain>,
    pub constants:     Vec<AMQPConstant>,
    pub classes:       Vec<AMQPClass>,
}

impl AMQProtocolDefinition {
    pub fn codegen(&self, templates: &AMQPTemplates) -> String {
        let handlebars = register_templates(templates);
        let mut data   = BTreeMap::new();

        data.insert("name".to_string(),          self.name.clone());
        data.insert("major_version".to_string(), format!("{}", self.major_version));
        data.insert("minor_version".to_string(), format!("{}", self.minor_version));
        data.insert("revision".to_string(),      format!("{}", self.revision));
        data.insert("port".to_string(),          format!("{}", self.port));
        data.insert("copyright".to_string(),     self.copyright.iter().join("\n"));
        data.insert("domains".to_string(),       self.domains.iter().map(|domain| domain.codegen(&handlebars)).join("\n"));
        data.insert("constants".to_string(),     self.constants.iter().map(|constant| constant.codegen(&handlebars)).join("\n"));
        data.insert("classes".to_string(),       self.classes.iter().map(|klass| klass.codegen(&handlebars)).join("\n"));

        handlebars.render("main", &data).expect("Failed to render main template")
    }
}

fn register_templates(templates: &AMQPTemplates) -> Handlebars {
    let mut handlebars = Handlebars::new();

    handlebars.register_template_string("main",     &templates.main).expect("Failed to register main template");
    handlebars.register_template_string("domain",   &templates.main).expect("Failed to register domain template");
    handlebars.register_template_string("constant", &templates.constant).expect("Failed to register constant template");
    handlebars.register_template_string("class",    &templates.klass).expect("Failed to register class template");
    handlebars.register_template_string("method",   &templates.method).expect("Failed to register method template");
    handlebars.register_template_string("argument", &templates.argument).expect("Failed to register argument template");
    handlebars.register_template_string("property", &templates.property).expect("Failed to register property template");

    handlebars
}

pub struct AMQPTemplates {
    pub main:     String,
    pub domain:   String,
    pub constant: String,
    pub klass:    String,
    pub method:   String,
    pub argument: String,
    pub property: String,
}

#[derive(Debug, Deserialize)]
pub enum AMQPType {
    #[serde(rename="bit")]
    Bit,
    #[serde(rename="octet")]
    Octet,
    #[serde(rename="short")]
    Short,
    #[serde(rename="long")]
    Long,
    #[serde(rename="longlong")]
    LongLong,
    #[serde(rename="shortstr")]
    ShortStr,
    #[serde(rename="longstr")]
    LongStr,
    #[serde(rename="table")]
    Table,
    #[serde(rename="timestamp")]
    Timestamp,
}

impl AMQPType {
    fn to_string(&self) -> String {
        match *self {
            AMQPType::Bit       => "bit",
            AMQPType::Octet     => "octet",
            AMQPType::Short     => "short",
            AMQPType::Long      => "long",
            AMQPType::LongLong  => "longlong",
            AMQPType::ShortStr  => "shortstr",
            AMQPType::LongStr   => "longstr",
            AMQPType::Table     => "table",
            AMQPType::Timestamp => "timestamp",
        }.to_string()
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPDomain(String, AMQPType);

impl Codegen for AMQPDomain {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("name".to_string(), self.0.clone());
        data.insert("type".to_string(), self.1.to_string());

        handlebars.render("domain", &data).expect("Failed to render domain template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPConstant {
    pub name:  String,
    pub value: u16,
    #[serde(rename="class")]
    pub klass: Option<String>,
}

impl Codegen for AMQPConstant {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("name".to_string(),  self.name.clone());
        data.insert("value".to_string(), format!("{}", self.value));
        if let Some(ref klass) = self.klass {
            data.insert("class".to_string(), klass.clone());
        }

        handlebars.render("constant", &data).expect("Failed to render constant template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPClass {
    pub id:         u8,
    pub methods:    Vec<AMQPMethod>,
    pub name:       String,
    pub properties: Option<Vec<AMQPProperty>>,
}

impl Codegen for AMQPClass {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("id".to_string(),      format!("{}", self.id));
        data.insert("methods".to_string(), self.methods.iter().map(|method| method.codegen(&handlebars)).join("\n"));
        data.insert("name".to_string(),    self.name.clone());
        if let Some(ref properties) = self.properties {
            data.insert("properties".to_string(), properties.iter().map(|prop| prop.codegen(&handlebars)).join("\n"));
        }

        handlebars.render("class", &data).expect("Failed to render class template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPMethod {
    pub id:          u8,
    pub arguments:   Vec<AMQPArgument>,
    pub name:        String,
    pub synchronous: Option<bool>,
}

impl Codegen for AMQPMethod {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("id".to_string(),          format!("{}", self.id));
        data.insert("arguments".to_string(),   self.arguments.iter().map(|arg| arg.codegen(&handlebars)).join("\n"));
        data.insert("name".to_string(),        self.name.clone());
        data.insert("synchronous".to_string(), format!("{}", self.synchronous.unwrap_or(false)));

        handlebars.render("method", &data).expect("Failed to render method template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPArgument {
    #[serde(rename="type")]
    pub amqp_type:     Option<AMQPType>,
    pub name:          String,
    #[serde(rename="default-value")]
    pub default_value: Option<Value>,
    pub domain:        Option<String>,
}

impl Codegen for AMQPArgument {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        if let Some(ref amqp_type) = self.amqp_type {
            data.insert("type".to_string(), amqp_type.to_string());
        }
        if let Some(ref default_value) = self.default_value {
            data.insert("default_value".to_string(), default_value.to_string());
        }
        data.insert("name".to_string(),   self.name.clone());
        if let Some(ref domain) = self.domain {
            data.insert("domain".to_string(), domain.clone());
        }

        handlebars.render("domain", &data).expect("Failed to render domain template")
    }
}

#[derive(Debug, Deserialize)]
pub struct AMQPProperty {
    #[serde(rename="type")]
    pub amqp_type: AMQPType,
    pub name:      String,
}

impl Codegen for AMQPProperty {
    fn codegen(&self, handlebars: &Handlebars) -> String {
        let mut data = BTreeMap::new();

        data.insert("type".to_string(), self.amqp_type.to_string());
        data.insert("name".to_string(), self.name.clone());

        handlebars.render("domain", &data).expect("Failed to render domain template")
    }
}

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

    fn specs() -> AMQProtocolDefinition {
        AMQProtocolDefinition {
            name:          "AMQP".to_string(),
            major_version: 0,
            minor_version: 9,
            revision:      1,
            port:          5672,
            copyright:     Vec::new(),
            domains:       Vec::new(),
            constants:     Vec::new(),
            classes:       Vec::new(),
        }
    }

    fn templates() -> AMQPTemplates {
        AMQPTemplates {
            main:     "{{name}} - {{major_version}}.{{minor_version}}.{{revision}}".to_string(),
            domain:   String::new(),
            constant: String::new(),
            klass:    String::new(),
            method:   String::new(),
            argument: String::new(),
            property: String::new(),
        }
    }

    #[test]
    fn main_template() {
        assert_eq!(specs().codegen(&templates()), "AMQP - 0.9.1");
    }
}
<|endoftext|>


<commit_before>use std::sync::atomic::{AtomicU64, Ordering};

lazy_static! {
    static ref NEXT_FUTURE_ID: AtomicU64 = AtomicU64::new(0);
}

///
/// ID of a future used in a state
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub (super) struct FutureId(pub u64);

impl FutureId {
    ///
    /// Creates a new unique future ID
    ///
    pub fn new() -> FutureId {
        let next_id = NEXT_FUTURE_ID.fetch_add(1, Ordering::Relaxed);

        FutureId(next_id)
    }
}

///
/// Represents the state of a job queue
///
#[derive(PartialEq, Debug, Clone, Copy)]
pub (super) enum QueueState {
    /// Queue is currently not running and not ready to run
    ///
    /// The queue has this state when it has no jobs in it.
    Idle,

    /// Queue has been queued up to run but isn't running yet
    ///
    /// In general, this means the queue is waiting for a background thread to run on.
    Pending,

    /// Queue has been assigned to a thread and is currently running
    ///
    /// The queue must not be scheduled anywhere else while this is going on.
    Running,

    /// A job on the queue has indicated that it's waiting to be re-awakened (by the scheduler)
    ///
    /// This state is reached when a future for this queue generates a result and the queue moves
    /// into the pending state. It generally means it's scheduled to resume on a background
    /// thread (similar to Pending)
    WaitingForWake,

    /// The queue is running synchronously on a thread and is waiting to be unparked
    ///
    /// This occurs when the queue has been running on a thread and needs to wait for an event to
    /// occur on some other thread, usually the completion of a future. Queues in this state must
    /// only be resumed by the appropriate unparking method (the queue is effectively 'running'
    /// on the thread where it is parked)
    WaitingForUnpark,

    /// We've returned from a polling operation and are waiting to be resumed
    ///
    /// This happens when a queue has scheduled itself onto a thread as a result of calling the
    /// poll() method on a future and has returned pending. This queue should be resumed when the
    /// future is next awoken by calling 'poll' (it's effectively 'running' in the context of the
    /// call too poll)
    ///
    /// Only the future that moved the queue into this state can re-awaken the queue (ie, any other
    /// futures must wait for this one to complete first)
    WaitingForPoll(FutureId),

    /// A wake-up call was made while the queue was in the running state
    ///
    /// When attempting to suspend a queue as the result of a future indicating that it is pending,
    /// it is possible for the future to wake the queue before it has reached the suspended state.
    /// We capture this event by setting the queue's status to 'AwokenWhileRunning'.
    AwokenWhileRunning,

    /// Queue received a panic and is no longer able to be scheduled
    Panicked
}

impl QueueState {
    ///
    /// Indicates if this queue is in the running state
    ///
    pub (crate) fn is_running(&self) -> bool {
        match self {
            QueueState::Running             |
            QueueState::AwokenWhileRunning  |
            QueueState::WaitingForPoll(_)   |
            QueueState::WaitingForUnpark    => true,
            _other                          => false
        }
    }
}
<commit_msg>Add some extra notes about these states.<commit_after>use std::sync::atomic::{AtomicU64, Ordering};

lazy_static! {
    static ref NEXT_FUTURE_ID: AtomicU64 = AtomicU64::new(0);
}

///
/// ID of a future used in a state
///
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub (super) struct FutureId(pub u64);

impl FutureId {
    ///
    /// Creates a new unique future ID
    ///
    pub fn new() -> FutureId {
        let next_id = NEXT_FUTURE_ID.fetch_add(1, Ordering::Relaxed);

        FutureId(next_id)
    }
}

///
/// Represents the state of a job queue
///
#[derive(PartialEq, Debug, Clone, Copy)]
pub (super) enum QueueState {
    /// Queue is currently not running and not ready to run
    ///
    /// The queue has this state when it has no jobs in it.
    Idle,

    /// Queue has been queued up to run but isn't running yet
    ///
    /// In general, this means the queue is waiting for a background thread to run on.
    Pending,

    /// Queue has been assigned to a thread and is currently running
    ///
    /// The queue must not be scheduled anywhere else while this is going on.
    Running,

    /// A job on the queue has indicated that it's waiting to be re-awakened (by the scheduler)
    ///
    /// This state is reached when a future for this queue generates a result and the queue moves
    /// into the pending state. It generally means it's scheduled to resume on a background
    /// thread (similar to Pending)
    WaitingForWake,

    /// The queue is running synchronously on a thread and is waiting to be unparked
    ///
    /// This occurs when the queue has been running on a thread and needs to wait for an event to
    /// occur on some other thread, usually the completion of a future. Queues in this state must
    /// only be resumed by the appropriate unparking method (the queue is effectively 'running'
    /// on the thread where it is parked)
    ///
    /// As the queue is only allowed to run on one thread at any one time, only one thread can be
    /// waiting to be unparked.
    WaitingForUnpark,

    /// We've returned from a polling operation and are waiting to be resumed
    ///
    /// This happens when a queue has scheduled itself onto a thread as a result of calling the
    /// poll() method on a future and has returned pending. This queue should be resumed when the
    /// future is next awoken by calling 'poll' (it's effectively 'running' in the context of the
    /// call too poll)
    ///
    /// Only the future that moved the queue into this state can re-awaken the queue (ie, any other
    /// futures must wait for this one to complete first). As the queue can only run on a single
    /// thread at any one time, only a single future is allowed to put the queue into this state.
    WaitingForPoll(FutureId),

    /// A wake-up call was made while the queue was in the running state
    ///
    /// When attempting to suspend a queue as the result of a future indicating that it is pending,
    /// it is possible for the future to wake the queue before it has reached the suspended state.
    /// We capture this event by setting the queue's status to 'AwokenWhileRunning'.
    AwokenWhileRunning,

    /// Queue received a panic and is no longer able to be scheduled
    Panicked
}

impl QueueState {
    ///
    /// Indicates if this queue is in the running state
    ///
    pub (crate) fn is_running(&self) -> bool {
        match self {
            QueueState::Running             |
            QueueState::AwokenWhileRunning  |
            QueueState::WaitingForPoll(_)   |
            QueueState::WaitingForUnpark    => true,
            _other                          => false
        }
    }
}
<|endoftext|>


<commit_before>//! Generator of Rust-Qt crates.
//!
//! See [README](https://github.com/rust-qt/cpp_to_rust/tree/master/qt_generator/qt_generator)
//! for more information.

#![allow(clippy::collapsible_if)]

use crate::lib_configs::create_config;
use itertools::Itertools;
use log::{error, info};
use qt_ritual_common::all_crate_names;
use ritual::processor;
use ritual::workspace::Workspace;
use ritual_common::errors::{FancyUnwrap, Result};
use ritual_common::file_utils::canonicalize;
use ritual_common::file_utils::path_to_str;
use std::path::PathBuf;
use structopt::StructOpt;
mod detect_signal_argument_types;
mod detect_signals_and_slots;
mod doc_decoder;
mod doc_parser;
mod fix_header_names;
mod lib_configs;
mod slot_wrappers;
mod versions;

#[cfg(test)]
mod test_moqt;

use flexi_logger::{Duplicate, LevelFilter, LogSpecification, Logger};

#[derive(Debug, StructOpt)]
/// Generates rust_qt crates using ritual.
/// See https://github.com/rust-qt/cpp_to_rust for more details.
struct Options {
    #[structopt(parse(from_os_str))]
    /// Directory for output and temporary files
    workspace: PathBuf,
    #[structopt(long = "local-paths")]
    /// Write local paths to `ritual` crates in generated `Cargo.toml`
    local_paths: Option<bool>,
    #[structopt(long = "delete-database")]
    /// Delete previously created database before processing
    delete_database: bool,
    #[structopt(short = "c", long = "crates", required = true)]
    /// Crates to process (e.g. `qt_core`)
    crates: Vec<String>,
    #[structopt(short = "o", long = "operations", required = true)]
    /// Operations to perform
    operations: Vec<String>,
}

fn run(options: Options) -> Result<()> {
    let workspace_path = canonicalize(options.workspace)?;

    let mut workspace = Workspace::new(workspace_path.clone())?;

    Logger::with(LogSpecification::default(LevelFilter::Trace).build())
        .log_to_file()
        .directory(path_to_str(&workspace.log_path())?)
        .print_message()
        .duplicate_to_stderr(Duplicate::Info)
        .start()
        .unwrap_or_else(|e| panic!("Logger initialization failed: {}", e));

    info!("Workspace: {}", workspace_path.display());

    if let Some(local_paths) = options.local_paths {
        workspace.set_write_dependencies_local_paths(local_paths)?;
    }

    let mut was_any_action = false;

    let final_crates = if options.crates.iter().any(|x| *x == "all") {
        all_crate_names().to_vec()
    } else {
        options.crates.iter().map(|s| s.as_str()).collect()
    };

    let operations = options
        .operations
        .iter()
        .map(|s| s.to_lowercase())
        .collect_vec();

    if operations.is_empty() {
        error!("No action requested. Run \"qt_generator --help\".");
        return Ok(());
    }

    for crate_name in &final_crates {
        if options.delete_database {
            workspace.delete_database_if_exists(&crate_name)?;
        }

        let config = create_config(&crate_name)?;
        was_any_action = true;
        processor::process(&mut workspace, &config, &operations)?;
    }

    //workspace.save_data()?;
    if was_any_action {
        info!("qt_generator finished");
    } else {
        error!("No action requested. Run \"qt_generator --help\".");
    }
    Ok(())
}

pub fn main() {
    run(Options::from_args()).fancy_unwrap();
}
<commit_msg>disable moqt test on macos<commit_after>//! Generator of Rust-Qt crates.
//!
//! See [README](https://github.com/rust-qt/cpp_to_rust/tree/master/qt_generator/qt_generator)
//! for more information.

#![allow(clippy::collapsible_if)]

use crate::lib_configs::create_config;
use itertools::Itertools;
use log::{error, info};
use qt_ritual_common::all_crate_names;
use ritual::processor;
use ritual::workspace::Workspace;
use ritual_common::errors::{FancyUnwrap, Result};
use ritual_common::file_utils::canonicalize;
use ritual_common::file_utils::path_to_str;
use std::path::PathBuf;
use structopt::StructOpt;
mod detect_signal_argument_types;
mod detect_signals_and_slots;
mod doc_decoder;
mod doc_parser;
mod fix_header_names;
mod lib_configs;
mod slot_wrappers;
mod versions;

#[cfg(not(target_os = "macos"))]
#[cfg(test)]
mod test_moqt;

use flexi_logger::{Duplicate, LevelFilter, LogSpecification, Logger};

#[derive(Debug, StructOpt)]
/// Generates rust_qt crates using ritual.
/// See https://github.com/rust-qt/cpp_to_rust for more details.
struct Options {
    #[structopt(parse(from_os_str))]
    /// Directory for output and temporary files
    workspace: PathBuf,
    #[structopt(long = "local-paths")]
    /// Write local paths to `ritual` crates in generated `Cargo.toml`
    local_paths: Option<bool>,
    #[structopt(long = "delete-database")]
    /// Delete previously created database before processing
    delete_database: bool,
    #[structopt(short = "c", long = "crates", required = true)]
    /// Crates to process (e.g. `qt_core`)
    crates: Vec<String>,
    #[structopt(short = "o", long = "operations", required = true)]
    /// Operations to perform
    operations: Vec<String>,
}

fn run(options: Options) -> Result<()> {
    let workspace_path = canonicalize(options.workspace)?;

    let mut workspace = Workspace::new(workspace_path.clone())?;

    Logger::with(LogSpecification::default(LevelFilter::Trace).build())
        .log_to_file()
        .directory(path_to_str(&workspace.log_path())?)
        .print_message()
        .duplicate_to_stderr(Duplicate::Info)
        .start()
        .unwrap_or_else(|e| panic!("Logger initialization failed: {}", e));

    info!("Workspace: {}", workspace_path.display());

    if let Some(local_paths) = options.local_paths {
        workspace.set_write_dependencies_local_paths(local_paths)?;
    }

    let mut was_any_action = false;

    let final_crates = if options.crates.iter().any(|x| *x == "all") {
        all_crate_names().to_vec()
    } else {
        options.crates.iter().map(|s| s.as_str()).collect()
    };

    let operations = options
        .operations
        .iter()
        .map(|s| s.to_lowercase())
        .collect_vec();

    if operations.is_empty() {
        error!("No action requested. Run \"qt_generator --help\".");
        return Ok(());
    }

    for crate_name in &final_crates {
        if options.delete_database {
            workspace.delete_database_if_exists(&crate_name)?;
        }

        let config = create_config(&crate_name)?;
        was_any_action = true;
        processor::process(&mut workspace, &config, &operations)?;
    }

    //workspace.save_data()?;
    if was_any_action {
        info!("qt_generator finished");
    } else {
        error!("No action requested. Run \"qt_generator --help\".");
    }
    Ok(())
}

pub fn main() {
    run(Options::from_args()).fancy_unwrap();
}
<|endoftext|>


<commit_before>use std::rand::{task_rng, Rng};
use std::sync::Arc;
use raytracer::compositor::composite;
use raytracer::{Ray, Tile};
use scene::{Camera, Scene};
use vec3::Vec3;

pub struct Renderer {
    pub reflect_depth: int,  // Maximum reflection recursions.
    pub refract_depth: int,  // Maximum refraction recursions. A sphere takes up 2 recursions.
    pub use_octree: bool,    // Unimplemented. Use octree/k-d tree?
    pub shadow_samples: int, // Number of samples for soft shadows and area lights.
    pub pixel_samples: int,  // The square of this is the number of samples per pixel.
    pub tasks: int           // Minimum number of tasks to spawn.
}

impl Renderer {
    pub fn render(&self, camera: Camera, scene: Scene) -> Vec<Vec3> {
        let mut tiles = Vec::with_capacity(self.tasks as uint);
        let tiles_per_side = (self.tasks as f64).sqrt().ceil() as int;
        let tile_width  = (camera.image_width  as f64 / tiles_per_side as f64) as int;
        let tile_height = (camera.image_height as f64 / tiles_per_side as f64) as int;

        let shared_scene = Arc::new(scene);
        let (tx, rx) = channel();

        for tile_x in range(0, tiles_per_side) {
            for tile_y in range(0, tiles_per_side) {
                let scene_local = shared_scene.clone();
                let child_tx = tx.clone();

                let shadow_samples_local = self.shadow_samples;
                let pixel_samples_local = self.pixel_samples;
                let reflect_depth_local = self.reflect_depth;
                let refract_depth_local = self.refract_depth;

                let start_x = tile_x * tile_width;
                let start_y = tile_y * tile_height;
                let end_x = start_x + tile_width;
                let end_y = start_y + tile_height;

                spawn(proc() {
                    child_tx.send(Renderer::render_tile(camera,
                                                        scene_local.deref(),
                                                        shadow_samples_local,
                                                        pixel_samples_local,
                                                        reflect_depth_local,
                                                        refract_depth_local,
                                                        start_x, start_y,
                                                        end_x, end_y));
                });

            }
        }

        for _ in range(0, tiles_per_side * tiles_per_side) {
            tiles.push(rx.recv())
        }

        composite(tiles, camera.image_width, camera.image_height)
    }

    fn render_tile(camera: Camera,
                   scene: &Scene,
                   shadow_samples: int,
                   pixel_samples: int,
                   reflect_depth: int,
                   refract_depth: int,
                   from_x: int,
                   from_y: int,
                   to_x: int,
                   to_y: int)
                   -> Tile {
        let width  = to_x - from_x;
        let height = to_y - from_y;
        let tile_size = width * height;
        let mut image_data: Vec<Vec3> = Vec::with_capacity(tile_size as uint);

        for y in range(from_y, to_y) {
            for x in range(from_x, to_x) {
                let mut color = Vec3::zero();

                // Supersampling, jitter algorithm
                let mut rng = task_rng();
                let pixel_width = 1.0 / pixel_samples as f64;

                for _ in range(0, pixel_samples) {
                    for _ in range(0, pixel_samples) {
                        let mut j_x = x as f64 + rng.gen::<f64>() * pixel_width as f64;
                        let mut j_y = y as f64 + rng.gen::<f64>() * pixel_width as f64;

                        // Unwanted jitter if not anti-aliasing
                        if pixel_samples == 1 {
                            j_x = x as f64;
                            j_y = y as f64;
                        }

                        let ray = camera.get_ray(j_x, j_y);
                        let result = Renderer::trace(scene, &ray, shadow_samples, reflect_depth, refract_depth, false);
                        color = color + result.scale(1.0 / (pixel_samples * pixel_samples) as f64);
                    }
                }

                image_data.push(Vec3 {
                    x: color.x,
                    y: color.y,
                    z: color.z
                });
            }
        }

        Tile {
            from_x: from_x,
            from_y: from_y,
            to_x: to_x,
            to_y: to_y,
            data: image_data
        }
    }

    fn trace(scene: &Scene,
             ray: &Ray,
             shadow_samples: int,
             reflect_depth: int,
             refract_depth: int,
             inside: bool)
             -> Vec3 {
        if reflect_depth <= 0 || refract_depth <= 0 { return Vec3::zero() }
        let epsilon = ::std::f64::EPSILON * 10000.0;

        match ray.get_nearest_hit(scene) {
            Some(nearest_hit) => {
                let n = nearest_hit.n.unit();
                let i = (ray.direction.scale(-1.0)).unit();

                // Local lighting computation: surface shading, shadows
                let mut result = scene.lights.iter().fold(Vec3::zero(), |color_acc, light| {
                    let mut shadow = Vec3::zero();

                    if shadow_samples > 0 {
                        // Point light speedup
                        let shadow_sample_tries = if light.is_point() { 1 } else { shadow_samples };

                        // Take average shadow color after jittering/sampling light position
                        for _ in range(0, shadow_sample_tries) {
                            // L has to be a unit vector for t_max 1:1 correspondence to
                            // distance to light to work. Shadow feelers only search up
                            // until light source.
                            let sampled_light_position = light.position();
                            let shadow_l = (sampled_light_position - nearest_hit.position).unit();
                            let shadow_ray = Ray {origin: nearest_hit.position, direction: shadow_l};
                            let distance_to_light = (sampled_light_position - nearest_hit.position).len();

                            // Check against candidate primitives in scene for occlusion
                            // and multiply shadow color by occluders' shadow colors
                            shadow = shadow + scene.prims.iter().fold(Vec3::one(), |shadow_acc, prim| {
                                let occlusion = prim.intersects(&shadow_ray, epsilon, distance_to_light);
                                match occlusion {
                                    Some(occulusion) => {shadow_acc * occulusion.material.transmission()}
                                    None => shadow_acc
                                }
                            });
                        }

                        shadow = shadow.scale(1.0 / shadow_sample_tries as f64);
                    } else {
                        shadow = Vec3::one();
                    }

                    let l = (light.center() - nearest_hit.position).unit();

                    color_acc + light.color() * nearest_hit.material.sample(n, i, l) * shadow
                });

                // Global reflection
                if nearest_hit.material.is_reflective() {
                    let r = Vec3::reflect(&i, &n);
                    let reflect_ray = Ray {origin: nearest_hit.position, direction: r};
                    let reflection = Renderer::trace(scene, &reflect_ray, shadow_samples, reflect_depth - 1, refract_depth, inside);

                    result = result + nearest_hit.material.global_specular(&reflection);
                }

                // Global refraction
                if nearest_hit.material.is_refractive() {
                    let t = Vec3::refract(&i, &n, nearest_hit.material.ior(), inside);
                    let refract_ray = Ray {origin: nearest_hit.position + t.scale(epsilon), direction: t};
                    let refraction = Renderer::trace(scene, &refract_ray, shadow_samples, reflect_depth, refract_depth, !inside);

                    result = result + nearest_hit.material.global_transmissive(&refraction);
                }

                result
            }

            None => {scene.background}
        }
    }
}
<commit_msg>Fix broken supersampling jitter.<commit_after>use std::rand::{task_rng, Rng};
use std::sync::Arc;
use raytracer::compositor::composite;
use raytracer::{Ray, Tile};
use scene::{Camera, Scene};
use vec3::Vec3;

pub struct Renderer {
    pub reflect_depth: int,  // Maximum reflection recursions.
    pub refract_depth: int,  // Maximum refraction recursions. A sphere takes up 2 recursions.
    pub use_octree: bool,    // Unimplemented. Use octree/k-d tree?
    pub shadow_samples: int, // Number of samples for soft shadows and area lights.
    pub pixel_samples: int,  // The square of this is the number of samples per pixel.
    pub tasks: int           // Minimum number of tasks to spawn.
}

impl Renderer {
    pub fn render(&self, camera: Camera, scene: Scene) -> Vec<Vec3> {
        let mut tiles = Vec::with_capacity(self.tasks as uint);
        let tiles_per_side = (self.tasks as f64).sqrt().ceil() as int;
        let tile_width  = (camera.image_width  as f64 / tiles_per_side as f64) as int;
        let tile_height = (camera.image_height as f64 / tiles_per_side as f64) as int;

        let shared_scene = Arc::new(scene);
        let (tx, rx) = channel();

        for tile_x in range(0, tiles_per_side) {
            for tile_y in range(0, tiles_per_side) {
                let scene_local = shared_scene.clone();
                let child_tx = tx.clone();

                let shadow_samples_local = self.shadow_samples;
                let pixel_samples_local = self.pixel_samples;
                let reflect_depth_local = self.reflect_depth;
                let refract_depth_local = self.refract_depth;

                let start_x = tile_x * tile_width;
                let start_y = tile_y * tile_height;
                let end_x = start_x + tile_width;
                let end_y = start_y + tile_height;

                spawn(proc() {
                    child_tx.send(Renderer::render_tile(camera,
                                                        scene_local.deref(),
                                                        shadow_samples_local,
                                                        pixel_samples_local,
                                                        reflect_depth_local,
                                                        refract_depth_local,
                                                        start_x, start_y,
                                                        end_x, end_y));
                });

            }
        }

        for _ in range(0, tiles_per_side * tiles_per_side) {
            tiles.push(rx.recv())
        }

        composite(tiles, camera.image_width, camera.image_height)
    }

    fn render_tile(camera: Camera,
                   scene: &Scene,
                   shadow_samples: int,
                   pixel_samples: int,
                   reflect_depth: int,
                   refract_depth: int,
                   from_x: int,
                   from_y: int,
                   to_x: int,
                   to_y: int)
                   -> Tile {
        let width  = to_x - from_x;
        let height = to_y - from_y;
        let tile_size = width * height;
        let mut image_data: Vec<Vec3> = Vec::with_capacity(tile_size as uint);

        for y in range(from_y, to_y) {
            for x in range(from_x, to_x) {
                let mut color = Vec3::zero();

                // Supersampling, jitter algorithm
                let mut rng = task_rng();
                let pixel_width = 1.0 / pixel_samples as f64;

                for y_subpixel in range(0, pixel_samples) {
                    for x_subpixel in range(0, pixel_samples) {
                        let mut j_x = x as f64;
                        let mut j_y = y as f64;

                        // Don't jitter if not antialiasing
                        if pixel_samples > 1 {
                            j_x = j_x + x_subpixel as f64 * pixel_width + rng.gen::<f64>() * pixel_width as f64;
                            j_y = j_y + y_subpixel as f64 * pixel_width + rng.gen::<f64>() * pixel_width as f64;
                        }

                        let ray = camera.get_ray(j_x, j_y);
                        let result = Renderer::trace(scene, &ray, shadow_samples, reflect_depth, refract_depth, false);
                        color = color + result.scale(1.0 / (pixel_samples * pixel_samples) as f64);
                    }
                }

                image_data.push(Vec3 {
                    x: color.x,
                    y: color.y,
                    z: color.z
                });
            }
        }

        Tile {
            from_x: from_x,
            from_y: from_y,
            to_x: to_x,
            to_y: to_y,
            data: image_data
        }
    }

    fn trace(scene: &Scene,
             ray: &Ray,
             shadow_samples: int,
             reflect_depth: int,
             refract_depth: int,
             inside: bool)
             -> Vec3 {
        if reflect_depth <= 0 || refract_depth <= 0 { return Vec3::zero() }
        let epsilon = ::std::f64::EPSILON * 10000.0;

        match ray.get_nearest_hit(scene) {
            Some(nearest_hit) => {
                let n = nearest_hit.n.unit();
                let i = (ray.direction.scale(-1.0)).unit();

                // Local lighting computation: surface shading, shadows
                let mut result = scene.lights.iter().fold(Vec3::zero(), |color_acc, light| {
                    let mut shadow = Vec3::zero();

                    if shadow_samples > 0 {
                        // Point light speedup
                        let shadow_sample_tries = if light.is_point() { 1 } else { shadow_samples };

                        // Take average shadow color after jittering/sampling light position
                        for _ in range(0, shadow_sample_tries) {
                            // L has to be a unit vector for t_max 1:1 correspondence to
                            // distance to light to work. Shadow feelers only search up
                            // until light source.
                            let sampled_light_position = light.position();
                            let shadow_l = (sampled_light_position - nearest_hit.position).unit();
                            let shadow_ray = Ray {origin: nearest_hit.position, direction: shadow_l};
                            let distance_to_light = (sampled_light_position - nearest_hit.position).len();

                            // Check against candidate primitives in scene for occlusion
                            // and multiply shadow color by occluders' shadow colors
                            shadow = shadow + scene.prims.iter().fold(Vec3::one(), |shadow_acc, prim| {
                                let occlusion = prim.intersects(&shadow_ray, epsilon, distance_to_light);
                                match occlusion {
                                    Some(occulusion) => {shadow_acc * occulusion.material.transmission()}
                                    None => shadow_acc
                                }
                            });
                        }

                        shadow = shadow.scale(1.0 / shadow_sample_tries as f64);
                    } else {
                        shadow = Vec3::one();
                    }

                    let l = (light.center() - nearest_hit.position).unit();

                    color_acc + light.color() * nearest_hit.material.sample(n, i, l) * shadow
                });

                // Global reflection
                if nearest_hit.material.is_reflective() {
                    let r = Vec3::reflect(&i, &n);
                    let reflect_ray = Ray {origin: nearest_hit.position, direction: r};
                    let reflection = Renderer::trace(scene, &reflect_ray, shadow_samples, reflect_depth - 1, refract_depth, inside);

                    result = result + nearest_hit.material.global_specular(&reflection);
                }

                // Global refraction
                if nearest_hit.material.is_refractive() {
                    let t = Vec3::refract(&i, &n, nearest_hit.material.ior(), inside);
                    let refract_ray = Ray {origin: nearest_hit.position + t.scale(epsilon), direction: t};
                    let refraction = Renderer::trace(scene, &refract_ray, shadow_samples, reflect_depth, refract_depth, !inside);

                    result = result + nearest_hit.material.global_transmissive(&refraction);
                }

                result
            }

            None => {scene.background}
        }
    }
}
<|endoftext|>


<commit_before>#![cfg(unix)]

extern crate rexpect;

use rexpect::spawn;
use rexpect::session::PtySession;
use rexpect::errors::*;

macro_rules! test {
    ($b: block) => {
        if ::std::env::var("GLUON_PATH").is_err() {
            ::std::env::set_var("GLUON_PATH", "..");
        }

        || -> Result<()> {
            $b
            Ok(())
        }().unwrap_or_else(|err| panic!("{}", err));
    };
}

struct REPL {
    session: PtySession,
    prompt: &'static str,
}

impl REPL {
    /// Defines the command, timeout, and prompt settings.
    /// Wraps a rexpect::session::PtySession. expecting the prompt after launch.
    fn new() -> Result<REPL> {
        let command = "../target/debug/gluon -i";
        let timeout: u64 = 10_000;
        let prompt: &'static str = "> ";

        let mut session = spawn(command, Some(timeout))?;
        session.exp_string(prompt)?;

        Ok(REPL { session, prompt })
    }

    /// Ensures certain lines are expected to reduce race conditions.
    /// If no ouput is expected or desired to be tested, pass it an Option::None,
    /// causing rexpect to wait for the next prompt.
    fn test(&mut self, send: &str, expect: Option<&str>) -> Result<()> {
        self.session.send_line(send)?;
        self.session.exp_string(send)?;

        if let Some(string) = expect {
            self.session.exp_string(string)?;
        }

        self.session.exp_string(self.prompt)?;
        Ok(())
    }

    fn quit(&mut self) -> Result<()> {
        let line: &'static str = ":q";
        self.session.send_line(line)?;
        self.session.exp_string(line)?;
        self.session.exp_eof()?;
        Ok(())
    }
}

#[test]
fn prompt() {
    test!({
        let mut repl = REPL::new()?;
    });
}

#[test]
fn quit() {
    test!({
        let mut repl = REPL::new()?;
        repl.quit()?;
    });
}

#[test]
fn hello_world() {
    test!({
        let mut repl = REPL::new()?;

        repl.test("let io = import! std.io", None)?;
        repl.test("io.println \"Hello world\"", Some("Hello world"))?;
    });
}

#[test]
fn expression_types() {
    test!({
        let mut repl = REPL::new()?;

        repl.test(":t 5", Some("Int"))?;
        // repl.test(":t 5 + 5", Some("Int -> Int"))?;
        repl.test(":t \"gluon\"", Some("String"))?;
    });
}

#[test]
fn names() {
    test!({
        let mut repl = REPL::new()?;

        repl.test(
            ":i std.prelude.show",
            Some("std.prelude.show: forall a . [std.prelude.Show a] -> a -> String"),
        )?;
    });
}

#[test]
fn comments() {
    test!({
        let mut repl = REPL::new()?;

        repl.test("1 + 2 // Calls the + function on 1 and 2", Some("3"))?;
        repl.test("1 + 2 /* Calls the + function on 1 and 2 */", Some("3"))?;
    });
}

#[test]
fn if_expressions() {
    test!({
        let mut repl = REPL::new()?;

        repl.test("if True then 1 else 0", Some("1"))?;
        repl.test("if False then 1 else 0", Some("0"))?;
    });
}

#[test]
fn records() {
    test!({
        let mut repl = REPL::new()?;

        repl.test("let record = { pi = 3.14, add1 = (+) 1.0 }", None)?;
        repl.test("record.pi", Some("3.14"))?;

        repl.test("let record_2 = {x = 1 .. record }", None)?;
        repl.test("record_2.x", Some("1"))?;
        repl.test("record_2.pi", Some("3.14"))?;
    });
}

#[test]
fn arrays() {
    test!({
        let mut repl = REPL::new()?;

        repl.test("let array = import! std.array", None)?;
        repl.test("array.len [1, 2, 3]", Some("3"))?;
    });
}
<commit_msg>Move repl test error handling to wrapper. Remove macro.<commit_after>#![cfg(unix)]

extern crate rexpect;

use rexpect::spawn;
use rexpect::session::PtySession;
use rexpect::errors::*;

struct REPL {
    session: PtySession,
    prompt: &'static str,
}

impl REPL {
    fn new() -> REPL {
        let repl = REPL::new_().unwrap_or_else(|err| panic!("{}", err));
        repl
    }

    /// Defines the command, timeout, and prompt settings.
    /// Wraps a rexpect::session::PtySession. expecting the prompt after launch.
    fn new_() -> Result<REPL> {
        if ::std::env::var("GLUON_PATH").is_err() {
            ::std::env::set_var("GLUON_PATH", "..");
        }

        let command = "../target/debug/gluon -i";
        let timeout: u64 = 10_000;

        let prompt: &'static str = "> ";

        let mut session = spawn(command, Some(timeout))?;
        session.exp_string(prompt)?;

        Ok(REPL { session, prompt })
    }

    fn test(&mut self, send: &str, expect: Option<&str>) {
        self.test_(send, expect)
            .unwrap_or_else(|err| panic!("{}", err));
    }

    /// Ensures certain lines are expected to reduce race conditions.
    /// If no ouput is expected or desired to be tested, pass it an Option::None,
    /// causing rexpect to wait for the next prompt.
    fn test_(&mut self, send: &str, expect: Option<&str>) -> Result<()> {
        self.session.send_line(send)?;
        self.session.exp_string(send)?;

        if let Some(string) = expect {
            self.session.exp_string(string)?;
        }

        self.session.exp_string(self.prompt)?;
        Ok(())
    }

    fn quit(&mut self) {
        self.quit_().unwrap_or_else(|err| panic!("{}", err));
    }

    fn quit_(&mut self) -> Result<()> {
        let line: &'static str = ":q";
        self.session.send_line(line)?;
        self.session.exp_string(line)?;
        self.session.exp_eof()?;
        Ok(())
    }
}

#[test]
fn prompt() {
    let _repl = REPL::new();
}

#[test]
fn quit() {
    let mut repl = REPL::new();
    repl.quit();
}

#[test]
fn hello_world() {
    let mut repl = REPL::new();

    repl.test("let io = import! std.io", None);
    repl.test("io.println \"Hello world\"", Some("Hello world"));
}

#[test]
fn expression_types() {
    let mut repl = REPL::new();

    repl.test(":t 5", Some("Int"));
    // repl.test(":t 5 + 5", Some("Int -> Int"));
    repl.test(":t \"gluon\"", Some("String"));
}

#[test]
fn names() {
    let mut repl = REPL::new();

    repl.test(
        ":i std.prelude.show",
        Some("std.prelude.show: forall a . [std.prelude.Show a] -> a -> String"),
    );
}

#[test]
fn comments() {
    let mut repl = REPL::new();

    repl.test("1 + 2 // Calls the + function on 1 and 2", Some("3"));
    repl.test("1 + 2 /* Calls the + function on 1 and 2 */", Some("3"));
}

#[test]
fn if_expressions() {
    let mut repl = REPL::new();

    repl.test("if True then 1 else 0", Some("1"));
    repl.test("if False then 1 else 0", Some("0"));
}

#[test]
fn records() {
    let mut repl = REPL::new();

    repl.test("let record = { pi = 3.14, add1 = (+) 1.0 }", None);
    repl.test("record.pi", Some("3.14"));

    repl.test("let record_2 = {x = 1 .. record }", None);
    repl.test("record_2.x", Some("1"));
    repl.test("record_2.pi", Some("3.14"));
}

#[test]
fn arrays() {
    let mut repl = REPL::new();

    repl.test("let array = import! std.array", None);
    repl.test("array.len [1, 2, 3]", Some("3"));
}
<|endoftext|>