<commit_before>#![crate_name = "document"]

use std::collections::hashmap::HashMap;
use std::collections::hashmap::HashSet;

#[deriving(Show)]
pub struct Document {
    /// Storage for each maintained type
    elements: Vec<Element>,
    attributes: Vec<Attribute>,

    // Primary associations between nodes
    children: HashMap<Node, HashSet<Node>>, // Needs order!
    parents: HashMap<Node, Node>,

    // Associated attributes
    assigned_attributes: HashMap<Node, HashSet<Node>>,
}

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Node {
    ElementNode(uint),
    AttributeNode(uint),
}

impl Document {
    pub fn new() -> Document {
        Document {
            elements: Vec::new(),
            attributes: Vec::new(),
            children: HashMap::new(),
            parents: HashMap::new(),
            assigned_attributes: HashMap::new(),
        }
    }

    fn next_element_ref(& self) -> Node {
        ElementNode(self.elements.len())
    }

    fn next_attribute_ref(& self) -> Node {
        AttributeNode(self.attributes.len())
    }

    pub fn new_element(&mut self, name: &str) -> Node {
        let eref = self.next_element_ref();
        self.elements.push(Element {
            name: name.to_string(),
        });
        eref
    }

    fn new_attribute(&mut self, name: &str, value: &str) -> Node {
        let aref = self.next_attribute_ref();
        self.attributes.push(Attribute {
            name: name.to_string(),
            value: value.to_string(),
        });
        aref
    }

    pub fn element<'a>(&'a self, element: Node) -> &'a Element {
        match element {
            ElementNode(i) => &self.elements[i],
            _ => fail!("Not an element"),
        }
    }

    pub fn mut_element<'a>(&'a mut self, element: Node) -> &'a mut Element {
        match element {
            ElementNode(i) => self.elements.get_mut(i),
            _ => fail!("Not an element"),
        }
    }

    fn attribute<'a>(&'a self, attribute: Node) -> &'a Attribute {
        match attribute {
            AttributeNode(i) => &self.attributes[i],
            _ => fail!("Not an attribute"),
        }
    }

    fn mut_attribute<'a>(&'a mut self, attribute: Node) -> &'a mut Attribute {
        match attribute {
            AttributeNode(i) => self.attributes.get_mut(i),
            _ => fail!("Not an attribute"),
        }
    }

    fn attribute_for(&self, element: Node, name: &str) -> Option<Node> {
        match self.assigned_attributes.find(&element) {
            Some(ref attributes) => {
                let mut node_attrs = attributes.iter().map(|node| (node, self.attribute(*node)));
                match node_attrs.find(|&(_, attr)| attr.name.as_slice() == name) {
                    Some((node, _)) => Some(*node),
                    None => None,
                }
            },
            None => None,
        }
    }

    pub fn get_attribute(&self, element: Node, name: &str) -> Option<&str> {
        match self.attribute_for(element, name) {
            Some(aref) => Some(self.attribute(aref).value.as_slice()),
            None => None,
        }
    }

    pub fn set_attribute(&mut self, element: Node, name: &str, value: &str) -> Node {
        match self.attribute_for(element, name) {
            Some(aref) => {
                self.mut_attribute(aref).value = value.to_string();
                aref
            },
            None => {
                let aref = self.new_attribute(name, value);
                let assigned_attributes = self.assigned_attributes.find_or_insert(element, HashSet::new());
                assigned_attributes.insert(aref);
                aref
            },
        }
    }

    fn remove_parentage(&mut self, child: Node) {
        match self.parent(child) {
            Some(ref parent) => {
                match self.children.find_mut(parent) {
                    Some(children) => { children.remove(&child); },
                    None => {},
                }
            },
            None => {}
        }
    }

    pub fn append_child(&mut self, parent: Node, child: Node) {
        {
            let kids = self.children.find_or_insert(parent, HashSet::new());
            kids.insert(child);
        }

        self.remove_parentage(child);
        self.parents.insert(child, parent);
    }

    pub fn children(&self, parent: Node) -> Vec<Node> {
        match self.children.find(&parent) {
            Some(v) => v.iter().map(|r| r.clone()).collect(),
            None => vec![],
        }
    }

    pub fn parent(&self, child: Node) -> Option<Node> {
        self.parents.find_copy(&child)
    }
}

#[deriving(Show)]
pub struct Element {
    name: String,
}

impl Element {
    pub fn name(&self) -> &str {
        self.name.as_slice()
    }

    pub fn set_name(&mut self, name: &str) {
        self.name = name.to_string();
    }
}

#[deriving(Show)]
pub struct Attribute {
    name: String,
    value: String,
}

pub struct Text;
pub struct Comment;
pub struct Root;

#[test]
fn can_add_an_element_as_a_child() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let children = d.children(alpha);
    assert_eq!(1, children.len());

    let result = d.element(children[0]);
    assert_eq!(result.name(), "beta");
}

#[test]
fn children_know_their_parent() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let child = d.children(alpha)[0];
    let parent = d.parent(child).unwrap();

    let result = d.element(parent);
    assert_eq!(result.name(), "alpha");
}

#[test]
fn replacing_parent_updates_original_parent() {
    let mut d = Document::new();
    let parent1 = d.new_element("parent1");
    let parent2 = d.new_element("parent2");
    let child = d.new_element("child");

    d.append_child(parent1, child);
    d.append_child(parent2, child);

    assert!(d.children(parent1).is_empty());
    assert_eq!(1, d.children(parent2).len());
}

#[test]
fn can_rename_an_element() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    {
        let element = d.mut_element(alpha);
        element.set_name("beta");
    }

    let beta = d.element(alpha);
    assert_eq!(beta.name(), "beta");
}

#[test]
fn elements_have_attributes() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "world");
}

#[test]
fn attributes_can_be_reset() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    d.set_attribute(alpha, "hello", "universe");

    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "universe");
}
<commit_msg>Children are ordered<commit_after>#![crate_name = "document"]

use std::collections::hashmap::HashMap;
use std::collections::hashmap::HashSet;

#[deriving(Show)]
pub struct Document {
    /// Storage for each maintained type
    elements: Vec<Element>,
    attributes: Vec<Attribute>,

    // Primary associations between nodes
    children: HashMap<Node, Vec<Node>>,
    parents: HashMap<Node, Node>,

    // Associated attributes
    assigned_attributes: HashMap<Node, HashSet<Node>>,
}

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Node {
    ElementNode(uint),
    AttributeNode(uint),
}

impl Document {
    pub fn new() -> Document {
        Document {
            elements: Vec::new(),
            attributes: Vec::new(),
            children: HashMap::new(),
            parents: HashMap::new(),
            assigned_attributes: HashMap::new(),
        }
    }

    fn next_element_ref(& self) -> Node {
        ElementNode(self.elements.len())
    }

    fn next_attribute_ref(& self) -> Node {
        AttributeNode(self.attributes.len())
    }

    pub fn new_element(&mut self, name: &str) -> Node {
        let eref = self.next_element_ref();
        self.elements.push(Element {
            name: name.to_string(),
        });
        eref
    }

    fn new_attribute(&mut self, name: &str, value: &str) -> Node {
        let aref = self.next_attribute_ref();
        self.attributes.push(Attribute {
            name: name.to_string(),
            value: value.to_string(),
        });
        aref
    }

    pub fn element<'a>(&'a self, element: Node) -> &'a Element {
        match element {
            ElementNode(i) => &self.elements[i],
            _ => fail!("Not an element"),
        }
    }

    pub fn mut_element<'a>(&'a mut self, element: Node) -> &'a mut Element {
        match element {
            ElementNode(i) => self.elements.get_mut(i),
            _ => fail!("Not an element"),
        }
    }

    fn attribute<'a>(&'a self, attribute: Node) -> &'a Attribute {
        match attribute {
            AttributeNode(i) => &self.attributes[i],
            _ => fail!("Not an attribute"),
        }
    }

    fn mut_attribute<'a>(&'a mut self, attribute: Node) -> &'a mut Attribute {
        match attribute {
            AttributeNode(i) => self.attributes.get_mut(i),
            _ => fail!("Not an attribute"),
        }
    }

    fn attribute_for(&self, element: Node, name: &str) -> Option<Node> {
        match self.assigned_attributes.find(&element) {
            Some(ref attributes) => {
                let mut node_attrs = attributes.iter().map(|node| (node, self.attribute(*node)));
                match node_attrs.find(|&(_, attr)| attr.name.as_slice() == name) {
                    Some((node, _)) => Some(*node),
                    None => None,
                }
            },
            None => None,
        }
    }

    pub fn get_attribute(&self, element: Node, name: &str) -> Option<&str> {
        match self.attribute_for(element, name) {
            Some(aref) => Some(self.attribute(aref).value.as_slice()),
            None => None,
        }
    }

    pub fn set_attribute(&mut self, element: Node, name: &str, value: &str) -> Node {
        match self.attribute_for(element, name) {
            Some(aref) => {
                self.mut_attribute(aref).value = value.to_string();
                aref
            },
            None => {
                let aref = self.new_attribute(name, value);
                let assigned_attributes = self.assigned_attributes.find_or_insert(element, HashSet::new());
                assigned_attributes.insert(aref);
                aref
            },
        }
    }

    fn remove_parentage(&mut self, child: Node) {
        match self.parent(child) {
            Some(ref parent) => {
                match self.children.find_mut(parent) {
                    Some(children) => {
                        match children.as_slice().position_elem(&child) {
                            Some(idx) => { children.remove(idx); },
                            None => {},
                        }
                    },
                    None => {},
                }
            },
            None => {}
        }
    }

    pub fn append_child(&mut self, parent: Node, child: Node) {
        {
            let kids = self.children.find_or_insert(parent, Vec::new());
            kids.push(child);
        }

        self.remove_parentage(child);
        self.parents.insert(child, parent);
    }

    pub fn children(&self, parent: Node) -> Vec<Node> {
        match self.children.find(&parent) {
            Some(v) => v.iter().map(|r| r.clone()).collect(),
            None => vec![],
        }
    }

    pub fn parent(&self, child: Node) -> Option<Node> {
        self.parents.find_copy(&child)
    }
}

