<commit_before>use super::start_server;
use graph;
use graph::*;
use graph::edge::*;
use graph::vertex::*;
use server::schema::{MorpheusSchema, SchemaError, EMPTY_FIELDS};
use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Value, Map};
use neb::ram::cell::Cell;
use env_logger;

#[test]
pub fn schemas() {
    let server = start_server(4001, "schemas");
    let graph = &server.graph;
    let mut edge_schema = MorpheusSchema::new(
        "test_edge_schema",
        None,
        &vec![Field::new(&"test_field", TypeId::U32 as u32, false, false, None)], false
    );
    assert_eq!(edge_schema.id, 0);
    assert!(
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new
            (
                graph::edge::EdgeType::Directed,
                false
            )).is_err());
    assert_eq!(edge_schema.id, 0);
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new(graph::edge::EdgeType::Directed, true)).unwrap();
    let mut vertex_schema = edge_schema.clone();
    vertex_schema.name = "test_vertex_schema".to_string();
    graph.new_vertex_group(&mut vertex_schema).unwrap();
    assert_eq!(edge_schema.id, 1);
    assert_eq!(vertex_schema.id, 2);
    let mut test_data = Map::new();
    test_data.insert("test_field", Value::U32(1));
    graph.new_vertex(&vertex_schema, test_data.clone()).unwrap();
    graph.new_vertex("test_edge_schema", test_data.clone()).is_err();
}

#[test]
pub fn relationship() {
    env_logger::init();
    let server = start_server(4002, "relationship");
    let graph = &server.graph;
    let mut people_schema = MorpheusSchema::new("people", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None)
    ], true);
    let mut movie_schema = MorpheusSchema::new("movie", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None),
        Field::new("year", TypeId::U32 as u32, false, false, None)
    ], true);
    let mut acted_in_schema = MorpheusSchema::new("acted-in", None, &vec! [
        Field::new("role", TypeId::String as u32, false, false, None)
    ], true);
    let mut spouse_schema = MorpheusSchema::new("spouse", None, &EMPTY_FIELDS, false);
    graph.new_vertex_group(&mut people_schema).unwrap();
    graph.new_vertex_group(&mut movie_schema).unwrap();
    graph.new_edge_group(
        &mut acted_in_schema,
        EdgeAttributes::new(
            EdgeType::Directed,
            true
        )
    ).unwrap();
    graph.new_edge_group(
        &mut spouse_schema,
        EdgeAttributes::new(
            EdgeType::Undirected,
            false
        )
    ).unwrap();
    assert_eq!(people_schema.id, 1);
    assert_eq!(movie_schema.id, 2);
    assert_eq!(acted_in_schema.id, 3);
    assert_eq!(spouse_schema.id, 4);
    let morgan_freeman_name = "Morgan Freeman";
    let batman_begins_name = "Batman Begins";
    let the_dark_knight_name = "The Dark Knight";
    let the_dark_knight_rises_name = "The Dark Knight Rises";
    let oblivion_name = "Oblivion";
    let jeanette_name = "Jeanette Adair Bradshaw";
    graph.new_vertex("people", data_map!{
        name: morgan_freeman_name, age: 80 as u8
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: batman_begins_name, year: 2005 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight_name, year: 2008 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight_rises_name, year: 2012 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: oblivion_name, year: 2010 as u32
    }).unwrap();
    graph.new_vertex("people", data_map!{
        name: jeanette_name
    }).unwrap();

    assert_eq!(
        graph.vertex_by_key("people", morgan_freeman_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        morgan_freeman_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", batman_begins_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        batman_begins_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", the_dark_knight_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        the_dark_knight_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", the_dark_knight_rises_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        the_dark_knight_rises_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", oblivion_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        oblivion_name
    );
    assert_eq!(
        graph.vertex_by_key("people", jeanette_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        jeanette_name
    );
    assert_eq!(
        graph.vertex_by_key("people", morgan_freeman_name)
            .unwrap().unwrap()["age"].U8().unwrap(),
        80u8
    );

    let morgan_freeman =
        graph.vertex_by_key("people", morgan_freeman_name)
        .unwrap().unwrap();

    let batman_begins =
        graph.vertex_by_key("movie", batman_begins_name)
        .unwrap().unwrap();

    let the_dark_knight =
        graph.vertex_by_key("movie", the_dark_knight_name)
            .unwrap().unwrap();

    let the_dark_knight_rises =
        graph.vertex_by_key("movie", the_dark_knight_rises_name)
        .unwrap().unwrap();

    let oblivion =
        graph.vertex_by_key("movie", oblivion_name)
            .unwrap().unwrap();
    let jeanette =
        graph.vertex_by_key("people", jeanette_name)
            .unwrap().unwrap();

    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 0
    );

    let batman_edge = graph.link(&morgan_freeman, "acted-in", &batman_begins, Some(&data_map!{
        role: "Lucius Fox", works_for: "Bruce Wayne"
    })).unwrap().unwrap();
    graph.link(&morgan_freeman, "acted-in", &the_dark_knight, Some(&data_map!{
        role: "Lucius Fox"
    })).unwrap().unwrap();
    graph.link(&morgan_freeman, "acted-in", &the_dark_knight_rises, Some(&data_map!{
        role: "Lucius Fox"
    })).unwrap().unwrap();

    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 3);

    let should_error = graph.link(&morgan_freeman, "acted-in", &oblivion, Some(&data_map!{
        // missing required field should fail
    })).err().unwrap();
    {
        let neighbourhoods_should_have = 3;
        let morgan_acted_in = graph.neighbourhoods(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap();
        if morgan_acted_in.len() != neighbourhoods_should_have {
            panic!("Assertion failed. Wrong neighbourhood number {:?}", &morgan_acted_in);
        }
        assert_eq!(
            graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(),
            neighbourhoods_should_have);
    }

    graph.link(&morgan_freeman, "acted-in", &oblivion, Some(&data_map!{
        role: "Beech"
    })).unwrap().unwrap();
    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 4);
    assert_eq!(
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 0);
    graph.link(&morgan_freeman, "spouse", &jeanette, Some(&data_map!{
        role: "Sister"
    })).unwrap().err().unwrap();
    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 4);
    assert_eq!(
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 0);
    println!("MF Link Jeanette {:?}", graph.link(&morgan_freeman, "spouse", &jeanette, None));
    println!("MF spouse {:?}", graph.neighbourhoods(&morgan_freeman, "spouse", EdgeDirection::Outbound).unwrap().unwrap());
    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 4);
    assert_eq!(
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 1);
}

<commit_msg>refine test<commit_after>use super::start_server;
use graph;
use graph::*;
use graph::edge::*;
use graph::vertex::*;
use server::schema::{MorpheusSchema, SchemaError, EMPTY_FIELDS};
use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Value, Map};
use neb::ram::cell::Cell;
use env_logger;

#[test]
pub fn schemas() {
    let server = start_server(4001, "schemas");
    let graph = &server.graph;
    let mut edge_schema = MorpheusSchema::new(
        "test_edge_schema",
        None,
        &vec![Field::new(&"test_field", TypeId::U32 as u32, false, false, None)], false
    );
    assert_eq!(edge_schema.id, 0);
    assert!(
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new
            (
                graph::edge::EdgeType::Directed,
                false
            )).is_err());
    assert_eq!(edge_schema.id, 0);
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new(graph::edge::EdgeType::Directed, true)).unwrap();
    let mut vertex_schema = edge_schema.clone();
    vertex_schema.name = "test_vertex_schema".to_string();
    graph.new_vertex_group(&mut vertex_schema).unwrap();
    assert_eq!(edge_schema.id, 1);
    assert_eq!(vertex_schema.id, 2);
    let mut test_data = Map::new();
    test_data.insert("test_field", Value::U32(1));
    graph.new_vertex(&vertex_schema, test_data.clone()).unwrap();
    graph.new_vertex("test_edge_schema", test_data.clone()).is_err();
}