#[deriving(Show)]
pub struct Element {
    name: String,
}

impl Element {
    pub fn name(&self) -> &str {
        self.name.as_slice()
    }

    pub fn set_name(&mut self, name: &str) {
        self.name = name.to_string();
    }
}

#[deriving(Show)]
pub struct Attribute {
    name: String,
    value: String,
}

pub struct Text;
pub struct Comment;
pub struct Root;

#[test]
fn can_add_an_element_as_a_child() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let children = d.children(alpha);
    assert_eq!(1, children.len());

    let result = d.element(children[0]);
    assert_eq!(result.name(), "beta");
}

#[test]
fn children_are_ordered() {
    let mut d = Document::new();
    let greek = d.new_element("greek");
    let alpha = d.new_element("alpha");
    let omega = d.new_element("omega");

    d.append_child(greek, alpha);
    d.append_child(greek, omega);
    let children = d.children(greek);

    assert_eq!(2, children.len());
    assert_eq!(d.element(children[0]).name(), "alpha");
    assert_eq!(d.element(children[1]).name(), "omega");
}

#[test]
fn children_know_their_parent() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let child = d.children(alpha)[0];
    let parent = d.parent(child).unwrap();

    let result = d.element(parent);
    assert_eq!(result.name(), "alpha");
}

#[test]
fn replacing_parent_updates_original_parent() {
    let mut d = Document::new();
    let parent1 = d.new_element("parent1");
    let parent2 = d.new_element("parent2");
    let child = d.new_element("child");

    d.append_child(parent1, child);
    d.append_child(parent2, child);

    assert!(d.children(parent1).is_empty());
    assert_eq!(1, d.children(parent2).len());
}

#[test]
fn can_rename_an_element() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    {
        let element = d.mut_element(alpha);
        element.set_name("beta");
    }

    let beta = d.element(alpha);
    assert_eq!(beta.name(), "beta");
}

#[test]
fn elements_have_attributes() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "world");
}

#[test]
fn attributes_can_be_reset() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    d.set_attribute(alpha, "hello", "universe");

    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "universe");
}
<|endoftext|>


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

// Test that the type of `sum` falls back to `i32` here,
// and that the for loop desugaring doesn't inferfere with
// that.

fn main() {
    let mut sum = 0;
    for i in Vec::new() {
        sum += i;
    }
}
<commit_msg>get ci green<commit_after>// Copyright 2017 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.

// Test that the type of `sum` falls back to `i32` here,
// and that the for loop desugaring doesn't interfere with
// that.

// ignore-test

fn main() {
    let mut sum = 0;
    for i in Vec::new() {
        sum += i;
    }
}
<|endoftext|>


<commit_before>use std::{cmp, usize};
use slsr_core::puzzle::Side;
use slsr_core::geom::{CellId, Geom};

use {State, SolverResult};
use model::connect_map::ConnectMap;
use model::side_map::SideMap;

fn create_conn_graph(conn_map: &mut ConnectMap,
                     exclude_side: Side)
                     -> (Vec<CellId>, Vec<State<Side>>, Vec<Vec<usize>>) {
    let mut pts = vec![];
    let mut sides = vec![];
    for i in 0..conn_map.cell_len() {
        let p = CellId::new(i);
        let a = conn_map.get(p);
        if a.coord() != p || a.side() == State::Fixed(exclude_side) {
            continue;
        }
        pts.push(p);
        sides.push(a.side());
    }

    let mut verts = vec![None; conn_map.cell_len()];
    for (i, &p) in pts.iter().enumerate() {
        verts[p.id()] = Some(i);
    }

    let graph = pts.iter()
                   .map(|&p| {
                       conn_map.get(p)
                               .unknown_edge()
                               .iter()
                               .filter_map(|p2| verts[p2.id()])
                               .collect::<Vec<_>>()
                   })
                   .collect();

    (pts, sides, graph)
}

fn get_articulation(graph: &[Vec<usize>],
                    v: usize,
                    arts: &mut Vec<usize>,
                    gvisited: &mut [bool])
                    -> Vec<bool> {
    let mut visited = vec![false; graph.len()];
    let mut ord = vec![0; graph.len()];
    let mut low = vec![0; graph.len()];
    let mut ord_cnt = 0;
    unsafe {
        dfs(graph,
            v,
            usize::MAX,
            arts,
            gvisited,
            &mut visited,
            &mut ord,
            &mut low,
            &mut ord_cnt);
    }

    return visited;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  prev: usize,
                  arts: &mut Vec<usize>,
                  gvisited: &mut [bool],
                  visited: &mut [bool],
                  ord: &mut [usize],
                  low: &mut [usize],
                  ord_cnt: &mut usize) {
        debug_assert!(!visited[v]);

        *visited.get_unchecked_mut(v) = true;
        *gvisited.get_unchecked_mut(v) = true;

        let ord_v = *ord_cnt;
        *ord.get_unchecked_mut(v) = ord_v;
        *low.get_unchecked_mut(v) = ord_v;
        *ord_cnt += 1;

        let mut is_articulation = false;
        let mut num_child = 0;

        for &u in graph.get_unchecked(v) {
            if u == v {
                continue;
            }

            if !*visited.get_unchecked(u) {
                dfs(graph, u, v, arts, gvisited, visited, ord, low, ord_cnt);

                let low_u = *low.get_unchecked(u);
                num_child += 1;
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), low_u);
                if ord_v <= low_u {
                    is_articulation = true;
                }
            } else if u != prev {
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), *ord.get_unchecked(u));
            } else {
            }
        }

        if ord_v == 0 {
            is_articulation = num_child > 1;
        }
        if is_articulation {
            arts.push(v);
        }
    }
}

fn find_disconn_area(conn_map: &mut ConnectMap,
                     pts: &[CellId],
                     visited: &[bool])
                     -> SolverResult<Vec<usize>> {
    let mut disconn = vec![];
    let mut disconn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if !vis {
            disconn.push(u);
            disconn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if disconn.is_empty() {
        // All area is connected
        return Ok(vec![]);
    }
    if disconn_sum == 0 {
        // Disconnected components does not contain any edges. It is a hole in
        // the exclude_side area.
        return Ok(disconn);
    }

    let mut conn = vec![];
    let mut conn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if vis {
            conn.push(u);
            conn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if conn_sum == 0 {
        // Conencted area does not contain any edges. It is a hole in the
        // exclude_side area.
        return Ok(conn);
    }

    // Graph is splitted into more than two parts, but both parts contain edges.
    // This may be valid in some situation, so, return empty.
    Ok(vec![])
}

fn splits(graph: &[Vec<usize>], v: usize, sides: &[State<Side>], set_side: Side) -> bool {
    if graph.is_empty() {
        return false;
    }

    let mut contain_cnt = 0;
    let mut visited = vec![false; graph.len()];

    unsafe {
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked(u) {
                continue;
            }

            let mut contains = false;
            dfs(graph, u, &mut contains, &mut visited, sides, set_side);

            if contains {
                contain_cnt += 1;
                if contain_cnt > 1 {
                    return true;
                }
            }
        }
    }

    return false;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  contains: &mut bool,
                  visited: &mut [bool],
                  sides: &[State<Side>],
                  set_side: Side) {
        if *sides.get_unchecked(v) == State::Fixed(set_side) {
            *contains = true;

            *visited.get_unchecked_mut(v) = true;

            for &u in graph.get_unchecked(v) {
                if *visited.get_unchecked_mut(u) {
                    continue;
                }
                dfs_mark(graph, u, visited);
            }
            return;
        }

        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked_mut(u) {
                continue;
            }
            dfs(graph, u, contains, visited, sides, set_side);
        }
    }

    unsafe fn dfs_mark(graph: &[Vec<usize>], v: usize, visited: &mut [bool]) {
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked_mut(u) {
                continue;
            }
            dfs_mark(graph, u, visited);
        }
    }
}

pub fn run(side_map: &mut SideMap, conn_map: &mut ConnectMap) -> SolverResult<()> {
    try!(conn_map.sync(side_map));

    let sides = &[(Side::In, Side::Out), (Side::Out, Side::In)];

    for &(set_side, exclude_side) in sides {
        let (pts, sides, graph) = create_conn_graph(conn_map, exclude_side);

        let mut arts = vec![];
        let mut gvisited = vec![false; graph.len()];
        for v in 0..graph.len() {
            if gvisited[v] {
                continue;
            }

            let visited = get_articulation(&graph, v, &mut arts, &mut gvisited);

            if set_side == Side::Out || conn_map.sum_of_hint() != 0 {
                // If there is no edge in puzzle (sum_of_hint == 0) and set_side ==
                // Side::In, any disconnected area can be loop.
                let disconn = try!(find_disconn_area(conn_map, &pts, &visited));
                for v in disconn {
                    side_map.set_side(pts[v], exclude_side);
                }
            }
        }

        for v in arts {
            if sides[v] == State::Fixed(set_side) {
                continue;
            }

            if splits(&graph, v, &sides, set_side) {
                side_map.set_side(pts[v], set_side);
            }
        }
    }

    Ok(())
}
<commit_msg>solver: simplify splits implementaion<commit_after>use std::{cmp, usize};
use slsr_core::puzzle::Side;
use slsr_core::geom::{CellId, Geom};

use {State, SolverResult};
use model::connect_map::ConnectMap;
use model::side_map::SideMap;

fn create_conn_graph(conn_map: &mut ConnectMap,
                     exclude_side: Side)
                     -> (Vec<CellId>, Vec<State<Side>>, Vec<Vec<usize>>) {
    let mut pts = vec![];
    let mut sides = vec![];
    for i in 0..conn_map.cell_len() {
        let p = CellId::new(i);
        let a = conn_map.get(p);
        if a.coord() != p || a.side() == State::Fixed(exclude_side) {
            continue;
        }
        pts.push(p);
        sides.push(a.side());
    }

    let mut verts = vec![None; conn_map.cell_len()];
    for (i, &p) in pts.iter().enumerate() {
        verts[p.id()] = Some(i);
    }

    let graph = pts.iter()
                   .map(|&p| {
                       conn_map.get(p)
                               .unknown_edge()
                               .iter()
                               .filter_map(|p2| verts[p2.id()])
                               .collect::<Vec<_>>()
                   })
                   .collect();

    (pts, sides, graph)
}

fn get_articulation(graph: &[Vec<usize>],
                    v: usize,
                    arts: &mut Vec<usize>,
                    gvisited: &mut [bool])
                    -> Vec<bool> {
    let mut visited = vec![false; graph.len()];
    let mut ord = vec![0; graph.len()];
    let mut low = vec![0; graph.len()];
    let mut ord_cnt = 0;
    unsafe {
        dfs(graph,
            v,
            usize::MAX,
            arts,
            gvisited,
            &mut visited,
            &mut ord,
            &mut low,
            &mut ord_cnt);
    }

    return visited;

    unsafe fn dfs(graph: &[Vec<usize>],
                  v: usize,
                  prev: usize,
                  arts: &mut Vec<usize>,
                  gvisited: &mut [bool],
                  visited: &mut [bool],
                  ord: &mut [usize],
                  low: &mut [usize],
                  ord_cnt: &mut usize) {
        debug_assert!(!visited[v]);

        *visited.get_unchecked_mut(v) = true;
        *gvisited.get_unchecked_mut(v) = true;

        let ord_v = *ord_cnt;
        *ord.get_unchecked_mut(v) = ord_v;
        *low.get_unchecked_mut(v) = ord_v;
        *ord_cnt += 1;

        let mut is_articulation = false;
        let mut num_child = 0;

        for &u in graph.get_unchecked(v) {
            if u == v {
                continue;
            }

            if !*visited.get_unchecked(u) {
                dfs(graph, u, v, arts, gvisited, visited, ord, low, ord_cnt);

                let low_u = *low.get_unchecked(u);
                num_child += 1;
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), low_u);
                if ord_v <= low_u {
                    is_articulation = true;
                }
            } else if u != prev {
                *low.get_unchecked_mut(v) = cmp::min(*low.get_unchecked(v), *ord.get_unchecked(u));
            } else {
            }
        }

        if ord_v == 0 {
            is_articulation = num_child > 1;
        }
        if is_articulation {
            arts.push(v);
        }
    }
}