#[test]
pub fn relationship() {
    env_logger::init();
    let server = start_server(4002, "relationship");
    let graph = &server.graph;
    let mut people_schema = MorpheusSchema::new("people", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None)
    ], true);
    let mut movie_schema = MorpheusSchema::new("movie", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None),
        Field::new("year", TypeId::U32 as u32, false, false, None)
    ], true);
    let mut acted_in_schema = MorpheusSchema::new("acted-in", None, &vec! [
        Field::new("role", TypeId::String as u32, false, false, None)
    ], true);
    let mut spouse_schema = MorpheusSchema::new("spouse", None, &EMPTY_FIELDS, false);
    graph.new_vertex_group(&mut people_schema).unwrap();
    graph.new_vertex_group(&mut movie_schema).unwrap();
    graph.new_edge_group(
        &mut acted_in_schema,
        EdgeAttributes::new(
            EdgeType::Directed,
            true
        )
    ).unwrap();
    graph.new_edge_group(
        &mut spouse_schema,
        EdgeAttributes::new(
            EdgeType::Undirected,
            false
        )
    ).unwrap();
    assert_eq!(people_schema.id, 1);
    assert_eq!(movie_schema.id, 2);
    assert_eq!(acted_in_schema.id, 3);
    assert_eq!(spouse_schema.id, 4);
    let morgan_freeman_name = "Morgan Freeman";
    let batman_begins_name = "Batman Begins";
    let the_dark_knight_name = "The Dark Knight";
    let the_dark_knight_rises_name = "The Dark Knight Rises";
    let oblivion_name = "Oblivion";
    let jeanette_name = "Jeanette Adair Bradshaw";
    graph.new_vertex("people", data_map!{
        name: morgan_freeman_name, age: 80 as u8
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: batman_begins_name, year: 2005 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight_name, year: 2008 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight_rises_name, year: 2012 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: oblivion_name, year: 2010 as u32
    }).unwrap();
    graph.new_vertex("people", data_map!{
        name: jeanette_name
    }).unwrap();

    assert_eq!(
        graph.vertex_by_key("people", morgan_freeman_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        morgan_freeman_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", batman_begins_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        batman_begins_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", the_dark_knight_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        the_dark_knight_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", the_dark_knight_rises_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        the_dark_knight_rises_name
    );
    assert_eq!(
        graph.vertex_by_key("movie", oblivion_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        oblivion_name
    );
    assert_eq!(
        graph.vertex_by_key("people", jeanette_name)
            .unwrap().unwrap()["name"].String().unwrap(),
        jeanette_name
    );
    assert_eq!(
        graph.vertex_by_key("people", morgan_freeman_name)
            .unwrap().unwrap()["age"].U8().unwrap(),
        80u8
    );

    let morgan_freeman =
        graph.vertex_by_key("people", morgan_freeman_name)
        .unwrap().unwrap();

    let batman_begins =
        graph.vertex_by_key("movie", batman_begins_name)
        .unwrap().unwrap();

    let the_dark_knight =
        graph.vertex_by_key("movie", the_dark_knight_name)
            .unwrap().unwrap();

    let the_dark_knight_rises =
        graph.vertex_by_key("movie", the_dark_knight_rises_name)
        .unwrap().unwrap();

    let oblivion =
        graph.vertex_by_key("movie", oblivion_name)
            .unwrap().unwrap();
    let jeanette =
        graph.vertex_by_key("people", jeanette_name)
            .unwrap().unwrap();

    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 0
    );

    let batman_edge = graph.link(&morgan_freeman, "acted-in", &batman_begins, Some(&data_map!{
        role: "Lucius Fox", works_for: "Bruce Wayne"
    })).unwrap().unwrap();
    graph.link(&morgan_freeman, "acted-in", &the_dark_knight, Some(&data_map!{
        role: "Lucius Fox"
    })).unwrap().unwrap();
    graph.link(&morgan_freeman, "acted-in", &the_dark_knight_rises, Some(&data_map!{
        role: "Lucius Fox"
    })).unwrap().unwrap();

    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 3);

    let should_error = graph.link(&morgan_freeman, "acted-in", &oblivion, Some(&data_map!{
        // missing required field should fail
    })).err().unwrap();
    {
        let neighbourhoods_should_have = 3;
        let morgan_acted_in = graph.neighbourhoods(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap();
        if morgan_acted_in.len() != neighbourhoods_should_have {
            panic!("Assertion failed. Wrong neighbourhood number {:?}", &morgan_acted_in);
        }
        assert_eq!(
            graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(),
            neighbourhoods_should_have);
    }

    graph.link(&morgan_freeman, "acted-in", &oblivion, Some(&data_map!{
        role: "Beech"
    })).unwrap().unwrap();
    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 4);
    assert_eq!(
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 0);
    graph.link(&morgan_freeman, "spouse", &jeanette, Some(&data_map!{
        role: "Sister"
    })).unwrap().err().unwrap();
    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 4);
    assert_eq!(
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 0);
    println!("MF Link Jeanette {:?}", graph.link(&morgan_freeman, "spouse", &jeanette, None));
    assert_eq!( // must use the right edge direction
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Outbound).unwrap().unwrap(), 0);
    assert_eq!(
        graph.degree(&morgan_freeman, "acted-in", EdgeDirection::Outbound).unwrap().unwrap(), 4);
    assert_eq!(
        graph.degree(&morgan_freeman, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 1);
    assert_eq!(
        graph.degree(&jeanette, "spouse", EdgeDirection::Undirected).unwrap().unwrap(), 1);
    println!(
        "Edge sample {:?}",
        graph.neighbourhoods(&jeanette, "spouse", EdgeDirection::Undirected).unwrap().unwrap());
}

<|endoftext|>


<commit_before>use super::start_server;
use graph;
use graph::*;
use graph::edge::*;
use graph::vertex::*;
use server::schema::{MorpheusSchema, SchemaError, EMPTY_FIELDS};
use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Value, Map};
use neb::ram::cell::Cell;

#[test]
pub fn schemas() {
    let server = start_server(4001, "schemas");
    let graph = &server.graph;
    let mut edge_schema = MorpheusSchema::new(
        "test_edge_schema",
        None,
        &vec![Field::new(&"test_field", TypeId::U32 as u32, false, false, None)], false
    );
    assert_eq!(edge_schema.id, 0);
    assert!(
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new
            (
                graph::edge::EdgeType::Directed,
                false
            )).is_err());
    assert_eq!(edge_schema.id, 0);
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new(graph::edge::EdgeType::Directed, true)).unwrap();
    let mut vertex_schema = edge_schema.clone();
    vertex_schema.name = "test_vertex_schema".to_string();
    graph.new_vertex_group(&mut vertex_schema).unwrap();
    assert_eq!(edge_schema.id, 1);
    assert_eq!(vertex_schema.id, 2);
    let mut test_data = Map::new();
    test_data.insert("test_field", Value::U32(1));
    graph.new_vertex(&vertex_schema, test_data.clone()).unwrap();
    graph.new_vertex("test_edge_schema", test_data.clone()).is_err();
}

#[test]
pub fn relationship() {
    let server = start_server(4002, "relationship");
    let graph = &server.graph;
    let mut people_schema = MorpheusSchema::new("people", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None)
    ], true);
    let mut movie_schema = MorpheusSchema::new("movie", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None),
        Field::new("year", TypeId::U32 as u32, false, false, None)
    ], true);
    let mut acted_in_schema = MorpheusSchema::new("acted-in", None, &vec! [
        Field::new("role", TypeId::String as u32, false, false, None)
    ], true);
    let mut spouse_schema = MorpheusSchema::new("spouse", None, &EMPTY_FIELDS, false);
    graph.new_vertex_group(&mut people_schema).unwrap();
    graph.new_vertex_group(&mut movie_schema).unwrap();
    graph.new_edge_group(
        &mut acted_in_schema,
        EdgeAttributes::new(
            EdgeType::Directed,
            true
        )
    ).unwrap();
    graph.new_edge_group(
        &mut spouse_schema,
        EdgeAttributes::new(
            EdgeType::Undirected,
            false
        )
    ).unwrap();
    assert_eq!(people_schema.id, 1);
    assert_eq!(movie_schema.id, 2);
    assert_eq!(acted_in_schema.id, 3);
    assert_eq!(spouse_schema.id, 4);
    let morgan_freeman = "Morgan Freeman";
    let batman_begins = "Batman Begins";
    let the_dark_knight = "The Dark Knight";
    let the_dark_knight_rises = "The Dark Knight Rises";
    let oblivion = "Oblivion";
    let jeanette = "Jeanette Adair Bradshaw";
    let morgan_vertex = graph.new_vertex("people", data_map!{
        name: morgan_freeman, age: 78 as u8
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: batman_begins, year: 2005 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight, year: 2008 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight_rises, year: 2012 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: oblivion, year: 2010 as u32
    }).unwrap();
    graph.new_vertex("people", data_map!{
        name: jeanette
    }).unwrap();

    graph.vertex_by_key("people", morgan_freeman).unwrap().unwrap();
}<commit_msg>check new vertices correctness<commit_after>use super::start_server;
use graph;
use graph::*;
use graph::edge::*;
use graph::vertex::*;
use server::schema::{MorpheusSchema, SchemaError, EMPTY_FIELDS};
use neb::ram::schema::Field;
use neb::ram::types::{TypeId, Value, Map};
use neb::ram::cell::Cell;

#[test]
pub fn schemas() {
    let server = start_server(4001, "schemas");
    let graph = &server.graph;
    let mut edge_schema = MorpheusSchema::new(
        "test_edge_schema",
        None,
        &vec![Field::new(&"test_field", TypeId::U32 as u32, false, false, None)], false
    );
    assert_eq!(edge_schema.id, 0);
    assert!(
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new
            (
                graph::edge::EdgeType::Directed,
                false
            )).is_err());
    assert_eq!(edge_schema.id, 0);
    graph.new_edge_group(
        &mut edge_schema,
        graph::edge::EdgeAttributes::new(graph::edge::EdgeType::Directed, true)).unwrap();
    let mut vertex_schema = edge_schema.clone();
    vertex_schema.name = "test_vertex_schema".to_string();
    graph.new_vertex_group(&mut vertex_schema).unwrap();
    assert_eq!(edge_schema.id, 1);
    assert_eq!(vertex_schema.id, 2);
    let mut test_data = Map::new();
    test_data.insert("test_field", Value::U32(1));
    graph.new_vertex(&vertex_schema, test_data.clone()).unwrap();
    graph.new_vertex("test_edge_schema", test_data.clone()).is_err();
}

#[test]
pub fn relationship() {
    let server = start_server(4002, "relationship");
    let graph = &server.graph;
    let mut people_schema = MorpheusSchema::new("people", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None)
    ], true);
    let mut movie_schema = MorpheusSchema::new("movie", Some(&vec!["name".to_string()]), &vec! [
        Field::new("name", TypeId::String as u32, false, false, None),
        Field::new("year", TypeId::U32 as u32, false, false, None)
    ], true);
    let mut acted_in_schema = MorpheusSchema::new("acted-in", None, &vec! [
        Field::new("role", TypeId::String as u32, false, false, None)
    ], true);
    let mut spouse_schema = MorpheusSchema::new("spouse", None, &EMPTY_FIELDS, false);
    graph.new_vertex_group(&mut people_schema).unwrap();
    graph.new_vertex_group(&mut movie_schema).unwrap();
    graph.new_edge_group(
        &mut acted_in_schema,
        EdgeAttributes::new(
            EdgeType::Directed,
            true
        )
    ).unwrap();
    graph.new_edge_group(
        &mut spouse_schema,
        EdgeAttributes::new(
            EdgeType::Undirected,
            false
        )
    ).unwrap();
    assert_eq!(people_schema.id, 1);
    assert_eq!(movie_schema.id, 2);
    assert_eq!(acted_in_schema.id, 3);
    assert_eq!(spouse_schema.id, 4);
    let morgan_freeman = "Morgan Freeman";
    let batman_begins = "Batman Begins";
    let the_dark_knight = "The Dark Knight";
    let the_dark_knight_rises = "The Dark Knight Rises";
    let oblivion = "Oblivion";
    let jeanette = "Jeanette Adair Bradshaw";
    let morgan_vertex = graph.new_vertex("people", data_map!{
        name: morgan_freeman, age: 78 as u8
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: batman_begins, year: 2005 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight, year: 2008 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: the_dark_knight_rises, year: 2012 as u32
    }).unwrap();
    graph.new_vertex("movie", data_map!{
        name: oblivion, year: 2010 as u32
    }).unwrap();
    graph.new_vertex("people", data_map!{
        name: jeanette
    }).unwrap();

    assert_eq!(
        graph.vertex_by_key("people", morgan_freeman)
            .unwrap().unwrap()["name"].String().unwrap(),
        morgan_freeman
    );
    assert_eq!(
        graph.vertex_by_key("movie", batman_begins)
            .unwrap().unwrap()["name"].String().unwrap(),
        batman_begins
    );
    assert_eq!(
        graph.vertex_by_key("movie", the_dark_knight)
            .unwrap().unwrap()["name"].String().unwrap(),
        the_dark_knight
    );
    assert_eq!(
        graph.vertex_by_key("movie", the_dark_knight_rises)
            .unwrap().unwrap()["name"].String().unwrap(),
        the_dark_knight_rises
    );
    assert_eq!(
        graph.vertex_by_key("movie", oblivion)
            .unwrap().unwrap()["name"].String().unwrap(),
        oblivion
    );
    assert_eq!(
        graph.vertex_by_key("people", jeanette)
            .unwrap().unwrap()["name"].String().unwrap(),
        jeanette
    );
    assert_eq!(
        graph.vertex_by_key("people", morgan_freeman)
            .unwrap().unwrap()["age"].U8().unwrap(),
        78u8
    );

}<|endoftext|>