fn find_disconn_area(conn_map: &mut ConnectMap,
                     pts: &[CellId],
                     visited: &[bool])
                     -> SolverResult<Vec<usize>> {
    let mut disconn = vec![];
    let mut disconn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if !vis {
            disconn.push(u);
            disconn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if disconn.is_empty() {
        // All area is connected
        return Ok(vec![]);
    }
    if disconn_sum == 0 {
        // Disconnected components does not contain any edges. It is a hole in
        // the exclude_side area.
        return Ok(disconn);
    }

    let mut conn = vec![];
    let mut conn_sum = 0;
    for (u, &vis) in visited.iter().enumerate() {
        if vis {
            conn.push(u);
            conn_sum += conn_map.get(pts[u]).sum_of_hint();
        }
    }
    if conn_sum == 0 {
        // Conencted area does not contain any edges. It is a hole in the
        // exclude_side area.
        return Ok(conn);
    }

    // Graph is splitted into more than two parts, but both parts contain edges.
    // This may be valid in some situation, so, return empty.
    Ok(vec![])
}

fn splits(graph: &[Vec<usize>], v: usize, sides: &[State<Side>], set_side: Side) -> bool {
    let mut visited = vec![false; graph.len()];

    unsafe {
        *visited.get_unchecked_mut(v) = true;

        let mut hit = false;
        for u in 0..graph.len() {
            let side = *sides.get_unchecked(u);
            if side != State::Fixed(set_side) {
                continue;
            }
            if *visited.get_unchecked(u) {
                continue;
            }

            if hit {
                return true;
            }

            hit = true;
            visit(graph, u, &mut visited);
        }
    }

    return false;

    unsafe fn visit(graph: &[Vec<usize>], v: usize, visited: &mut [bool]) {
        *visited.get_unchecked_mut(v) = true;

        for &u in graph.get_unchecked(v) {
            if *visited.get_unchecked(u) {
                continue;
            }
            visit(graph, u, visited);
        }
    }
}

pub fn run(side_map: &mut SideMap, conn_map: &mut ConnectMap) -> SolverResult<()> {
    try!(conn_map.sync(side_map));

    let sides = &[(Side::In, Side::Out), (Side::Out, Side::In)];

    for &(set_side, exclude_side) in sides {
        let (pts, sides, graph) = create_conn_graph(conn_map, exclude_side);

        let mut arts = vec![];
        let mut gvisited = vec![false; graph.len()];
        for v in 0..graph.len() {
            if gvisited[v] {
                continue;
            }

            let visited = get_articulation(&graph, v, &mut arts, &mut gvisited);

            if set_side == Side::Out || conn_map.sum_of_hint() != 0 {
                // If there is no edge in puzzle (sum_of_hint == 0) and set_side ==
                // Side::In, any disconnected area can be loop.
                let disconn = try!(find_disconn_area(conn_map, &pts, &visited));
                for v in disconn {
                    side_map.set_side(pts[v], exclude_side);
                }
            }
        }

        for v in arts {
            if sides[v] == State::Fixed(set_side) {
                continue;
            }

            if splits(&graph, v, &sides, set_side) {
                side_map.set_side(pts[v], set_side);
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::net;
use std::path;
use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use quiche::packet;
use quiche::rand;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10000000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1000000,
    initial_max_stream_data_bidi_remote: 1000000,
    initial_max_stream_data_uni: 1000000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &'static str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Conn>> = HashMap::new();

    loop {
        let (len, src) = socket.recv_from(&mut buf).unwrap();
        debug!("Got {} bytes from {}", len, src);

        let buf = &mut buf[..len];

        let hdr = if packet::has_long_header(buf[0]) {
            packet::Header::decode_long(buf)
        } else {
            packet::Header::decode_short(buf, LOCAL_CONN_ID_LEN)
        };

        let hdr = match hdr {
            Ok(v) => v,

            Err(e) => {
                error!("Parsing packet header failed: {:?}", e);
                continue
            }
        };

        let conn = match connections.entry(src) {
            hash_map::Entry::Vacant(v) =>{
                if hdr.version != quiche::VERSION_DRAFT15 {
                    warn!("Doing version negotiation");

                    let len = packet::negotiate_version(&hdr, &mut out).unwrap();
                    let out = &out[..len];

                    socket.send_to(out, &src).unwrap();
                    continue;
                }

                if hdr.ty != packet::Type::Initial {
                    error!("Packet is not Initial");
                    continue;
                }

                let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                rand::rand_bytes(&mut scid[..]);

                let config = quiche::Config {
                    version: quiche::VERSION_DRAFT15,

                    local_conn_id: &scid,

                    local_transport_params: &TRANSPORT_PARAMS,

                    tls_server_name: args.get_str("--name"),
                    tls_certificate: args.get_str("--cert"),
                    tls_certificate_key: args.get_str("--key"),
                };

                debug!("New connection: dcid={} scid={} lcid={}",
                       hex_dump(&hdr.dcid),
                       hex_dump(&hdr.scid),
                       hex_dump(&scid));

                let conn = quiche::Conn::new(config, true).unwrap();

                v.insert(conn)
            },

            hash_map::Entry::Occupied(v) => v.into_mut(),
        };

        let mut left = len;

        // Process potentially coalesced packets.
        while left > 0 {
            let read = match conn.recv(&mut buf[len - left..len]) {
                Ok(v)  => v,
                Err(e) => panic!("{} recv failed: {:?}", conn.trace_id(), e),
            };

            left -= read;

            debug!("{} read {} bytes", conn.trace_id(), read);
        }

        let streams: Vec<u64> = conn.stream_iter().collect();
        for s in streams {
            info!("{} stream {} is readable", conn.trace_id(), s);
            handle_stream(conn, s, &args);
        }

        loop {
            let write = match conn.send(&mut out) {
                Ok(v) => v,

                Err(quiche::Error::NothingToDo) => {
                    debug!("{} done writing", conn.trace_id());
                    break;
                },

                Err(e) => panic!("{} socket send failed: {:?}",
                                 conn.trace_id(), e),
            };

            // TODO: coalesce packets.
            socket.send_to(&out[..write], &src).unwrap();

            debug!("{} written {} bytes", conn.trace_id(), write);
        }
    }
}

fn handle_stream(conn: &mut quiche::Conn, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,
        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    if &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            match c {
                path::Component::Normal(v) => path.push(v),
                _ => (),
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path()).unwrap_or(
            Vec::from(String::from("Not Found!"))
        );

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            panic!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<commit_msg>server: statically limit size of send flight until proper congestion control<commit_after>// Copyright (c) 2018, Alessandro Ghedini
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#[macro_use]
extern crate log;
extern crate docopt;
extern crate quiche;
extern crate env_logger;

use std::fs;
use std::net;
use std::path;
use std::collections::hash_map;
use std::collections::HashMap;

use docopt::Docopt;

use quiche::packet;
use quiche::rand;

const LOCAL_CONN_ID_LEN: usize = 16;

const TRANSPORT_PARAMS: quiche::TransportParams = quiche::TransportParams {
    idle_timeout: 30,
    initial_max_data: 10000000,
    initial_max_bidi_streams: 100,
    initial_max_uni_streams: 100,
    max_packet_size: 1500,
    ack_delay_exponent: 3,
    disable_migration: true,
    max_ack_delay: 25,
    initial_max_stream_data_bidi_local: 1000000,
    initial_max_stream_data_bidi_remote: 1000000,
    initial_max_stream_data_uni: 1000000,
    stateless_reset_token_present: true,
    stateless_reset_token: [0xba; 16],
};

const USAGE: &'static str = "Usage: server [options]

Options:
  -h --help         Show this screen.
  --listen <addr>   Listen on the given IP:port [default: 127.0.0.1:4433]
  --cert <file>     TLS certificate path [default: examples/cert.crt]
  --key <file>      TLS certificate key path [default: examples/cert.key]
  --root <dir>      Root directory [default: examples/root/]
  --name <str>      Name of the server [default: quic.tech]
";

fn main() {
    let mut buf = [0; TRANSPORT_PARAMS.max_packet_size as usize];
    let mut out = [0; TRANSPORT_PARAMS.max_packet_size as usize];

    env_logger::init();

    let args = Docopt::new(USAGE)
                      .and_then(|dopt| dopt.parse())
                      .unwrap_or_else(|e| e.exit());

    let socket = net::UdpSocket::bind(args.get_str("--listen")).unwrap();

    let mut connections: HashMap<net::SocketAddr, Box<quiche::Conn>> = HashMap::new();

    loop {
        let (len, src) = socket.recv_from(&mut buf).unwrap();
        debug!("Got {} bytes from {}", len, src);

        let buf = &mut buf[..len];

        let hdr = if packet::has_long_header(buf[0]) {
            packet::Header::decode_long(buf)
        } else {
            packet::Header::decode_short(buf, LOCAL_CONN_ID_LEN)
        };

        let hdr = match hdr {
            Ok(v) => v,

            Err(e) => {
                error!("Parsing packet header failed: {:?}", e);
                continue
            }
        };

        let conn = match connections.entry(src) {
            hash_map::Entry::Vacant(v) =>{
                if hdr.version != quiche::VERSION_DRAFT15 {
                    warn!("Doing version negotiation");

                    let len = packet::negotiate_version(&hdr, &mut out).unwrap();
                    let out = &out[..len];

                    socket.send_to(out, &src).unwrap();
                    continue;
                }

                if hdr.ty != packet::Type::Initial {
                    error!("Packet is not Initial");
                    continue;
                }

                let mut scid: [u8; LOCAL_CONN_ID_LEN] = [0; LOCAL_CONN_ID_LEN];
                rand::rand_bytes(&mut scid[..]);

                let config = quiche::Config {
                    version: quiche::VERSION_DRAFT15,

                    local_conn_id: &scid,

                    local_transport_params: &TRANSPORT_PARAMS,

                    tls_server_name: args.get_str("--name"),
                    tls_certificate: args.get_str("--cert"),
                    tls_certificate_key: args.get_str("--key"),
                };

                debug!("New connection: dcid={} scid={} lcid={}",
                       hex_dump(&hdr.dcid),
                       hex_dump(&hdr.scid),
                       hex_dump(&scid));

                let conn = quiche::Conn::new(config, true).unwrap();

                v.insert(conn)
            },

            hash_map::Entry::Occupied(v) => v.into_mut(),
        };

        let mut left = len;

        // Process potentially coalesced packets.
        while left > 0 {
            let read = match conn.recv(&mut buf[len - left..len]) {
                Ok(v)  => v,
                Err(e) => panic!("{} recv failed: {:?}", conn.trace_id(), e),
            };

            left -= read;

            debug!("{} read {} bytes", conn.trace_id(), read);
        }

        let streams: Vec<u64> = conn.stream_iter().collect();
        for s in streams {
            info!("{} stream {} is readable", conn.trace_id(), s);
            handle_stream(conn, s, &args);
        }

        let mut written = 0;
        while written < buf.len() {
            let write = match conn.send(&mut out) {
                Ok(v) => v,

                Err(quiche::Error::NothingToDo) => {
                    debug!("{} done writing", conn.trace_id());
                    break;
                },

                Err(e) => panic!("{} socket send failed: {:?}",
                                 conn.trace_id(), e),
            };

            // TODO: coalesce packets.
            socket.send_to(&out[..write], &src).unwrap();
            written += write;

            debug!("{} written {} bytes", conn.trace_id(), write);
        }
    }
}

fn handle_stream(conn: &mut quiche::Conn, stream: u64, args: &docopt::ArgvMap) {
    let stream_data = match conn.stream_recv(stream) {
        Ok(v) => v,
        Err(e) => panic!("{} stream recv failed {:?}",
                         conn.trace_id(), e),
    };

    if &stream_data[..4] == b"GET " {
        let uri = &stream_data[4..stream_data.len()];
        let uri = String::from_utf8(uri.to_vec()).unwrap();
        let uri = String::from(uri.lines().next().unwrap());
        let uri = path::Path::new(&uri);
        let mut path = path::PathBuf::from(args.get_str("--root"));

        for c in uri.components() {
            match c {
                path::Component::Normal(v) => path.push(v),
                _ => (),
            }
        }

        info!("{} got GET request for {:?} on stream {}",
              conn.trace_id(), path, stream);

        let data = fs::read(path.as_path()).unwrap_or(
            Vec::from(String::from("Not Found!"))
        );

        info!("{} sending response of size {} on stream {}",
              conn.trace_id(), data.len(), stream);

        if let Err(e) = conn.stream_send(stream, &data, true) {
            panic!("{} stream send failed {:?}", conn.trace_id(), e);
        }
    }
}

fn hex_dump(buf: &[u8]) -> String {
    let vec: Vec<String> = buf.iter()
                              .map(|b| format!("{:02x}", b))
                              .collect();

    vec.join("")
}
<|endoftext|>


<commit_before>extern crate tungstenite;

use std::thread::spawn;
use std::net::TcpListener;

use tungstenite::accept_hdr;
use tungstenite::handshake::server::Request;

fn main() {
    let server = TcpListener::bind("127.0.0.1:3012").unwrap();
    for stream in server.incoming() {
        spawn(move || {
            let callback = |req: &Request| {
                println!("Received a new ws handshake");
                println!("The request's path is: {}", req.path);
                println!("The request's headers are:");
                for &(ref header, _ /* value */) in req.headers.iter() {
                    println!("* {}", header);
                }

                // Let's add an additional header to our response to the client.
                let extra_headers = vec![
                    (String::from("MyCustomHeader"), String::from(":)")),
                    (String::from("SOME_TUNGSTENITE_HEADER"), String::from("header_value")),
                ];
                Ok(Some(extra_headers))
            };
            let mut websocket = accept_hdr(stream.unwrap(), callback).unwrap();

            loop {
                let msg = websocket.read_message().unwrap();
                if msg.is_binary() || msg.is_text() {
                    websocket.write_message(msg).unwrap();
                }
            }
        });
    }
}
<commit_msg>example: trivial: init logger in server example<commit_after>extern crate tungstenite;
extern crate env_logger;

use std::thread::spawn;
use std::net::TcpListener;

use tungstenite::accept_hdr;
use tungstenite::handshake::server::Request;

fn main() {
    env_logger::init();
    let server = TcpListener::bind("127.0.0.1:3012").unwrap();
    for stream in server.incoming() {
        spawn(move || {
            let callback = |req: &Request| {
                println!("Received a new ws handshake");
                println!("The request's path is: {}", req.path);
                println!("The request's headers are:");
                for &(ref header, _ /* value */) in req.headers.iter() {
                    println!("* {}", header);
                }

                // Let's add an additional header to our response to the client.
                let extra_headers = vec![
                    (String::from("MyCustomHeader"), String::from(":)")),
                    (String::from("SOME_TUNGSTENITE_HEADER"), String::from("header_value")),
                ];
                Ok(Some(extra_headers))
            };
            let mut websocket = accept_hdr(stream.unwrap(), callback).unwrap();

            loop {
                let msg = websocket.read_message().unwrap();
                if msg.is_binary() || msg.is_text() {
                    websocket.write_message(msg).unwrap();
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>extern crate isosurface;
extern crate ndarray;

use ndarray::Array;
use isosurface::marching_tetrahedra;

fn main() {
    let xs = Array::linspace(-0.5, 0.5, 3);
    let ys = Array::linspace(-0.5, 0.5, 3);
    let zs = Array::linspace(-0.5, 0.5, 3);

    let dim = (xs.len(), ys.len(), zs.len());

    let u = {
        let mut u = Array::from_elem(dim, 0.);

        for ((i, j, k), u) in u.indexed_iter_mut() {
            let (x, y, z) = (xs[i], ys[j], zs[k]);
            *u = x * x + y * y + z * z - 0.3;
        }
        u
    };

    println!("{}", u);

    let (verts, faces, normals) = marching_tetrahedra(u.as_slice().unwrap(), dim, 0.);

    println!("{:?}", verts);
    println!("{:?}", faces);
}
<commit_msg>Fix warning<commit_after>extern crate isosurface;
extern crate ndarray;

use ndarray::Array;
use isosurface::marching_tetrahedra;

fn main() {
    let xs = Array::linspace(-0.5, 0.5, 3);
    let ys = Array::linspace(-0.5, 0.5, 3);
    let zs = Array::linspace(-0.5, 0.5, 3);

    let dim = (xs.len(), ys.len(), zs.len());

    let u = {
        let mut u = Array::from_elem(dim, 0.);

        for ((i, j, k), u) in u.indexed_iter_mut() {
            let (x, y, z) = (xs[i], ys[j], zs[k]);
            *u = x * x + y * y + z * z - 0.3;
        }
        u
    };

    println!("{}", u);

    let (verts, faces, normals) = marching_tetrahedra(u.as_slice().unwrap(), dim, 0.);

    println!("{:?}", verts);
    println!("{:?}", faces);
    println!("{:?}", normals);
}
<|endoftext|>


<commit_before>use error::{Error,Result};
use html::HtmlRenderer;
use book::Book;
use number::Number;
use token::Token;
use templates::html;
use resource_handler::ResourceHandler;

use mustache;

use std::io::{Read,Write};
use std::fs;
use std::fs::File;
use std::path::Path;
use std::path::PathBuf;
use std::borrow::Cow;

/// Multiple files HTML renderer
///
/// Renders HTML in a given directory.
#[derive(Debug)]
pub struct HtmlDirRenderer<'a> {
    book: &'a Book,
    html: HtmlRenderer<'a>,
}

impl<'a> HtmlDirRenderer<'a> {
    /// Creates a new HtmlDirRenderer
    pub fn new(book: &'a Book) -> HtmlDirRenderer<'a> {
        let mut html = HtmlRenderer::new(book);
        html.handler.set_images_mapping(true);
        html.handler.set_base64(false);
        HtmlDirRenderer {
            book: book,
            html: html,
        }
    }

    /// Render a book
    pub fn render_book(&mut self) -> Result<()> {
        // Add internal files to resource handler
        for (i, filename) in self.book.filenames.iter().enumerate() {
            self.html.handler.add_link(filename.clone(), filenamer(i));
        }

        // Create the directory
        let dest_path = try!(self.book.options.get_path("output.html_dir"));
        match fs::metadata(&dest_path) {
            Ok(metadata) => if metadata.is_file() {
                return Err(Error::Render(format!("{} already exists and is not a directory", &dest_path)));
            } else if metadata.is_dir() {
                self.book.logger.warning(format!("{} already exists, deleting it", &dest_path));
                try!(fs::remove_dir_all(&dest_path)
                     .map_err(|e| Error::Render(format!("error deleting directory {}: {}", &dest_path, e))));
            },
            Err(_) => (),
        }
        try!(fs::DirBuilder::new()
             .recursive(true)
             .create(&dest_path)
             .map_err(|e| Error::Render(format!("could not create HTML directory {}:{}", &dest_path, e))));

        // Write CSS
        try!(self.write_css());
        // Write print.css
        try!(self.write_file("print.css",
                             &self.book.get_template("html.print_css").unwrap().as_bytes()));
        // Write index.html and chapter_xxx.html
        try!(self.write_html());
        // Write menu.svg
        try!(self.write_file("menu.svg", html::MENU_SVG));

        // Write all images (including cover)
        let images_path = PathBuf::from(&self.book.options.get_path("resources.base_path.images").unwrap());
        for (source, dest) in self.html.handler.images_mapping() {
            let mut f = try!(File::open(images_path.join(source)).map_err(|_| Error::FileNotFound(source.to_owned())));
            let mut content = vec!();
            try!(f.read_to_end(&mut content).map_err(|e| Error::Render(format!("error while reading image file {}: {}", source, e))));
            try!(self.write_file(dest, &content));
        }

        // Write additional files
        if let Ok(list) = self.book.options.get_paths_list("resources.files") {
            let files_path = self.book.options.get_path("resources.base_path.files").unwrap();
            let data_path = Path::new(self.book.options.get_relative_path("resources.out_path").unwrap());
            let list = try!(ResourceHandler::get_files(list, &files_path));
            for path in list {
                let abs_path = Path::new(&files_path).join(&path);
                let mut f = try!(File::open(&abs_path)
                                 .map_err(|_| Error::FileNotFound(abs_path.to_string_lossy().into_owned())));
                let mut content = vec!();
                try!(f.read_to_end(&mut content).map_err(|e| Error::Render(format!("error while reading resource file: {}", e))));
                try!(self.write_file(data_path.join(&path).to_str().unwrap(), &content));
            }
        }

        Ok(())
    }

    // Render each chapter and write them, and index.html too
    fn write_html(&mut self) -> Result<()> {
        let mut chapters = vec!();
        let mut titles = vec!();
        for (i, &(n, ref v)) in self.book.chapters.iter().enumerate() {
            self.html.filename = filenamer(i);
            // Todo: this part could be factorized between html, epub and html_dir
            self.html.current_hide = false;

            let book_numbering = self.book.options.get_i32("numbering").unwrap();
            match n {
                Number::Unnumbered => self.html.current_numbering = 0,
                Number::Default => self.html.current_numbering = book_numbering,
                Number::Specified(n) => {
                    self.html.current_numbering = book_numbering;
                    self.html.current_chapter[0] = n - 1;
                },
                Number::Hidden => {
                    self.html.current_numbering = 0;
                    self.html.current_hide = true;
                }
            }

            let mut title = String::new();
            for token in v {
                match *token {
                    Token::Header(1, ref vec) => {
                        if self.html.current_hide || self.html.current_numbering == 0 {
                            title = self.html.render_vec(vec);
                        } else {
                            title = try!(self.book.get_header(self.html.current_chapter[0] + 1,
                                                              &self.html.render_vec(vec)));
                        }
                        break;
                    },
                    _ => {
                        continue;
                    }
                }
            }
            titles.push(title);

            let chapter = self.html.render_html(v);
            chapters.push(chapter);
        }
        let toc = self.html.toc.render();

        for (i, content) in chapters.into_iter().enumerate() {
            let prev_chapter = if i > 0 {
                format!("

    << {}

",
                        filenamer(i-1),
                        titles[i-1])
            } else {
                String::new()
            };

            let next_chapter = if i < titles.len() - 1 {
                format!("

    {} »

",
                        filenamer(i+1),
                        titles[i+1])
            } else {
                String::new()
            };

            // Render each HTML document
            let data = self.book.get_mapbuilder("none")
                .insert_str("content", content)
                .insert_str("chapter_title", format!("{} – {}",
                                             self.book.options.get_str("title").unwrap(),
                                             titles[i]))
                .insert_str("toc", toc.clone())
                .insert_str("prev_chapter", prev_chapter)
                .insert_str("next_chapter", next_chapter)
                .insert_str("script", self.book.get_template("html_dir.script").unwrap())
                .insert_bool(self.book.options.get_str("lang").unwrap(), true)
                .build();
            let template = mustache::compile_str(try!(self.book.get_template("html_dir.chapter.html")).as_ref());
            let mut res = vec!();
            template.render_data(&mut res, &data);
            try!(self.write_file(&filenamer(i), &res));
        }

        let mut content = if let Ok(cover) = self.book.options.get_path("cover") {
            format!("

",
                    self.book.options.get_str("title").unwrap(),
                    self.html.handler.map_image(Cow::Owned(cover)).as_ref())
        } else {
            String::new()
        };
        if titles.len() > 1 {
            content.push_str(&format!("

    {} >>

",
                        filenamer(0),
                        titles[0]));
        }
        // Render index.html and write it too
        let data = self.book.get_mapbuilder("none")
            .insert_str("content", content)
            .insert_str("toc", toc.clone())
            .insert_str("script", self.book.get_template("html_dir.script").unwrap())
            .insert_bool(self.book.options.get_str("lang").unwrap(), true)
            .build();
        let template = mustache::compile_str(try!(self.book.get_template("html_dir.index.html")).as_ref());
        let mut res = vec!();
        template.render_data(&mut res, &data);
        try!(self.write_file("index.html", &res));

        Ok(())
    }

    // Render the CSS file and write it
    fn write_css(&self) -> Result<()> {
        // Render the CSS
        let template_css = mustache::compile_str(try!(self.book.get_template("html_dir.css")).as_ref());
        let data = self.book.get_mapbuilder("none")
            .insert_bool(self.book.options.get_str("lang").unwrap(), true)
            .build();
        let mut res:Vec<u8> = vec!();
        template_css.render_data(&mut res, &data);
        let css = String::from_utf8_lossy(&res);

        // Write it
        self.write_file("stylesheet.css", css.as_bytes())
    }

    // Write content to a file
    fn write_file(&self, file: &str, content: &[u8]) -> Result<()> {
        let dest_path = PathBuf::from(&self.book.options.get_path("output.html_dir").unwrap());
        if dest_path.starts_with("..") {
            panic!("html dir is asked to create a file outside of its directory, no way!");
        }
        let dest_file = dest_path.join(file);
        let dest_dir = dest_file.parent().unwrap();
        if !fs::metadata(dest_dir).is_ok() { // dir does not exist, create it
            try!(fs::DirBuilder::new()
                 .recursive(true)
                 .create(&dest_dir)
                 .map_err(|e| Error::Render(format!("could not create directory in {}:{}", dest_dir.display(), e))));
        }
        let mut f = try!(File::create(&dest_file)
                         .map_err(|e| Error::Render(format!("could not create file {}:{}", dest_file.display(), e))));
        f.write_all(content)
            .map_err(|e| Error::Render(format!("could not write to file {}:{}", dest_file.display(), e)))
    }
}

/// Generate a file name given an int
fn filenamer(i: usize) -> String {
    format!("chapter_{:03}.html", i)
}
<commit_msg>Fix prev/next chapter display in html_dir<commit_after>use error::{Error,Result};
use html::HtmlRenderer;
use book::Book;
use number::Number;
use token::Token;
use templates::html;
use resource_handler::ResourceHandler;

use mustache;

use std::io::{Read,Write};
use std::fs;
use std::fs::File;
use std::path::Path;
use std::path::PathBuf;
use std::borrow::Cow;

/// Multiple files HTML renderer
///
/// Renders HTML in a given directory.
#[derive(Debug)]
pub struct HtmlDirRenderer<'a> {
    book: &'a Book,
    html: HtmlRenderer<'a>,
}

impl<'a> HtmlDirRenderer<'a> {
    /// Creates a new HtmlDirRenderer
    pub fn new(book: &'a Book) -> HtmlDirRenderer<'a> {
        let mut html = HtmlRenderer::new(book);
        html.handler.set_images_mapping(true);
        html.handler.set_base64(false);
        HtmlDirRenderer {
            book: book,
            html: html,
        }
    }

    /// Render a book
    pub fn render_book(&mut self) -> Result<()> {
        // Add internal files to resource handler
        for (i, filename) in self.book.filenames.iter().enumerate() {
            self.html.handler.add_link(filename.clone(), filenamer(i));
        }

        // Create the directory
        let dest_path = try!(self.book.options.get_path("output.html_dir"));
        match fs::metadata(&dest_path) {
            Ok(metadata) => if metadata.is_file() {
                return Err(Error::Render(format!("{} already exists and is not a directory", &dest_path)));
            } else if metadata.is_dir() {
                self.book.logger.warning(format!("{} already exists, deleting it", &dest_path));
                try!(fs::remove_dir_all(&dest_path)
                     .map_err(|e| Error::Render(format!("error deleting directory {}: {}", &dest_path, e))));
            },
            Err(_) => (),
        }
        try!(fs::DirBuilder::new()
             .recursive(true)
             .create(&dest_path)
             .map_err(|e| Error::Render(format!("could not create HTML directory {}:{}", &dest_path, e))));

        // Write CSS
        try!(self.write_css());
        // Write print.css
        try!(self.write_file("print.css",
                             &self.book.get_template("html.print_css").unwrap().as_bytes()));
        // Write index.html and chapter_xxx.html
        try!(self.write_html());
        // Write menu.svg
        try!(self.write_file("menu.svg", html::MENU_SVG));

        // Write all images (including cover)
        let images_path = PathBuf::from(&self.book.options.get_path("resources.base_path.images").unwrap());
        for (source, dest) in self.html.handler.images_mapping() {
            let mut f = try!(File::open(images_path.join(source)).map_err(|_| Error::FileNotFound(source.to_owned())));
            let mut content = vec!();
            try!(f.read_to_end(&mut content).map_err(|e| Error::Render(format!("error while reading image file {}: {}", source, e))));
            try!(self.write_file(dest, &content));
        }

        // Write additional files
        if let Ok(list) = self.book.options.get_paths_list("resources.files") {
            let files_path = self.book.options.get_path("resources.base_path.files").unwrap();
            let data_path = Path::new(self.book.options.get_relative_path("resources.out_path").unwrap());
            let list = try!(ResourceHandler::get_files(list, &files_path));
            for path in list {
                let abs_path = Path::new(&files_path).join(&path);
                let mut f = try!(File::open(&abs_path)
                                 .map_err(|_| Error::FileNotFound(abs_path.to_string_lossy().into_owned())));
                let mut content = vec!();
                try!(f.read_to_end(&mut content).map_err(|e| Error::Render(format!("error while reading resource file: {}", e))));
                try!(self.write_file(data_path.join(&path).to_str().unwrap(), &content));
            }
        }

        Ok(())
    }

    // Render each chapter and write them, and index.html too
    fn write_html(&mut self) -> Result<()> {
        let mut chapters = vec!();
        let mut titles = vec!();
        for (i, &(n, ref v)) in self.book.chapters.iter().enumerate() {
            self.html.filename = filenamer(i);
            // Todo: this part could be factorized between html, epub and html_dir
            self.html.current_hide = false;

            let book_numbering = self.book.options.get_i32("numbering").unwrap();
            match n {
                Number::Unnumbered => self.html.current_numbering = 0,
                Number::Default => self.html.current_numbering = book_numbering,
                Number::Specified(n) => {
                    self.html.current_numbering = book_numbering;
                    self.html.current_chapter[0] = n - 1;
                },
                Number::Hidden => {
                    self.html.current_numbering = 0;
                    self.html.current_hide = true;
                }
            }

            let mut title = String::new();
            for token in v {
                match *token {
                    Token::Header(1, ref vec) => {
                        if self.html.current_hide || self.html.current_numbering == 0 {
                            title = self.html.render_vec(vec);
                        } else {
                            title = try!(self.book.get_header(self.html.current_chapter[0] + 1,
                                                              &self.html.render_vec(vec)));
                        }
                        break;
                    },
                    _ => {
                        continue;
                    }
                }
            }
            titles.push(title);

            let chapter = self.html.render_html(v);
            chapters.push(chapter);
        }
        let toc = self.html.toc.render();

        for (i, content) in chapters.into_iter().enumerate() {
            let prev_chapter = if i > 0 {
                format!("

    « {}

",
                        filenamer(i-1),
                        titles[i-1])
            } else {
                String::new()
            };

            let next_chapter = if i < titles.len() - 1 {
                format!("

    {} »

",
                        filenamer(i+1),
                        titles[i+1])
            } else {
                String::new()
            };

            // Render each HTML document
            let data = self.book.get_mapbuilder("none")
                .insert_str("content", content)
                .insert_str("chapter_title", format!("{} – {}",
                                             self.book.options.get_str("title").unwrap(),
                                             titles[i]))
                .insert_str("toc", toc.clone())
                .insert_str("prev_chapter", prev_chapter)
                .insert_str("next_chapter", next_chapter)
                .insert_str("script", self.book.get_template("html_dir.script").unwrap())
                .insert_bool(self.book.options.get_str("lang").unwrap(), true)
                .build();
            let template = mustache::compile_str(try!(self.book.get_template("html_dir.chapter.html")).as_ref());
            let mut res = vec!();
            template.render_data(&mut res, &data);
            try!(self.write_file(&filenamer(i), &res));
        }

        let mut content = if let Ok(cover) = self.book.options.get_path("cover") {
            format!("

",
                    self.book.options.get_str("title").unwrap(),
                    self.html.handler.map_image(Cow::Owned(cover)).as_ref())
        } else {
            String::new()
        };
        if titles.len() > 1 {
            content.push_str(&format!("

    {} »

",
                        filenamer(0),
                        titles[0]));
        }
        // Render index.html and write it too
        let data = self.book.get_mapbuilder("none")
            .insert_str("content", content)
            .insert_str("toc", toc.clone())
            .insert_str("script", self.book.get_template("html_dir.script").unwrap())
            .insert_bool(self.book.options.get_str("lang").unwrap(), true)
            .build();
        let template = mustache::compile_str(try!(self.book.get_template("html_dir.index.html")).as_ref());
        let mut res = vec!();
        template.render_data(&mut res, &data);
        try!(self.write_file("index.html", &res));

        Ok(())
    }

    // Render the CSS file and write it
    fn write_css(&self) -> Result<()> {
        // Render the CSS
        let template_css = mustache::compile_str(try!(self.book.get_template("html_dir.css")).as_ref());
        let data = self.book.get_mapbuilder("none")
            .insert_bool(self.book.options.get_str("lang").unwrap(), true)
            .build();
        let mut res:Vec<u8> = vec!();
        template_css.render_data(&mut res, &data);
        let css = String::from_utf8_lossy(&res);

        // Write it
        self.write_file("stylesheet.css", css.as_bytes())
    }

    // Write content to a file
    fn write_file(&self, file: &str, content: &[u8]) -> Result<()> {
        let dest_path = PathBuf::from(&self.book.options.get_path("output.html_dir").unwrap());
        if dest_path.starts_with("..") {
            panic!("html dir is asked to create a file outside of its directory, no way!");
        }
        let dest_file = dest_path.join(file);
        let dest_dir = dest_file.parent().unwrap();
        if !fs::metadata(dest_dir).is_ok() { // dir does not exist, create it
            try!(fs::DirBuilder::new()
                 .recursive(true)
                 .create(&dest_dir)
                 .map_err(|e| Error::Render(format!("could not create directory in {}:{}", dest_dir.display(), e))));
        }
        let mut f = try!(File::create(&dest_file)
                         .map_err(|e| Error::Render(format!("could not create file {}:{}", dest_file.display(), e))));
        f.write_all(content)
            .map_err(|e| Error::Render(format!("could not write to file {}:{}", dest_file.display(), e)))
    }
}

/// Generate a file name given an int
fn filenamer(i: usize) -> String {
    format!("chapter_{:03}.html", i)
}
<|endoftext|>


<commit_before>// xfail-stage0
// xfail-stage1
// xfail-stage2

// Since the bogus configuration isn't defined main will just be
// parsed, but nothing further will be done with it
#[cfg(bogus)]
fn main() { fail }

fn main() {}<commit_msg>Un-XFAIL run-pass/conditional-compile.rs. Issue #489<commit_after>// xfail-stage0

// Since the bogus configuration isn't defined main will just be
// parsed, but nothing further will be done with it
#[cfg(bogus)]
fn main() { fail }

fn main() {}<|endoftext|>


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

// Test a foreign function that accepts and returns a struct
// by value.

// xfail-fast This works standalone on windows but not with check-fast. don't know why

#[deriving(Eq)]
struct TwoU64s {
    one: u64, two: u64
}

pub extern {
    pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
}

pub fn main() {
    unsafe {
        let x = TwoU64s {one: 22, two: 23};
        let y = rust_dbg_extern_identity_TwoU64s(x);
        assert!(x == y);
    }
}

<commit_msg>test: Add more comments about why extern-pass-TwoU64s is xfailed<commit_after>// Copyright 2012 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.

// Test a foreign function that accepts and returns a struct
// by value.

// xfail-fast This works standalone on windows but not with check-fast.
// possibly because there is another test that uses this extern fn but gives it
// a diferent signature

#[deriving(Eq)]
struct TwoU64s {
    one: u64, two: u64
}

pub extern {
    pub fn rust_dbg_extern_identity_TwoU64s(v: TwoU64s) -> TwoU64s;
}

pub fn main() {
    unsafe {
        let x = TwoU64s {one: 22, two: 23};
        let y = rust_dbg_extern_identity_TwoU64s(x);
        assert!(x == y);
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 Alexander Reece
//
// 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.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]

#[cfg(feature = "amqp0-pregen-parser")]
include!(concat!("../pregen/mod.rs"));
#[cfg(not(feature = "amqp0-pregen-parser"))]
include!(concat!(env!("OUT_DIR"), "/mod.rs"));

#[macro_use]
extern crate nom;
extern crate amqp0_primitives as primitives;

mod common;
mod field;

pub mod pool;

use nom::IResult;
use pool::ParserPool;

pub trait NomBytes<'a>: Sized {
    type Output: 'a;
    fn nom_bytes<'b, P> (&'a [u8], &'b mut P) -> IResult<&'a [u8], Self>
        where P: ParserPool;
}<commit_msg>[client] Disable use of generated code.<commit_after>// Copyright 2016 Alexander Reece
//
// 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.

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(not(feature="clippy"), allow(unknown_lints))]

#[macro_use]
extern crate nom;
extern crate amqp0_primitives as primitives;

mod common;
mod field;

pub mod pool;

use nom::IResult;
use pool::ParserPool;

pub trait NomBytes<'a>: Sized {
    type Output: 'a;
    fn nom_bytes<'b, P> (&'a [u8], &'b mut P) -> IResult<&'a [u8], Self>
        where P: ParserPool;
}<|endoftext|>


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

//! Collection types.
//!
//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.

#![crate_name = "collections"]
#![unstable(feature = "collections")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(core)]
#![feature(hash)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor, slicing_syntax)]
#![cfg_attr(test, feature(test))]
#![cfg_attr(test, allow(deprecated))] // rand

#![feature(no_std)]
#![no_std]

#[macro_use]
extern crate core;

extern crate unicode;
extern crate alloc;

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] #[macro_use] extern crate log;

pub use binary_heap::BinaryHeap;
pub use bitv::Bitv;
pub use bitv_set::BitvSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
pub use dlist::DList;
pub use enum_set::EnumSet;
pub use ring_buf::RingBuf;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;

// Needed for the vec! macro
pub use alloc::boxed;

#[macro_use]
mod macros;

pub mod binary_heap;
mod bit;
mod btree;
pub mod dlist;
pub mod enum_set;
pub mod fmt;
pub mod ring_buf;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_map;

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bitv {
    pub use bit::{Bitv, Iter};
}

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bitv_set {
    pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
    pub use bit::SetIter as Iter;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    pub use btree::map::*;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    pub use btree::set::*;
}

#[cfg(test)] mod bench;

// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
    // NOTE: remove after next snapshot
    #[cfg(stage0)] pub use core::clone;    // derive(Clone)
    #[cfg(stage0)] pub use core::cmp;      // derive(Eq, Ord, etc.)
    #[cfg(stage0)] pub use core::marker;   // derive(Copy)
    #[cfg(stage0)] pub use core::hash;     // derive(Hash)
    #[cfg(stage0)] pub use core::iter;
    #[cfg(stage0)] pub use core::fmt;      // necessary for panic!()
    #[cfg(stage0)] pub use core::option;   // necessary for panic!()

    pub use core::ops;      // RangeFull
}

#[cfg(test)]
mod prelude {
    // from core.
    pub use core::borrow::IntoCow;
    pub use core::clone::Clone;
    pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
    pub use core::cmp::Ordering::{Less, Equal, Greater};
    pub use core::iter::range;
    pub use core::iter::{FromIterator, Extend, IteratorExt};
    pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
    pub use core::iter::{ExactSizeIterator};
    pub use core::marker::{Copy, Send, Sized, Sync};
    pub use core::mem::drop;
    pub use core::ops::{Drop, Fn, FnMut, FnOnce};
    pub use core::option::Option;
    pub use core::option::Option::{Some, None};
    pub use core::ptr::PtrExt;
    pub use core::result::Result;
    pub use core::result::Result::{Ok, Err};

    // in core and collections (may differ).
    pub use slice::{AsSlice, SliceExt};
    pub use str::{Str, StrExt};

    // from other crates.
    pub use alloc::boxed::Box;
    pub use unicode::char::CharExt;

    // from collections.
    pub use slice::SliceConcatExt;
    pub use string::{String, ToString};
    pub use vec::Vec;
}

/// An endpoint of a range of keys.
pub enum Bound<T> {
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T),
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
}
<commit_msg>rollup merge of #22067: Gankro/collections-tests<commit_after>// Copyright 2013-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.

//! Collection types.
//!
//! See [std::collections](../std/collections) for a detailed discussion of collections in Rust.

#![crate_name = "collections"]
#![unstable(feature = "collections")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/",
       html_playground_url = "http://play.rust-lang.org/")]

#![feature(alloc)]
#![feature(box_syntax)]
#![feature(core)]
#![feature(hash)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor, slicing_syntax)]
#![cfg_attr(test, feature(rand, rustc_private, test))]
#![cfg_attr(test, allow(deprecated))] // rand

#![feature(no_std)]
#![no_std]

#[macro_use]
extern crate core;

extern crate unicode;
extern crate alloc;

#[cfg(test)] extern crate test;
#[cfg(test)] #[macro_use] extern crate std;
#[cfg(test)] #[macro_use] extern crate log;

pub use binary_heap::BinaryHeap;
pub use bitv::Bitv;
pub use bitv_set::BitvSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
pub use dlist::DList;
pub use enum_set::EnumSet;
pub use ring_buf::RingBuf;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;

// Needed for the vec! macro
pub use alloc::boxed;

#[macro_use]
mod macros;

pub mod binary_heap;
mod bit;
mod btree;
pub mod dlist;
pub mod enum_set;
pub mod fmt;
pub mod ring_buf;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_map;

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bitv {
    pub use bit::{Bitv, Iter};
}

#[unstable(feature = "collections",
           reason = "RFC 509")]
pub mod bitv_set {
    pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
    pub use bit::SetIter as Iter;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    pub use btree::map::*;
}

#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    pub use btree::set::*;
}

#[cfg(test)] mod bench;

// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

#[cfg(not(test))]
mod std {
    // NOTE: remove after next snapshot
    #[cfg(stage0)] pub use core::clone;    // derive(Clone)
    #[cfg(stage0)] pub use core::cmp;      // derive(Eq, Ord, etc.)
    #[cfg(stage0)] pub use core::marker;   // derive(Copy)
    #[cfg(stage0)] pub use core::hash;     // derive(Hash)
    #[cfg(stage0)] pub use core::iter;
    #[cfg(stage0)] pub use core::fmt;      // necessary for panic!()
    #[cfg(stage0)] pub use core::option;   // necessary for panic!()

    pub use core::ops;      // RangeFull
}

#[cfg(test)]
mod prelude {
    // from core.
    pub use core::borrow::IntoCow;
    pub use core::clone::Clone;
    pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
    pub use core::cmp::Ordering::{Less, Equal, Greater};
    pub use core::iter::range;
    pub use core::iter::{FromIterator, Extend, IteratorExt};
    pub use core::iter::{Iterator, DoubleEndedIterator, RandomAccessIterator};
    pub use core::iter::{ExactSizeIterator};
    pub use core::marker::{Copy, Send, Sized, Sync};
    pub use core::mem::drop;
    pub use core::ops::{Drop, Fn, FnMut, FnOnce};
    pub use core::option::Option;
    pub use core::option::Option::{Some, None};
    pub use core::ptr::PtrExt;
    pub use core::result::Result;
    pub use core::result::Result::{Ok, Err};

    // in core and collections (may differ).
    pub use slice::{AsSlice, SliceExt};
    pub use str::{Str, StrExt};

    // from other crates.
    pub use alloc::boxed::Box;
    pub use unicode::char::CharExt;

    // from collections.
    pub use slice::SliceConcatExt;
    pub use string::{String, ToString};
    pub use vec::Vec;
}

/// An endpoint of a range of keys.
pub enum Bound<T> {
    /// An inclusive bound.
    Included(T),
    /// An exclusive bound.
    Excluded(T),
    /// An infinite endpoint. Indicates that there is no bound in this direction.
    Unbounded,
}
<|endoftext|>


<commit_before>extern crate assert_cmd;
extern crate predicates;

use crate::cmdline::png_predicate;

use assert_cmd::Command;
use predicates::prelude::*;
use std::path::Path;

// What should be tested here?
// The goal is to test the code in rsvg-convert, not the entire library.
//
//  - all command-line options are accepted
//  - size and resolution of the output (should be sufficient to do that for PNG)
//  - limit on output size (32767 pixels)
//  - handling of SOURCE_DATA_EPOCH environment variable for PDF output
//  - handling of background color option
//  - error handling for export lookup ID
//  - error handling for invalid input

struct RsvgConvert {}

impl RsvgConvert {
    fn binary_location() -> &'static Path {
        match option_env!("LIBRSVG_BUILD_DIR") {
            Some(dir) => Path::new(dir),
            None => Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(),
        }
    }

    fn new() -> Command {
        let path = Self::binary_location().join("rsvg-convert");
        Command::new(path)
    }

    fn new_with_input(input: &Path) -> Command {
        let mut command = RsvgConvert::new();
        match command.pipe_stdin(input) {
            Ok(_) => command,
            Err(e) => panic!("Error opening file '{}': {}", input.display(), e),
        }
    }
}

#[test]
fn empty_input_yields_error() {
    let starts_with = predicate::str::starts_with("Error reading SVG");
    let ends_with = predicate::str::ends_with("Input file is too short");
    RsvgConvert::new()
        .assert()
        .failure()
        .stderr(starts_with.and(ends_with).trim());
}

#[test]
fn reads_from_stdin() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .assert()
        .success()
        .stdout(png_predicate::has_size(200, 100));
}

#[test]
fn width_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=300")
        .assert()
        .success()
        .stdout(png_predicate::has_size(300, 150));
}

#[test]
fn height_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--height=200")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 200));
}

#[test]
fn width_and_height_options() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=300")
        .arg("--height=200")
        .assert()
        .success()
        .stdout(png_predicate::has_size(300, 200));
}

#[test]
fn zoom_factor() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--zoom=0.8")
        .assert()
        .success()
        .stdout(png_predicate::has_size(160, 80));
}

// TODO: Is this a bug in rsvg-convert or the desired behavior ?
#[test]
fn zoom_factor_and_width_conflicts() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=400")
        .arg("--zoom=1.5")
        .assert()
        .failure()
        .stderr(predicate::str::ends_with("Could not render file stdin").trim());
}

#[test]
fn zoom_factor_and_larger_size() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=400")
        .arg("--height=200")
        .arg("--zoom=1.5")
        .assert()
        .success()
        .stdout(png_predicate::has_size(300, 150));
}

#[test]
fn zoom_factor_and_smaller_size() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=400")
        .arg("--height=200")
        .arg("--zoom=3.5")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 200));
}

#[test]
fn x_zoom_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--x-zoom=2")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 100));
}

#[test]
fn x_short_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("-x")
        .arg("2.0")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 100));
}