<commit_before>use std::net::{UdpSocket, SocketAddr};
use std::time;
use tracker::{Announce, Result, ResultExt, Response, TrackerResponse, Event, Error, ErrorKind, dns};
use std::collections::HashMap;
use {CONFIG, PEER_ID, amy};
use util::bytes_to_addr;
use std::io::{self, Write, Read, Cursor};
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use slog::Logger;
use url::Url;
use rand::random;

// We're not going to bother with backoff, if the tracker/network aren't working now
// the torrent can just resend a request later.
const TIMEOUT_MS: u64 = 5000;
const RETRANS_MS: u64 = 500;
const MAGIC_NUM: u64 = 0x41727101980;

pub struct Handler {
    id: usize,
    sock: UdpSocket,
    connections: HashMap<usize, Connection>,
    transactions: HashMap<u32, usize>,
    conn_count: usize,
    l: Logger,
    buf: Vec<u8>,
}

struct Connection {
    torrent: usize,
    last_updated: time::Instant,
    last_retrans: time::Instant,
    state: State,
    announce: Announce,
}

enum State {
    ResolvingDNS { port: u16 },
    Connecting { addr: SocketAddr, data: [u8; 16] },
    Announcing { addr: SocketAddr, data: [u8; 98] },
}

impl Handler {
    pub fn new(reg: &amy::Registrar, l: Logger) -> io::Result<Handler> {
        let port = CONFIG.port;
        let sock = UdpSocket::bind(("0.0.0.0", port))?;
        sock.set_nonblocking(true)?;
        let id = reg.register(&sock, amy::Event::Read)?;
        Ok(Handler {
            id,
            sock,
            connections: HashMap::new(),
            transactions: HashMap::new(),
            l,
            conn_count: 0,
            buf: vec![0u8; 350],
        })
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn complete(&self) -> bool {
        self.connections.is_empty()
    }

    pub fn contains(&self, id: usize) -> bool {
        self.connections.contains_key(&id)
    }

    pub fn new_announce(
        &mut self,
        req: Announce,
        url: &Url,
        dns: &mut dns::Resolver,
    ) -> Result<()> {
        // TODO: Attempt to parse into an IP address first, then perform dns res
        debug!(self.l, "Received a new announce req for {:?}", url);
        let mut host = url.host_str().ok_or::<Error>(
            ErrorKind::InvalidRequest(
                format!("Tracker announce url has no host!"),
            ).into(),
        )?;
        let port = url.port().ok_or::<Error>(
            ErrorKind::InvalidRequest(
                format!("Tracker announce url has no port!"),
            ).into(),
        )?;

        let id = self.new_conn();
        self.connections.insert(
            id,
            Connection {
                torrent: req.id,
                last_updated: time::Instant::now(),
                last_retrans: time::Instant::now(),
                state: State::ResolvingDNS { port },
                announce: req,
            },
        );
        debug!(self.l, "Dispatching DNS req for {:?}, url: {:?}", id, host);
        dns.new_query(id, host);
        Ok(())
    }

    pub fn dns_resolved(&mut self, resp: dns::QueryResponse) -> Option<Response> {
        let id = resp.id;
        let mut success = false;
        debug!(self.l, "Received a DNS resp for {:?}", id);
        let resp = if let Some(mut conn) = self.connections.get_mut(&id) {
            match conn.state {
                State::ResolvingDNS { port } => {
                    conn.last_updated = time::Instant::now();
                    let tid = random::<u32>();
                    let mut data = [0u8; 16];
                    {
                        let mut connect_req = Cursor::new(&mut data[..]);
                        connect_req.write_u64::<BigEndian>(MAGIC_NUM).unwrap();
                        connect_req.write_u32::<BigEndian>(0).unwrap();
                        connect_req.write_u32::<BigEndian>(tid).unwrap();
                    }
                    match resp.res {
                        Ok(ip) => {
                            success = true;
                            conn.state = State::Connecting {
                                addr: SocketAddr::new(ip, port),
                                data,
                            };
                            self.transactions.insert(tid, id);
                            None
                        }
                        Err(e) => Some((conn.torrent, Err(e))),
                    }
                }
                _ => None,
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
            resp
        } else if success {
            self.send_data(id)
        } else {
            None
        }
    }

    pub fn readable(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        loop {
            match self.sock.recv_from(&mut self.buf[..]) {
                Ok((v, _)) => {
                    let action = (&self.buf[0..4]).read_u32::<BigEndian>().unwrap();
                    match action {
                        0 if v == 16 => {
                            if let Some(r) = self.process_connect() {
                                resps.push(r);
                            }
                        }
                        1 if v >= 20 => {
                            if let Some(r) = self.process_announce(v) {
                                resps.push(r);
                            }
                        }
                        3 if v >= 8 => {
                            if let Some(r) = self.process_error(v) {
                                resps.push(r);
                            }
                        }
                        _ => debug!(self.l, "Received invalid response from tracker!"),
                    }
                }
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        break;
                    } else {
                        // TODO: Handle this, could be some odd sort of failure
                        break;
                    }
                }
            }
        }
        resps
    }

    pub fn tick(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        let mut retrans = Vec::new();
        {
            let ref l = self.l;

            self.connections.retain(
                |id, conn| if conn.last_updated.elapsed() >
                    time::Duration::from_millis(
                        TIMEOUT_MS,
                    )
                {
                    resps.push((conn.torrent, Err(ErrorKind::Timeout.into())));
                    debug!(l, "Announce {:?} timed out", id);
                    false
                } else {
                    if conn.last_retrans.elapsed() > time::Duration::from_millis(RETRANS_MS) {
                        debug!(l, "Retransmiting req {:?}", id);
                        retrans.push(*id);
                    }
                    true
                },
            );

            let c = &self.connections;
            self.transactions.retain(|_, id| c.contains_key(id));
        }

        for id in retrans {
            if let Some(r) = self.send_data(id) {
                resps.push(r)
            }
        }
        resps
    }

    fn process_connect(&mut self) -> Option<Response> {
        let (transaction_id, connection_id) = {
            let mut connect_resp = Cursor::new(&self.buf[4..16]);
            let tid = connect_resp.read_u32::<BigEndian>().unwrap();
            let cid = connect_resp.read_u64::<BigEndian>().unwrap();
            (tid, cid)
        };

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let mut data = [0u8; 98];
        {
            let conn = match self.connections.get_mut(&id) {
                Some(conn) => conn,
                None => return None,
            };
            let addr = match conn.state {
                State::Connecting { addr, .. } => addr,
                _ => return None,
            };

            {
                let mut announce_req = Cursor::new(&mut data[..]);
                announce_req.write_u64::<BigEndian>(connection_id).unwrap();
                // announce action
                announce_req.write_u32::<BigEndian>(1).unwrap();

                let tid = random::<u32>();
                announce_req.write_u32::<BigEndian>(tid).unwrap();
                self.transactions.insert(tid, id);

                announce_req.write_all(&conn.announce.hash).unwrap();
                announce_req.write_all(&PEER_ID[..]).unwrap();
                announce_req
                    .write_u64::<BigEndian>(conn.announce.downloaded as u64)
                    .unwrap();
                announce_req
                    .write_u64::<BigEndian>(conn.announce.left as u64)
                    .unwrap();
                announce_req
                    .write_u64::<BigEndian>(conn.announce.uploaded as u64)
                    .unwrap();
                match conn.announce.event {
                    Some(Event::Started) => {
                        announce_req.write_u32::<BigEndian>(2).unwrap();
                    }
                    Some(Event::Stopped) => {
                        announce_req.write_u32::<BigEndian>(3).unwrap();
                    }
                    Some(Event::Completed) => {
                        announce_req.write_u32::<BigEndian>(1).unwrap();
                    }
                    None => {
                        announce_req.write_u32::<BigEndian>(0).unwrap();
                    }
                }

                // IP
                announce_req.write_u32::<BigEndian>(0).unwrap();
                // Key - TODO: randomly generate this
                announce_req.write_u32::<BigEndian>(0xF00BA).unwrap();
                // Num want
                let nw = conn.announce.num_want.map(|nw| nw as i32).unwrap_or(-1);
                announce_req.write_i32::<BigEndian>(nw).unwrap();
                // port
                announce_req.write_u16::<BigEndian>(conn.announce.port).unwrap();
            }
            conn.state = State::Announcing { addr, data };
            conn.last_updated = time::Instant::now();
        }
        self.send_data(id)
    }

    fn process_announce(&mut self, len: usize) -> Option<Response> {
        let mut announce_resp = Cursor::new(&self.buf[4..len]);
        let mut resp = TrackerResponse::empty();
        let transaction_id = announce_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        resp.interval = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.leechers = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.seeders = announce_resp.read_u32::<BigEndian>().unwrap();
        if len > 20 {
            let pos = announce_resp.position() as usize;
            for p in announce_resp.get_ref()[pos..].chunks(6) {
                resp.peers.push(bytes_to_addr(p));
            }
        }
        Some((conn.torrent, Ok(resp)))
    }

    fn process_error(&mut self, len: usize) -> Option<Response> {
        let mut s = String::new();
        let mut connect_resp = Cursor::new(&self.buf[4..len]);
        let transaction_id = connect_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        if connect_resp.read_to_string(&mut s).is_err() {
            Some((
                conn.torrent,
                Err(
                    ErrorKind::InvalidResponse(
                        "Tracker error response was invalid UTF8",
                    ).into(),
                ),
            ))
        } else {
            Some((conn.torrent, Err(ErrorKind::TrackerError(s).into())))
        }
    }

    fn new_conn(&mut self) -> usize {
        let c = self.conn_count;
        self.conn_count = self.conn_count.wrapping_add(1);
        c
    }

    fn send_data(&mut self, id: usize) -> Option<Response> {
        let tid;
        let res = {
            let conn = self.connections.get_mut(&id).unwrap();
            tid = conn.torrent;
            // If this actually blocks, something is really fucked(prob with the NIC)
            // and i dont think we need to care
            match conn.state {
                State::Connecting { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                State::Announcing { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                _ => Ok(0),
            }
        };

        match res {
            Err(e) => {
                self.connections.remove(&id);
                Some((tid, Err(e)))
            }
            Ok(_) => None,
        }
    }
}
<commit_msg>Remove unnecessary mut qualifier<commit_after>use std::net::{UdpSocket, SocketAddr};
use std::time;
use tracker::{Announce, Result, ResultExt, Response, TrackerResponse, Event, Error, ErrorKind, dns};
use std::collections::HashMap;
use {CONFIG, PEER_ID, amy};
use util::bytes_to_addr;
use std::io::{self, Write, Read, Cursor};
use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian};
use slog::Logger;
use url::Url;
use rand::random;

// We're not going to bother with backoff, if the tracker/network aren't working now
// the torrent can just resend a request later.
const TIMEOUT_MS: u64 = 5000;
const RETRANS_MS: u64 = 500;
const MAGIC_NUM: u64 = 0x41727101980;

pub struct Handler {
    id: usize,
    sock: UdpSocket,
    connections: HashMap<usize, Connection>,
    transactions: HashMap<u32, usize>,
    conn_count: usize,
    l: Logger,
    buf: Vec<u8>,
}

struct Connection {
    torrent: usize,
    last_updated: time::Instant,
    last_retrans: time::Instant,
    state: State,
    announce: Announce,
}

enum State {
    ResolvingDNS { port: u16 },
    Connecting { addr: SocketAddr, data: [u8; 16] },
    Announcing { addr: SocketAddr, data: [u8; 98] },
}

impl Handler {
    pub fn new(reg: &amy::Registrar, l: Logger) -> io::Result<Handler> {
        let port = CONFIG.port;
        let sock = UdpSocket::bind(("0.0.0.0", port))?;
        sock.set_nonblocking(true)?;
        let id = reg.register(&sock, amy::Event::Read)?;
        Ok(Handler {
            id,
            sock,
            connections: HashMap::new(),
            transactions: HashMap::new(),
            l,
            conn_count: 0,
            buf: vec![0u8; 350],
        })
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn complete(&self) -> bool {
        self.connections.is_empty()
    }

    pub fn contains(&self, id: usize) -> bool {
        self.connections.contains_key(&id)
    }

    pub fn new_announce(
        &mut self,
        req: Announce,
        url: &Url,
        dns: &mut dns::Resolver,
    ) -> Result<()> {
        // TODO: Attempt to parse into an IP address first, then perform dns res
        debug!(self.l, "Received a new announce req for {:?}", url);
        let host = url.host_str().ok_or::<Error>(
            ErrorKind::InvalidRequest(
                format!("Tracker announce url has no host!"),
            ).into(),
        )?;
        let port = url.port().ok_or::<Error>(
            ErrorKind::InvalidRequest(
                format!("Tracker announce url has no port!"),
            ).into(),
        )?;

        let id = self.new_conn();
        self.connections.insert(
            id,
            Connection {
                torrent: req.id,
                last_updated: time::Instant::now(),
                last_retrans: time::Instant::now(),
                state: State::ResolvingDNS { port },
                announce: req,
            },
        );
        debug!(self.l, "Dispatching DNS req for {:?}, url: {:?}", id, host);
        dns.new_query(id, host);
        Ok(())
    }

    pub fn dns_resolved(&mut self, resp: dns::QueryResponse) -> Option<Response> {
        let id = resp.id;
        let mut success = false;
        debug!(self.l, "Received a DNS resp for {:?}", id);
        let resp = if let Some(mut conn) = self.connections.get_mut(&id) {
            match conn.state {
                State::ResolvingDNS { port } => {
                    conn.last_updated = time::Instant::now();
                    let tid = random::<u32>();
                    let mut data = [0u8; 16];
                    {
                        let mut connect_req = Cursor::new(&mut data[..]);
                        connect_req.write_u64::<BigEndian>(MAGIC_NUM).unwrap();
                        connect_req.write_u32::<BigEndian>(0).unwrap();
                        connect_req.write_u32::<BigEndian>(tid).unwrap();
                    }
                    match resp.res {
                        Ok(ip) => {
                            success = true;
                            conn.state = State::Connecting {
                                addr: SocketAddr::new(ip, port),
                                data,
                            };
                            self.transactions.insert(tid, id);
                            None
                        }
                        Err(e) => Some((conn.torrent, Err(e))),
                    }
                }
                _ => None,
            }
        } else {
            None
        };
        if resp.is_some() {
            self.connections.remove(&id);
            resp
        } else if success {
            self.send_data(id)
        } else {
            None
        }
    }

    pub fn readable(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        loop {
            match self.sock.recv_from(&mut self.buf[..]) {
                Ok((v, _)) => {
                    let action = (&self.buf[0..4]).read_u32::<BigEndian>().unwrap();
                    match action {
                        0 if v == 16 => {
                            if let Some(r) = self.process_connect() {
                                resps.push(r);
                            }
                        }
                        1 if v >= 20 => {
                            if let Some(r) = self.process_announce(v) {
                                resps.push(r);
                            }
                        }
                        3 if v >= 8 => {
                            if let Some(r) = self.process_error(v) {
                                resps.push(r);
                            }
                        }
                        _ => debug!(self.l, "Received invalid response from tracker!"),
                    }
                }
                Err(e) => {
                    if e.kind() == io::ErrorKind::WouldBlock {
                        break;
                    } else {
                        // TODO: Handle this, could be some odd sort of failure
                        break;
                    }
                }
            }
        }
        resps
    }

    pub fn tick(&mut self) -> Vec<Response> {
        let mut resps = Vec::new();
        let mut retrans = Vec::new();
        {
            let ref l = self.l;

            self.connections.retain(
                |id, conn| if conn.last_updated.elapsed() >
                    time::Duration::from_millis(
                        TIMEOUT_MS,
                    )
                {
                    resps.push((conn.torrent, Err(ErrorKind::Timeout.into())));
                    debug!(l, "Announce {:?} timed out", id);
                    false
                } else {
                    if conn.last_retrans.elapsed() > time::Duration::from_millis(RETRANS_MS) {
                        debug!(l, "Retransmiting req {:?}", id);
                        retrans.push(*id);
                    }
                    true
                },
            );

            let c = &self.connections;
            self.transactions.retain(|_, id| c.contains_key(id));
        }

        for id in retrans {
            if let Some(r) = self.send_data(id) {
                resps.push(r)
            }
        }
        resps
    }

    fn process_connect(&mut self) -> Option<Response> {
        let (transaction_id, connection_id) = {
            let mut connect_resp = Cursor::new(&self.buf[4..16]);
            let tid = connect_resp.read_u32::<BigEndian>().unwrap();
            let cid = connect_resp.read_u64::<BigEndian>().unwrap();
            (tid, cid)
        };

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let mut data = [0u8; 98];
        {
            let conn = match self.connections.get_mut(&id) {
                Some(conn) => conn,
                None => return None,
            };
            let addr = match conn.state {
                State::Connecting { addr, .. } => addr,
                _ => return None,
            };

            {
                let mut announce_req = Cursor::new(&mut data[..]);
                announce_req.write_u64::<BigEndian>(connection_id).unwrap();
                // announce action
                announce_req.write_u32::<BigEndian>(1).unwrap();

                let tid = random::<u32>();
                announce_req.write_u32::<BigEndian>(tid).unwrap();
                self.transactions.insert(tid, id);

                announce_req.write_all(&conn.announce.hash).unwrap();
                announce_req.write_all(&PEER_ID[..]).unwrap();
                announce_req
                    .write_u64::<BigEndian>(conn.announce.downloaded as u64)
                    .unwrap();
                announce_req
                    .write_u64::<BigEndian>(conn.announce.left as u64)
                    .unwrap();
                announce_req
                    .write_u64::<BigEndian>(conn.announce.uploaded as u64)
                    .unwrap();
                match conn.announce.event {
                    Some(Event::Started) => {
                        announce_req.write_u32::<BigEndian>(2).unwrap();
                    }
                    Some(Event::Stopped) => {
                        announce_req.write_u32::<BigEndian>(3).unwrap();
                    }
                    Some(Event::Completed) => {
                        announce_req.write_u32::<BigEndian>(1).unwrap();
                    }
                    None => {
                        announce_req.write_u32::<BigEndian>(0).unwrap();
                    }
                }

                // IP
                announce_req.write_u32::<BigEndian>(0).unwrap();
                // Key - TODO: randomly generate this
                announce_req.write_u32::<BigEndian>(0xF00BA).unwrap();
                // Num want
                let nw = conn.announce.num_want.map(|nw| nw as i32).unwrap_or(-1);
                announce_req.write_i32::<BigEndian>(nw).unwrap();
                // port
                announce_req.write_u16::<BigEndian>(conn.announce.port).unwrap();
            }
            conn.state = State::Announcing { addr, data };
            conn.last_updated = time::Instant::now();
        }
        self.send_data(id)
    }

    fn process_announce(&mut self, len: usize) -> Option<Response> {
        let mut announce_resp = Cursor::new(&self.buf[4..len]);
        let mut resp = TrackerResponse::empty();
        let transaction_id = announce_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        resp.interval = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.leechers = announce_resp.read_u32::<BigEndian>().unwrap();
        resp.seeders = announce_resp.read_u32::<BigEndian>().unwrap();
        if len > 20 {
            let pos = announce_resp.position() as usize;
            for p in announce_resp.get_ref()[pos..].chunks(6) {
                resp.peers.push(bytes_to_addr(p));
            }
        }
        Some((conn.torrent, Ok(resp)))
    }

    fn process_error(&mut self, len: usize) -> Option<Response> {
        let mut s = String::new();
        let mut connect_resp = Cursor::new(&self.buf[4..len]);
        let transaction_id = connect_resp.read_u32::<BigEndian>().unwrap();

        let id = match self.transactions.remove(&transaction_id) {
            Some(id) => id,
            None => return None,
        };

        let conn = match self.connections.remove(&id) {
            Some(c) => c,
            None => return None,
        };

        if connect_resp.read_to_string(&mut s).is_err() {
            Some((
                conn.torrent,
                Err(
                    ErrorKind::InvalidResponse(
                        "Tracker error response was invalid UTF8",
                    ).into(),
                ),
            ))
        } else {
            Some((conn.torrent, Err(ErrorKind::TrackerError(s).into())))
        }
    }

    fn new_conn(&mut self) -> usize {
        let c = self.conn_count;
        self.conn_count = self.conn_count.wrapping_add(1);
        c
    }

    fn send_data(&mut self, id: usize) -> Option<Response> {
        let tid;
        let res = {
            let conn = self.connections.get_mut(&id).unwrap();
            tid = conn.torrent;
            // If this actually blocks, something is really fucked(prob with the NIC)
            // and i dont think we need to care
            match conn.state {
                State::Connecting { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                State::Announcing { ref addr, ref data } => {
                    conn.last_retrans = time::Instant::now();
                    self.sock.send_to(data, addr).chain_err(|| ErrorKind::IO)
                }
                _ => Ok(0),
            }
        };

        match res {
            Err(e) => {
                self.connections.remove(&id);
                Some((tid, Err(e)))
            }
            Ok(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>//! Validates the MIR to ensure that invariants are upheld.

use super::{MirPass, MirSource};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::{
    mir::{
        BasicBlock, Body, Location, Operand, Rvalue, Statement, StatementKind, Terminator,
        TerminatorKind,
    },
    ty::{self, fold::BottomUpFolder, ParamEnv, Ty, TyCtxt, TypeFoldable},
};

#[derive(Copy, Clone, Debug)]
enum EdgeKind {
    Unwind,
    Normal,
}

pub struct Validator {
    /// Describes at which point in the pipeline this validation is happening.
    pub when: String,
}

impl<'tcx> MirPass<'tcx> for Validator {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
        let param_env = tcx.param_env(source.def_id());
        TypeChecker { when: &self.when, source, body, tcx, param_env }.visit_body(body);
    }
}

struct TypeChecker<'a, 'tcx> {
    when: &'a str,
    source: MirSource<'tcx>,
    body: &'a Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ParamEnv<'tcx>,
}

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
    fn fail(&self, location: Location, msg: impl AsRef<str>) {
        let span = self.body.source_info(location).span;
        // We use `delay_span_bug` as we might see broken MIR when other errors have already
        // occurred.
        self.tcx.sess.diagnostic().delay_span_bug(
            span,
            &format!(
                "broken MIR in {:?} ({}) at {:?}:\n{}",
                self.source.instance,
                self.when,
                location,
                msg.as_ref()
            ),
        );
    }

    fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
        if let Some(bb) = self.body.basic_blocks().get(bb) {
            let src = self.body.basic_blocks().get(location.block).unwrap();
            match (src.is_cleanup, bb.is_cleanup, edge_kind) {
                // Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges
                (false, false, EdgeKind::Normal)
                // Non-cleanup blocks can jump to cleanup blocks along unwind edges
                | (false, true, EdgeKind::Unwind)
                // Cleanup blocks can jump to cleanup blocks along non-unwind edges
                | (true, true, EdgeKind::Normal) => {}
                // All other jumps are invalid
                _ => {
                    self.fail(
                        location,
                        format!(
                            "{:?} edge to {:?} violates unwind invariants (cleanup {:?} -> {:?})",
                            edge_kind,
                            bb,
                            src.is_cleanup,
                            bb.is_cleanup,
                        )
                    )
                }
            }
        } else {
            self.fail(location, format!("encountered jump to invalid basic block {:?}", bb))
        }
    }

    /// Check if src can be assigned into dest.
    /// This is not precise, it will accept some incorrect assignments.
    fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
        if src == dest {
            // Equal types, all is good.
            return true;
        }
        // Normalize projections and things like that.
        // FIXME: We need to reveal_all, as some optimizations change types in ways
        // that requires unfolding opaque types.
        let param_env = self.param_env.with_reveal_all();
        let src = self.tcx.normalize_erasing_regions(param_env, src);
        let dest = self.tcx.normalize_erasing_regions(param_env, dest);
        // It's worth checking equality again.
        if src == dest {
            return true;
        }

        // Type-changing assignments can happen when subtyping is used. While
        // all normal lifetimes are erased, higher-ranked types with their
        // late-bound lifetimes are still around and can lead to type
        // differences. Normalize both of them away.
        // Also see the related but slightly different post-monomorphization
        // method in `interpret/eval_context.rs`.
        let normalize = |ty: Ty<'tcx>| {
            ty.fold_with(&mut BottomUpFolder {
                tcx: self.tcx,
                ty_op: |ty| ty,
                // We just erase all late-bound lifetimes, but this is not fully correct (FIXME):
                // lifetimes in invariant positions could matter (e.g. through associated types).
                // But that just means we miss some potential incompatible types, it will not
                // lead to wrong errors.
                lt_op: |_| self.tcx.lifetimes.re_erased,
                // Evaluate consts.
                ct_op: |ct| ct.eval(self.tcx, param_env),
            })
        };
        normalize(src) == normalize(dest)
    }
}

impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
        // `Operand::Copy` is only supposed to be used with `Copy` types.
        if let Operand::Copy(place) = operand {
            let ty = place.ty(&self.body.local_decls, self.tcx).ty;
            let span = self.body.source_info(location).span;

            if !ty.is_copy_modulo_regions(self.tcx, self.param_env, span) {
                self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
            }
        }