#[test]
fn y_zoom_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--y-zoom=2.0")
        .assert()
        .success()
        .stdout(png_predicate::has_size(200, 200));
}

#[test]
fn y_short_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("-y")
        .arg("2")
        .assert()
        .success()
        .stdout(png_predicate::has_size(200, 200));
}

#[test]
fn huge_zoom_yields_error() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    let starts_with =
        predicate::str::starts_with("The resulting image would be larger than 32767 pixels");
    let ends_with = predicate::str::ends_with("Please specify a smaller size.");
    RsvgConvert::new_with_input(input)
        .arg("--zoom=1000")
        .assert()
        .failure()
        .stderr(starts_with.and(ends_with).trim());
}

#[test]
fn version_option() {
    let out = predicate::str::starts_with("rsvg-convert version ");
    RsvgConvert::new()
        .arg("-v")
        .assert()
        .success()
        .stdout(out.clone());
    RsvgConvert::new()
        .arg("--version")
        .assert()
        .success()
        .stdout(out);
}

#[test]
fn help_option() {
    let out = predicate::str::starts_with("Usage:");
    RsvgConvert::new()
        .arg("-?")
        .assert()
        .success()
        .stdout(out.clone());
    RsvgConvert::new()
        .arg("--help")
        .assert()
        .success()
        .stdout(out);
}
<commit_msg>tests: List more rsvg-convert features that should be tested<commit_after>extern crate assert_cmd;
extern crate predicates;