        self.super_operand(operand, location);
    }

    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
        match &statement.kind {
            StatementKind::Assign(box (dest, rvalue)) => {
                // LHS and RHS of the assignment must have the same type.
                let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
                let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
                if !self.mir_assign_valid_types(right_ty, left_ty) {
                    self.fail(
                        location,
                        format!(
                            "encountered `Assign` statement with incompatible types:\n\
                            left-hand side has type: {}\n\
                            right-hand side has type: {}",
                            left_ty, right_ty,
                        ),
                    );
                }
                // The sides of an assignment must not alias. Currently this just checks whether the places
                // are identical.
                match rvalue {
                    Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) => {
                        if dest == src {
                            self.fail(
                                location,
                                "encountered `Assign` statement with overlapping memory",
                            );
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }

    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match &terminator.kind {
            TerminatorKind::Goto { target } => {
                self.check_edge(location, *target, EdgeKind::Normal);
            }
            TerminatorKind::SwitchInt { targets, values, .. } => {
                if targets.len() != values.len() + 1 {
                    self.fail(
                        location,
                        format!(
                            "encountered `SwitchInt` terminator with {} values, but {} targets (should be values+1)",
                            values.len(),
                            targets.len(),
                        ),
                    );
                }
                for target in targets {
                    self.check_edge(location, *target, EdgeKind::Normal);
                }
            }
            TerminatorKind::Drop { target, unwind, .. } => {
                self.check_edge(location, *target, EdgeKind::Normal);
                if let Some(unwind) = unwind {
                    self.check_edge(location, *unwind, EdgeKind::Unwind);
                }
            }
            TerminatorKind::DropAndReplace { target, unwind, .. } => {
                self.check_edge(location, *target, EdgeKind::Normal);
                if let Some(unwind) = unwind {
                    self.check_edge(location, *unwind, EdgeKind::Unwind);
                }
            }
            TerminatorKind::Call { func, destination, cleanup, .. } => {
                let func_ty = func.ty(&self.body.local_decls, self.tcx);
                match func_ty.kind {
                    ty::FnPtr(..) | ty::FnDef(..) => {}
                    _ => self.fail(
                        location,
                        format!("encountered non-callable type {} in `Call` terminator", func_ty),
                    ),
                }
                if let Some((_, target)) = destination {
                    self.check_edge(location, *target, EdgeKind::Normal);
                }
                if let Some(cleanup) = cleanup {
                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
                }
            }
            TerminatorKind::Assert { cond, target, cleanup, .. } => {
                let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
                if cond_ty != self.tcx.types.bool {
                    self.fail(
                        location,
                        format!(
                            "encountered non-boolean condition of type {} in `Assert` terminator",
                            cond_ty
                        ),
                    );
                }
                self.check_edge(location, *target, EdgeKind::Normal);
                if let Some(cleanup) = cleanup {
                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
                }
            }
            TerminatorKind::Yield { resume, drop, .. } => {
                self.check_edge(location, *resume, EdgeKind::Normal);
                if let Some(drop) = drop {
                    self.check_edge(location, *drop, EdgeKind::Normal);
                }
            }
            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
                self.check_edge(location, *real_target, EdgeKind::Normal);
                self.check_edge(location, *imaginary_target, EdgeKind::Normal);
            }
            TerminatorKind::FalseUnwind { real_target, unwind } => {
                self.check_edge(location, *real_target, EdgeKind::Normal);
                if let Some(unwind) = unwind {
                    self.check_edge(location, *unwind, EdgeKind::Unwind);
                }
            }
            TerminatorKind::InlineAsm { destination, .. } => {
                if let Some(destination) = destination {
                    self.check_edge(location, *destination, EdgeKind::Normal);
                }
            }
            // Nothing to validate for these.
            TerminatorKind::Resume
            | TerminatorKind::Abort
            | TerminatorKind::Return
            | TerminatorKind::Unreachable
            | TerminatorKind::GeneratorDrop => {}
        }
    }
}
<commit_msg>use a TypeRelation to compare the types<commit_after>//! Validates the MIR to ensure that invariants are upheld.

use super::{MirPass, MirSource};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::{
    mir::{
        BasicBlock, Body, Location, Operand, Rvalue, Statement, StatementKind, Terminator,
        TerminatorKind,
    },
    ty::{
        self,
        relate::{Relate, RelateResult, TypeRelation},
        ParamEnv, Ty, TyCtxt,
    },
};

#[derive(Copy, Clone, Debug)]
enum EdgeKind {
    Unwind,
    Normal,
}

pub struct Validator {
    /// Describes at which point in the pipeline this validation is happening.
    pub when: String,
}

impl<'tcx> MirPass<'tcx> for Validator {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
        let param_env = tcx.param_env(source.def_id());
        TypeChecker { when: &self.when, source, body, tcx, param_env }.visit_body(body);
    }
}

struct TypeChecker<'a, 'tcx> {
    when: &'a str,
    source: MirSource<'tcx>,
    body: &'a Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ParamEnv<'tcx>,
}

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
    fn fail(&self, location: Location, msg: impl AsRef<str>) {
        let span = self.body.source_info(location).span;
        // We use `delay_span_bug` as we might see broken MIR when other errors have already
        // occurred.
        self.tcx.sess.diagnostic().delay_span_bug(
            span,
            &format!(
                "broken MIR in {:?} ({}) at {:?}:\n{}",
                self.source.instance,
                self.when,
                location,
                msg.as_ref()
            ),
        );
    }

    fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
        if let Some(bb) = self.body.basic_blocks().get(bb) {
            let src = self.body.basic_blocks().get(location.block).unwrap();
            match (src.is_cleanup, bb.is_cleanup, edge_kind) {
                // Non-cleanup blocks can jump to non-cleanup blocks along non-unwind edges
                (false, false, EdgeKind::Normal)
                // Non-cleanup blocks can jump to cleanup blocks along unwind edges
                | (false, true, EdgeKind::Unwind)
                // Cleanup blocks can jump to cleanup blocks along non-unwind edges
                | (true, true, EdgeKind::Normal) => {}
                // All other jumps are invalid
                _ => {
                    self.fail(
                        location,
                        format!(
                            "{:?} edge to {:?} violates unwind invariants (cleanup {:?} -> {:?})",
                            edge_kind,
                            bb,
                            src.is_cleanup,
                            bb.is_cleanup,
                        )
                    )
                }
            }
        } else {
            self.fail(location, format!("encountered jump to invalid basic block {:?}", bb))
        }
    }

    /// Check if src can be assigned into dest.
    /// This is not precise, it will accept some incorrect assignments.
    fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
        if src == dest {
            // Equal types, all is good.
            return true;
        }
        // Normalize projections and things like that.
        // FIXME: We need to reveal_all, as some optimizations change types in ways
        // that requires unfolding opaque types.
        let param_env = self.param_env.with_reveal_all();
        let src = self.tcx.normalize_erasing_regions(param_env, src);
        let dest = self.tcx.normalize_erasing_regions(param_env, dest);
        // It's worth checking equality again.
        if src == dest {
            return true;
        }

        // Type-changing assignments can happen when subtyping is used. While
        // all normal lifetimes are erased, higher-ranked types with their
        // late-bound lifetimes are still around and can lead to type
        // differences. So we compare ignoring lifetimes.
        struct LifetimeIgnoreRelation<'tcx> {
            tcx: TyCtxt<'tcx>,
            param_env: ty::ParamEnv<'tcx>,
        }

        impl TypeRelation<'tcx> for LifetimeIgnoreRelation<'tcx> {
            fn tcx(&self) -> TyCtxt<'tcx> {
                self.tcx
            }

            fn param_env(&self) -> ty::ParamEnv<'tcx> {
                self.param_env
            }

            fn tag(&self) -> &'static str {
                "librustc_mir::transform::validate"
            }

            fn a_is_expected(&self) -> bool {
                true
            }

            fn relate_with_variance<T: Relate<'tcx>>(
                &mut self,
                _: ty::Variance,
                a: &T,
                b: &T,
            ) -> RelateResult<'tcx, T> {
                // Ignore variance, require types to be exactly the same.
                self.relate(a, b)
            }

            fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
                if a == b {
                    // Short-circuit.
                    return Ok(a);
                }
                ty::relate::super_relate_tys(self, a, b)
            }

            fn regions(
                &mut self,
                a: ty::Region<'tcx>,
                _b: ty::Region<'tcx>,
            ) -> RelateResult<'tcx, ty::Region<'tcx>> {
                // Ignore regions.
                Ok(a)
            }

            fn consts(
                &mut self,
                a: &'tcx ty::Const<'tcx>,
                b: &'tcx ty::Const<'tcx>,
            ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
                ty::relate::super_relate_consts(self, a, b)
            }

            fn binders<T>(
                &mut self,
                a: &ty::Binder<T>,
                b: &ty::Binder<T>,
            ) -> RelateResult<'tcx, ty::Binder<T>>
            where
                T: Relate<'tcx>,
            {
                self.relate(a.skip_binder(), b.skip_binder())?;
                Ok(a.clone())
            }
        }

        // Instantiate and run relation.
        let mut relator: LifetimeIgnoreRelation<'tcx> =
            LifetimeIgnoreRelation { tcx: self.tcx, param_env };
        relator.relate(&src, &dest).is_ok()
    }
}

impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
    fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
        // `Operand::Copy` is only supposed to be used with `Copy` types.
        if let Operand::Copy(place) = operand {
            let ty = place.ty(&self.body.local_decls, self.tcx).ty;
            let span = self.body.source_info(location).span;

            if !ty.is_copy_modulo_regions(self.tcx, self.param_env, span) {
                self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
            }
        }

        self.super_operand(operand, location);
    }

    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
        match &statement.kind {
            StatementKind::Assign(box (dest, rvalue)) => {
                // LHS and RHS of the assignment must have the same type.
                let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
                let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
                if !self.mir_assign_valid_types(right_ty, left_ty) {
                    self.fail(
                        location,
                        format!(
                            "encountered `Assign` statement with incompatible types:\n\
                            left-hand side has type: {}\n\
                            right-hand side has type: {}",
                            left_ty, right_ty,
                        ),
                    );
                }
                // The sides of an assignment must not alias. Currently this just checks whether the places
                // are identical.
                match rvalue {
                    Rvalue::Use(Operand::Copy(src) | Operand::Move(src)) => {
                        if dest == src {
                            self.fail(
                                location,
                                "encountered `Assign` statement with overlapping memory",
                            );
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }

    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match &terminator.kind {
            TerminatorKind::Goto { target } => {
                self.check_edge(location, *target, EdgeKind::Normal);
            }
            TerminatorKind::SwitchInt { targets, values, .. } => {
                if targets.len() != values.len() + 1 {
                    self.fail(
                        location,
                        format!(
                            "encountered `SwitchInt` terminator with {} values, but {} targets (should be values+1)",
                            values.len(),
                            targets.len(),
                        ),
                    );
                }
                for target in targets {
                    self.check_edge(location, *target, EdgeKind::Normal);
                }
            }
            TerminatorKind::Drop { target, unwind, .. } => {
                self.check_edge(location, *target, EdgeKind::Normal);
                if let Some(unwind) = unwind {
                    self.check_edge(location, *unwind, EdgeKind::Unwind);
                }
            }
            TerminatorKind::DropAndReplace { target, unwind, .. } => {
                self.check_edge(location, *target, EdgeKind::Normal);
                if let Some(unwind) = unwind {
                    self.check_edge(location, *unwind, EdgeKind::Unwind);
                }
            }
            TerminatorKind::Call { func, destination, cleanup, .. } => {
                let func_ty = func.ty(&self.body.local_decls, self.tcx);
                match func_ty.kind {
                    ty::FnPtr(..) | ty::FnDef(..) => {}
                    _ => self.fail(
                        location,
                        format!("encountered non-callable type {} in `Call` terminator", func_ty),
                    ),
                }
                if let Some((_, target)) = destination {
                    self.check_edge(location, *target, EdgeKind::Normal);
                }
                if let Some(cleanup) = cleanup {
                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
                }
            }
            TerminatorKind::Assert { cond, target, cleanup, .. } => {
                let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
                if cond_ty != self.tcx.types.bool {
                    self.fail(
                        location,
                        format!(
                            "encountered non-boolean condition of type {} in `Assert` terminator",
                            cond_ty
                        ),
                    );
                }
                self.check_edge(location, *target, EdgeKind::Normal);
                if let Some(cleanup) = cleanup {
                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
                }
            }
            TerminatorKind::Yield { resume, drop, .. } => {
                self.check_edge(location, *resume, EdgeKind::Normal);
                if let Some(drop) = drop {
                    self.check_edge(location, *drop, EdgeKind::Normal);
                }
            }
            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
                self.check_edge(location, *real_target, EdgeKind::Normal);
                self.check_edge(location, *imaginary_target, EdgeKind::Normal);
            }
            TerminatorKind::FalseUnwind { real_target, unwind } => {
                self.check_edge(location, *real_target, EdgeKind::Normal);
                if let Some(unwind) = unwind {
                    self.check_edge(location, *unwind, EdgeKind::Unwind);
                }
            }
            TerminatorKind::InlineAsm { destination, .. } => {
                if let Some(destination) = destination {
                    self.check_edge(location, *destination, EdgeKind::Normal);
                }
            }
            // Nothing to validate for these.
            TerminatorKind::Resume
            | TerminatorKind::Abort
            | TerminatorKind::Return
            | TerminatorKind::Unreachable
            | TerminatorKind::GeneratorDrop => {}
        }
    }
}
<|endoftext|>


<commit_before>use std::rand::Rng;
use std::rand;
use serialize::base64::ToBase64;
use serialize::base64;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

static WEBSOCKET_GUID: &'static [u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

#[derive(Show, PartialEq)]
pub struct Nonce(String);

impl Nonce {
    pub fn new() -> Nonce {
        Nonce::generate(&mut rand::task_rng())
    }

    fn generate(r: &mut Rng) -> Nonce {
        let mut nonce = [0u8, ..10];
        r.fill_bytes(nonce);
        Nonce(nonce.to_base64(base64::STANDARD))
    }

    pub fn encode(self) -> Nonce {
        let n = match self { Nonce(n) => n };
        let mut sha1 = Sha1::new();
        let mut result = [0u8, ..20];
        sha1.input(n.as_bytes());
        sha1.input(WEBSOCKET_GUID);
        sha1.result(result);
        Nonce(result.to_base64(base64::STANDARD))
    }
}

impl<'a> Str for Nonce {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self { Nonce(ref n) => n.as_slice() }
    }
}
<commit_msg>, .. -> ;<commit_after>use std::rand::Rng;
use std::rand;
use serialize::base64::ToBase64;
use serialize::base64;
use crypto::sha1::Sha1;
use crypto::digest::Digest;