use crate::cmdline::png_predicate;

use assert_cmd::Command;
use predicates::prelude::*;
use std::path::Path;

// What should be tested here?
// The goal is to test the code in rsvg-convert, not the entire library.
//
//  - all command-line options are accepted
//  - size and resolution of the output (should be sufficient to do that for PNG)
//  - limit on output size (32767 pixels)
//  - output formats (PNG, PDF, PS, EPS, SVG), okay to ignore XML and recording
//  - multi-page output (for PDF)
//  - handling of SOURCE_DATA_EPOCH environment variable for PDF output
//  - handling of background color option
//  - support for optional CSS stylesheet
//  - error handling for export lookup ID
//  - error handling for invalid input

struct RsvgConvert {}

impl RsvgConvert {
    fn binary_location() -> &'static Path {
        match option_env!("LIBRSVG_BUILD_DIR") {
            Some(dir) => Path::new(dir),
            None => Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(),
        }
    }

    fn new() -> Command {
        let path = Self::binary_location().join("rsvg-convert");
        Command::new(path)
    }

    fn new_with_input(input: &Path) -> Command {
        let mut command = RsvgConvert::new();
        match command.pipe_stdin(input) {
            Ok(_) => command,
            Err(e) => panic!("Error opening file '{}': {}", input.display(), e),
        }
    }
}