static WEBSOCKET_GUID: &'static [u8] = b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

#[derive(Show, PartialEq)]
pub struct Nonce(String);

impl Nonce {
    pub fn new() -> Nonce {
        Nonce::generate(&mut rand::task_rng())
    }

    fn generate(r: &mut Rng) -> Nonce {
        let mut nonce = [0u8; 10];
        r.fill_bytes(nonce);
        Nonce(nonce.to_base64(base64::STANDARD))
    }

    pub fn encode(self) -> Nonce {
        let n = match self { Nonce(n) => n };
        let mut sha1 = Sha1::new();
        let mut result = [0u8; 20];
        sha1.input(n.as_bytes());
        sha1.input(WEBSOCKET_GUID);
        sha1.result(result);
        Nonce(result.to_base64(base64::STANDARD))
    }
}

impl<'a> Str for Nonce {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self { Nonce(ref n) => n.as_slice() }
    }
}
<|endoftext|>


<commit_before>use nickel::{Request, Response, MiddlewareResult};
use hyper::client::Client;
use common;
use nickel::status::StatusCode;
use hyper::header::Location;
use mustache::MapBuilder;
use mustache::Data;

pub fn id_handler<'a, D>(request: &mut Request<D>,
                         mut response: Response<'a, D>)
                         -> MiddlewareResult<'a, D> {
    let client = Client::new();
    let id_query = request.param("id").expect("Missing id");
    let url = &format!("https://api.tfl.gov.uk/StopPoint/{}", id_query);
    let obj = match common::json_for_request(client.get(url)) {
        Ok(val) => val,
        Err(val) => {
            response.set(StatusCode::BadGateway);
            return response.send(val);
        }
    };

    for line_group in obj["lineGroup"].members() {
        if line_group["stationAtcoCode"].as_str().unwrap_or("") == id_query ||
           line_group["naptanIdReference"].as_str().unwrap_or("") == id_query {
            response.set(Location(format!("/arrivals/{}", line_group["naptanIdReference"])))
                .set(StatusCode::PermanentRedirect);
            return response.send("");
        }
    }

    let data = MapBuilder::new()
        .insert_vec("stops", |vecbuilder| {
            let mut vecb = vecbuilder;
            for naptan_id in obj["lineGroup"]
                .members()
                .into_iter()
                .map(|x| x["naptanIdReference"].as_str().unwrap_or("")) {
                if naptan_id == "" {
                    continue;
                }
                let stopobj =
            match common::json_for_request(
                client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}/Arrivals",
                              naptan_id))) {
                Ok(val) => val,
                Err(_) => continue
            };
                let first_arrival = stopobj.members().nth(0);
                if let Some(val) = first_arrival {
                    vecb = vecb.push_map(|mapbuilder| {
                        let platform_name = val["platformName"].as_str().unwrap();
                        let stop_number = if platform_name == "null" {
                            "".to_string()
                        } else {
                            format!(" (Stop {})", platform_name)
                        };
                        mapbuilder.insert_str("id", naptan_id)
                            .insert_str("stopName", val["stationName"].as_str().unwrap())
                            .insert_str("stopNumber", stop_number)
                    })
                }
            }
            vecb
        })
        .insert_str("query", obj["commonName"].as_str().unwrap())
        .build();
    if let Data::Map(ref hash) = data {
        if let Data::VecVal(ref stops) = hash["stops"] {
            if stops.len() == 1 {
                if let Data::Map(ref stop) = stops[0] {
                    if let Data::StrVal(ref id) = stop["id"] {
                        response.set(Location(format!("/id/{}", id)))
                            .set(StatusCode::PermanentRedirect);
                        return response.send("");
                    }
                }
            }
        }
    }
    common::render_to_response(response, "resources/templates/multiple-id.mustache", &data)
}
<commit_msg>Don't auto-redirect to stations with null naptan refs<commit_after>use nickel::{Request, Response, MiddlewareResult};
use hyper::client::Client;
use common;
use nickel::status::StatusCode;
use hyper::header::Location;
use mustache::MapBuilder;
use mustache::Data;
use json::JsonValue;

pub fn id_handler<'a, D>(request: &mut Request<D>,
                         mut response: Response<'a, D>)
                         -> MiddlewareResult<'a, D> {
    let client = Client::new();
    let id_query = request.param("id").expect("Missing id");
    let url = &format!("https://api.tfl.gov.uk/StopPoint/{}", id_query);
    let obj = match common::json_for_request(client.get(url)) {
        Ok(val) => val,
        Err(val) => {
            response.set(StatusCode::BadGateway);
            return response.send(val);
        }
    };

    for line_group in obj["lineGroup"].members() {
        if line_group["naptanIdReference"] == JsonValue::Null {
            continue;
        }
        if line_group["stationAtcoCode"].as_str().unwrap_or("") == id_query ||
           line_group["naptanIdReference"].as_str().unwrap_or("") == id_query {
            response.set(Location(format!("/arrivals/{}", line_group["naptanIdReference"])))
                .set(StatusCode::PermanentRedirect);
            return response.send("");
        }
    }

    let data = MapBuilder::new()
        .insert_vec("stops", |vecbuilder| {
            let mut vecb = vecbuilder;
            for naptan_id in obj["lineGroup"]
                .members()
                .into_iter()
                .map(|x| x["naptanIdReference"].as_str().unwrap_or("")) {
                if naptan_id == "" {
                    continue;
                }
                let stopobj =
            match common::json_for_request(
                client.get(&format!("https://api.tfl.gov.uk/StopPoint/{}/Arrivals",
                              naptan_id))) {
                Ok(val) => val,
                Err(_) => continue
            };
                let first_arrival = stopobj.members().nth(0);
                if let Some(val) = first_arrival {
                    vecb = vecb.push_map(|mapbuilder| {
                        let platform_name = val["platformName"].as_str().unwrap();
                        let stop_number = if platform_name == "null" {
                            "".to_string()
                        } else {
                            format!(" (Stop {})", platform_name)
                        };
                        mapbuilder.insert_str("id", naptan_id)
                            .insert_str("stopName", val["stationName"].as_str().unwrap())
                            .insert_str("stopNumber", stop_number)
                    })
                }
            }
            vecb
        })
        .insert_str("query", obj["commonName"].as_str().unwrap())
        .build();
    if let Data::Map(ref hash) = data {
        if let Data::VecVal(ref stops) = hash["stops"] {
            if stops.len() == 1 {
                if let Data::Map(ref stop) = stops[0] {
                    if let Data::StrVal(ref id) = stop["id"] {
                        response.set(Location(format!("/id/{}", id)))
                            .set(StatusCode::PermanentRedirect);
                        return response.send("");
                    }
                }
            }
        }
    }
    common::render_to_response(response, "resources/templates/multiple-id.mustache", &data)
}
<|endoftext|>


<commit_before>extern crate ndarray;

use ndarray_ext::NdArray;
use tensor::Tensor;

pub type ComputeResult = Vec<Result<NdArray, ComputeError>>;

#[derive(Clone, Debug)]
pub enum ComputeError
{
    /// Computation finished correctly but delegates the result to its `to` th input.
    Delegate
    {
        to: usize
    },
    /// Could'nt compute output array because of bad inputs.
    BadInput(String),
    /// Computation finished correctly with no output
    NoOutput,
}

/// Operation trait. `Tensor` wraps trait-object of this.
pub trait Op
{
    /// Name of this op
    fn name(&self) -> &str;

    /// Actually runs this op.
    fn compute(&self, ctx: ::runtime::OpComputeContext) -> ComputeResult;

    /// Returns symbolic gradients for input nodes by use of output gradient etc.
    ///
    /// # Arguments
    ///
    /// * `gy` - Symbolic representation of the gradient of `compute`'s return value
    /// * `xs` - Symbolic representation of `compute::xs`
    /// * `y` - Symbolic representation of `compute`'s return value
    ///
    /// NOTE:
    /// The number of return values must match `xs.len()`.
    fn grad(&self, gy: &Tensor, xs: &[&Tensor], y: &Tensor) -> Vec<Option<Tensor>>;
}
<commit_msg>Add example of Op<commit_after>extern crate ndarray;

use ndarray_ext::NdArray;
use tensor::Tensor;

pub type ComputeResult = Vec<Result<NdArray, ComputeError>>;

#[derive(Clone, Debug)]
pub enum ComputeError
{
    /// Computation finished correctly but delegates the result to its `to` th input.
    Delegate
    {
        to: usize
    },
    /// Could'nt compute output array because of bad inputs.
    BadInput(String),
    /// Computation finished correctly with no output
    NoOutput,
}

/// Operation trait. `Tensor` wraps trait-object of this.
///
/// # Usage
///
/// ```
/// extern crate ndarray;
/// extern crate autograd as ag;
///
/// type NdArray = ndarray::Array<f32, ndarray::IxDyn>;
///
/// struct Sigmoid;
///
/// // Implements `Operation` trait for `Sigmoid`
/// impl ag::op::Op for Sigmoid {
///
///     fn name(&self) -> &str
///     {
///         "Sigmoid"
///     }
///
///     fn compute(&self, ctx: ag::runtime::OpComputeContext)
///         -> Vec<Result<NdArray, ag::op::ComputeError>>
///     {
///         let xs = ctx.grab_inputs();
///         let x = xs[0];
///         // Use `ndarray::Array::mapv` for element-wise computation.
///         let y = x.mapv(|a| ((a * 0.5).tanh() * 0.5) + 0.5);
///         vec![Ok(y)]
///     }
///
///     fn grad(&self, gy: &ag::Tensor, xs: &[&ag::Tensor], y: &ag::Tensor)
///         -> Vec<Option<ag::Tensor>>
///     {
///         // Symbolic gradient of `x`
///         let gx = gy * (y - ag::square(y));
///         vec![Some(gx)]
///     }
/// }
///
/// // Symbolic `sigmoid` function for end-user.
/// fn sigmoid(x: &ag::Tensor) -> ag::Tensor
/// {
///     ag::Tensor::builder()
///         .set_inputs(vec![x])
///         .set_shape(x.shape())
///         .build(Sigmoid)
/// }
/// ```
pub trait Op
{
    /// Name of this op
    fn name(&self) -> &str;

    /// Actually runs this op.
    fn compute(&self, ctx: ::runtime::OpComputeContext) -> ComputeResult;

    /// Returns symbolic gradients for input nodes by use of output gradient etc.
    ///
    /// # Arguments
    ///
    /// * `gy` - Symbolic representation of the gradient of `compute`'s return value
    /// * `xs` - Symbolic representation of `compute::xs`
    /// * `y` - Symbolic representation of `compute`'s return value
    ///
    /// NOTE:
    /// The number of return values must match `xs.len()`.
    fn grad(&self, gy: &Tensor, xs: &[&Tensor], y: &Tensor) -> Vec<Option<Tensor>>;
}
<|endoftext|>


<commit_before><commit_msg>Fix test with nightly<commit_after><|endoftext|>


<commit_before>use crate::prelude::*;

impl Uuid {
    /// Creates a random UUID.
    ///
    /// This uses the [`getrandom`] crate to utilise the operating system's RNG
    /// as the source of random numbers. If you'd like to use a custom generator,
    /// don't use this method: generate random bytes using your custom generator
    /// and pass them to the [`uuid::Builder::from_bytes`][from_bytes] function
    /// instead.
    ///
    /// Note that usage of this method requires the `v4` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Uuid;
    ///
    /// let uuid = Uuid::new_v4();
    /// ```
    ///
    /// [`getrandom`]: https://crates.io/crates/getrandom
    /// [from_bytes]: struct.Builder.html#method.from_bytes
    // TODO: change signature to support uuid's Error.
    pub fn new_v4() -> Result<Uuid, getrandom::Error> {
        let mut bytes = [0u8; 16];
        getrandom::getrandom(&mut bytes)?;

        let uuid = crate::builder::Builder::from_bytes(bytes)
            .set_variant(Variant::RFC4122)
            .set_version(Version::Random)
            .build();
        Ok(uuid)
    }
}

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

    #[test]
    fn test_new() {
        let uuid = Uuid::new_v4().unwrap();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));
    }

    #[test]
    fn test_get_version() {
        let uuid = Uuid::new_v4().unwrap();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_version_num(), 4)
    }
}
<commit_msg>fix v4 Builder path<commit_after>use crate::prelude::*;

impl Uuid {
    /// Creates a random UUID.
    ///
    /// This uses the [`getrandom`] crate to utilise the operating system's RNG
    /// as the source of random numbers. If you'd like to use a custom generator,
    /// don't use this method: generate random bytes using your custom generator
    /// and pass them to the [`uuid::Builder::from_bytes`][from_bytes] function
    /// instead.
    ///
    /// Note that usage of this method requires the `v4` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use uuid::Uuid;
    ///
    /// let uuid = Uuid::new_v4();
    /// ```
    ///
    /// [`getrandom`]: https://crates.io/crates/getrandom
    /// [from_bytes]: struct.Builder.html#method.from_bytes
    // TODO: change signature to support uuid's Error.
    pub fn new_v4() -> Result<Uuid, getrandom::Error> {
        let mut bytes = [0u8; 16];
        getrandom::getrandom(&mut bytes)?;

        let uuid = crate::Builder::from_bytes(bytes)
            .set_variant(Variant::RFC4122)
            .set_version(Version::Random)
            .build();
        Ok(uuid)
    }
}

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

    #[test]
    fn test_new() {
        let uuid = Uuid::new_v4().unwrap();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_variant(), Some(Variant::RFC4122));
    }

    #[test]
    fn test_get_version() {
        let uuid = Uuid::new_v4().unwrap();

        assert_eq!(uuid.get_version(), Some(Version::Random));
        assert_eq!(uuid.get_version_num(), 4)
    }
}
<|endoftext|>


<commit_before>extern crate vulkano;
extern crate winit;

use std::error;
use std::fmt;
use std::ptr;
use std::sync::Arc;

use vulkano::instance::Instance;
use vulkano::instance::InstanceExtensions;
use vulkano::swapchain::Surface;
use vulkano::swapchain::SurfaceCreationError;
use winit::WindowBuilder;
use winit::CreationError as WindowCreationError;

pub fn required_extensions() -> InstanceExtensions {
    let ideal = InstanceExtensions {
        khr_surface: true,
        khr_xlib_surface: true,
        khr_xcb_surface: true,
        khr_wayland_surface: true,
        khr_mir_surface: true,
        khr_android_surface: true,
        khr_win32_surface: true,
        .. InstanceExtensions::none()
    };

    let supported = InstanceExtensions::supported_by_core();
    supported.intersection(&ideal)
}

pub trait VkSurfaceBuild {
    fn build_vk_surface(self, instance: &Arc<Instance>) -> Result<Window, CreationError>;
}

impl VkSurfaceBuild for WindowBuilder {
    fn build_vk_surface(self, instance: &Arc<Instance>) -> Result<Window, CreationError> {
        let window = try!(self.build());
        let surface = try!(unsafe { winit_to_surface(instance, &window) });

        Ok(Window {
            window: window,
            surface: surface,
        })
    }
}

pub struct Window {
    window: winit::Window,
    surface: Arc<Surface>,
}

impl Window {
    #[inline]
    pub fn window(&self) -> &winit::Window {
        &self.window
    }

    #[inline]
    pub fn surface(&self) -> &Arc<Surface> {
        &self.surface
    }
}

/// Error that can happen when creating a window.
#[derive(Debug)]
pub enum CreationError {
    /// Error when creating the surface.
    SurfaceCreationError(SurfaceCreationError),
    /// Error when creating the window.
    WindowCreationError(WindowCreationError),
}

impl error::Error for CreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CreationError::SurfaceCreationError(_) => "error while creating the surface",
            CreationError::WindowCreationError(_) => "error while creating the window",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CreationError::SurfaceCreationError(ref err) => Some(err),
            CreationError::WindowCreationError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for CreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<SurfaceCreationError> for CreationError {
    #[inline]
    fn from(err: SurfaceCreationError) -> CreationError {
        CreationError::SurfaceCreationError(err)
    }
}

impl From<WindowCreationError> for CreationError {
    #[inline]
    fn from(err: WindowCreationError) -> CreationError {
        CreationError::WindowCreationError(err)
    }
}

#[cfg(target_os = "android")]
unsafe fn winit_to_surface(instance: &Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::android::WindowExt;
    Surface::from_anativewindow(instance, win.get_native_window())
}

#[cfg(all(unix, not(target_os = "android")))]
unsafe fn winit_to_surface(instance: &Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::unix::WindowExt;
    Surface::from_xlib(instance, window.get_xlib_display().unwrap(),
                       window.get_xlib_window().unwrap())
}

#[cfg(windows)]
unsafe fn winit_to_surface(instance: &Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::windows::WindowExt;
    Surface::from_hwnd(instance, ptr::null() as *const () /* FIXME */, win.get_hwnd())
}
<commit_msg>Fix vulkano-win for Linux<commit_after>extern crate vulkano;
extern crate winit;

use std::error;
use std::fmt;
use std::ptr;
use std::sync::Arc;

use vulkano::instance::Instance;
use vulkano::instance::InstanceExtensions;
use vulkano::swapchain::Surface;
use vulkano::swapchain::SurfaceCreationError;
use winit::WindowBuilder;
use winit::CreationError as WindowCreationError;

pub fn required_extensions() -> InstanceExtensions {
    let ideal = InstanceExtensions {
        khr_surface: true,
        khr_xlib_surface: true,
        khr_xcb_surface: true,
        khr_wayland_surface: true,
        khr_mir_surface: true,
        khr_android_surface: true,
        khr_win32_surface: true,
        .. InstanceExtensions::none()
    };

    let supported = InstanceExtensions::supported_by_core();
    supported.intersection(&ideal)
}

pub trait VkSurfaceBuild {
    fn build_vk_surface(self, instance: &Arc<Instance>) -> Result<Window, CreationError>;
}

impl VkSurfaceBuild for WindowBuilder {
    fn build_vk_surface(self, instance: &Arc<Instance>) -> Result<Window, CreationError> {
        let window = try!(self.build());
        let surface = try!(unsafe { winit_to_surface(instance, &window) });

        Ok(Window {
            window: window,
            surface: surface,
        })
    }
}

pub struct Window {
    window: winit::Window,
    surface: Arc<Surface>,
}

impl Window {
    #[inline]
    pub fn window(&self) -> &winit::Window {
        &self.window
    }

    #[inline]
    pub fn surface(&self) -> &Arc<Surface> {
        &self.surface
    }
}

/// Error that can happen when creating a window.
#[derive(Debug)]
pub enum CreationError {
    /// Error when creating the surface.
    SurfaceCreationError(SurfaceCreationError),
    /// Error when creating the window.
    WindowCreationError(WindowCreationError),
}

impl error::Error for CreationError {
    #[inline]
    fn description(&self) -> &str {
        match *self {
            CreationError::SurfaceCreationError(_) => "error while creating the surface",
            CreationError::WindowCreationError(_) => "error while creating the window",
        }
    }

    #[inline]
    fn cause(&self) -> Option<&error::Error> {
        match *self {
            CreationError::SurfaceCreationError(ref err) => Some(err),
            CreationError::WindowCreationError(ref err) => Some(err),
        }
    }
}

impl fmt::Display for CreationError {
    #[inline]
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "{}", error::Error::description(self))
    }
}

impl From<SurfaceCreationError> for CreationError {
    #[inline]
    fn from(err: SurfaceCreationError) -> CreationError {
        CreationError::SurfaceCreationError(err)
    }
}

impl From<WindowCreationError> for CreationError {
    #[inline]
    fn from(err: WindowCreationError) -> CreationError {
        CreationError::WindowCreationError(err)
    }
}

#[cfg(target_os = "android")]
unsafe fn winit_to_surface(instance: &Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::android::WindowExt;
    Surface::from_anativewindow(instance, win.get_native_window())
}

#[cfg(all(unix, not(target_os = "android")))]
unsafe fn winit_to_surface(instance: &Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::unix::WindowExt;
    Surface::from_xlib(instance, win.get_xlib_display().unwrap(),
                       win.get_xlib_window().unwrap())
}

#[cfg(windows)]
unsafe fn winit_to_surface(instance: &Arc<Instance>, win: &winit::Window)
                           -> Result<Arc<Surface>, SurfaceCreationError>
{
    use winit::os::windows::WindowExt;
    Surface::from_hwnd(instance, ptr::null() as *const () /* FIXME */, win.get_hwnd())
}
<|endoftext|>