#[test]
fn empty_input_yields_error() {
    let starts_with = predicate::str::starts_with("Error reading SVG");
    let ends_with = predicate::str::ends_with("Input file is too short");
    RsvgConvert::new()
        .assert()
        .failure()
        .stderr(starts_with.and(ends_with).trim());
}

#[test]
fn reads_from_stdin() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .assert()
        .success()
        .stdout(png_predicate::has_size(200, 100));
}

#[test]
fn width_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=300")
        .assert()
        .success()
        .stdout(png_predicate::has_size(300, 150));
}

#[test]
fn height_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--height=200")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 200));
}

#[test]
fn width_and_height_options() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=300")
        .arg("--height=200")
        .assert()
        .success()
        .stdout(png_predicate::has_size(300, 200));
}

#[test]
fn zoom_factor() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--zoom=0.8")
        .assert()
        .success()
        .stdout(png_predicate::has_size(160, 80));
}

// TODO: Is this a bug in rsvg-convert or the desired behavior ?
#[test]
fn zoom_factor_and_width_conflicts() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=400")
        .arg("--zoom=1.5")
        .assert()
        .failure()
        .stderr(predicate::str::ends_with("Could not render file stdin").trim());
}

#[test]
fn zoom_factor_and_larger_size() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=400")
        .arg("--height=200")
        .arg("--zoom=1.5")
        .assert()
        .success()
        .stdout(png_predicate::has_size(300, 150));
}

#[test]
fn zoom_factor_and_smaller_size() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--width=400")
        .arg("--height=200")
        .arg("--zoom=3.5")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 200));
}

#[test]
fn x_zoom_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--x-zoom=2")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 100));
}

#[test]
fn x_short_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("-x")
        .arg("2.0")
        .assert()
        .success()
        .stdout(png_predicate::has_size(400, 100));
}

#[test]
fn y_zoom_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("--y-zoom=2.0")
        .assert()
        .success()
        .stdout(png_predicate::has_size(200, 200));
}

#[test]
fn y_short_option() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    RsvgConvert::new_with_input(input)
        .arg("-y")
        .arg("2")
        .assert()
        .success()
        .stdout(png_predicate::has_size(200, 200));
}

#[test]
fn huge_zoom_yields_error() {
    let input = Path::new("fixtures/dimensions/521-with-viewbox.svg");
    let starts_with =
        predicate::str::starts_with("The resulting image would be larger than 32767 pixels");
    let ends_with = predicate::str::ends_with("Please specify a smaller size.");
    RsvgConvert::new_with_input(input)
        .arg("--zoom=1000")
        .assert()
        .failure()
        .stderr(starts_with.and(ends_with).trim());
}

#[test]
fn version_option() {
    let out = predicate::str::starts_with("rsvg-convert version ");
    RsvgConvert::new()
        .arg("-v")
        .assert()
        .success()
        .stdout(out.clone());
    RsvgConvert::new()
        .arg("--version")
        .assert()
        .success()
        .stdout(out);
}

#[test]
fn help_option() {
    let out = predicate::str::starts_with("Usage:");
    RsvgConvert::new()
        .arg("-?")
        .assert()
        .success()
        .stdout(out.clone());
    RsvgConvert::new()
        .arg("--help")
        .assert()
        .success()
        .stdout(out);
}
<|endoftext|>