<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate bragi;
extern crate rustless;
extern crate iron;
extern crate iron_test;
use std::process::Command;

fn get_handler(url: String) -> rustless::Application {
    let api = bragi::api::ApiEndPoint{es_cnx_string: url}.root();
    rustless::Application::new(api)
}

pub fn bragi_tests(es_wrapper: ::ElasticSearchWrapper) {

    let bano2mimir = concat!(env!("OUT_DIR"), "/../../../bano2mimir");
    info!("Launching {}", bano2mimir);
    let status = Command::new(bano2mimir)
                     .args(&["--input=./tests/fixtures/sample-bano.csv".into(),
                             format!("--connection-string={}", es_wrapper.host())])
                     .status()
                     .unwrap();
    assert!(status.success(), "`bano2mimir` failed {}", &status);
    es_wrapper.refresh();

	let handler = get_handler(format!("{}/munin", es_wrapper.host()));

    // Call status
    let resp = iron_test::request::get("http://localhost:3000/status",
                                iron::Headers::new(),
                                &handler).unwrap();
    let result_body = iron_test::response::extract_body_to_string(resp);

    assert_eq!(result_body, r#"{"version":"1.0.0","es":"http://localhost:9242/munin","status":"good"}"#);

    // Call autocomplete
    let resp = iron_test::request::get("http://localhost:3000/autocomplete?q=15 Rue Hector Malot, (Paris)",
                                iron::Headers::new(),
                                &handler).unwrap();
    let result_body = iron_test::response::extract_body_to_string(resp);
    let result = concat!(r#"{"Autocomplete":{"type":"FeatureCollection","#,
    	                 r#""geocoding":{"version":"0.1.0","query":""},"#,
                         r#""features":[{"type":"Feature","geometry":{"coordinates":"#,
                         r#"[2.3763789999999996,48.846495],"type":"Point"},"#,
                         r#""properties":{"geocoding":{"id":"addr:2.376379;48.846495","#,
                         r#""type":"house","label":"15 Rue Hector Malot, (Paris)","#,
                         r#""name":"15 Rue Hector Malot, (Paris)","housenumber":"15","#,
                         r#""street":"Rue Hector Malot, (Paris)","postcode":null,"#
                         r#""city":null}}}]}}"#);
    assert_eq!(result_body, result);
}
<commit_msg>corrections<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate bragi;
extern crate rustless;
extern crate iron;
extern crate iron_test;
use std::process::Command;

fn get_handler(url: String) -> rustless::Application {
    let api = bragi::api::ApiEndPoint{es_cnx_string: url}.root();
    rustless::Application::new(api)
}

pub fn bragi_tests(es_wrapper: ::ElasticSearchWrapper) {

    let bano2mimir = concat!(env!("OUT_DIR"), "/../../../bano2mimir");
    info!("Launching {}", bano2mimir);
    let status = Command::new(bano2mimir)
                     .args(&["--input=./tests/fixtures/sample-bano.csv".into(),
                             format!("--connection-string={}", es_wrapper.host())])
                     .status()
                     .unwrap();
    assert!(status.success(), "`bano2mimir` failed {}", &status);
    es_wrapper.refresh();

    let handler = get_handler(format!("{}/munin", es_wrapper.host()));

    // Call status
    let resp = iron_test::request::get("http://localhost:3000/status",
                                iron::Headers::new(),
                                &handler).unwrap();
    let result_body = iron_test::response::extract_body_to_string(resp);

    assert_eq!(result_body, r#"{"version":"1.0.0","es":"http://localhost:9242/munin","status":"good"}"#);

    // Call autocomplete
    let resp = iron_test::request::get("http://localhost:3000/autocomplete?q=15 Rue Hector Malot, (Paris)",
                                iron::Headers::new(),
                                &handler).unwrap();
    let result_body = iron_test::response::extract_body_to_string(resp);
    let result = concat!(r#"{"Autocomplete":{"type":"FeatureCollection","#,
                         r#""geocoding":{"version":"0.1.0","query":""},"#,
                         r#""features":[{"type":"Feature","geometry":{"coordinates":"#,
                         r#"[2.3763789999999996,48.846495],"type":"Point"},"#,
                         r#""properties":{"geocoding":{"id":"addr:2.376379;48.846495","#,
                         r#""type":"house","label":"15 Rue Hector Malot, (Paris)","#,
                         r#""name":"15 Rue Hector Malot, (Paris)","housenumber":"15","#,
                         r#""street":"Rue Hector Malot, (Paris)","postcode":null,"#
                         r#""city":null}}}]}}"#);
    assert_eq!(result_body, result);
}
<|endoftext|>


<commit_before>use std::io::{Write,Result};
use std::str;

pub struct FauxStdout {
    buffer: String
}

impl Write for FauxStdout {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.buffer += str::from_utf8(buf).expect("u8 slice provided to FauxStdout.write() was not valid UTF-8");
        Ok(0)
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}
<commit_msg>Create a more correct implementation of FauxStdout.write<commit_after>use std::io::{Write,Result};
use std::str;

pub struct FauxStdout {
    buffer: String
}

impl Write for FauxStdout {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        match str::from_utf8(buf) {
            Err(e) => panic!(e),
            Ok(s) => {
                self.buffer += s;
                return Ok(s.len());
            }
        }
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use ra_syntax::{File, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange};

use crate::db::SyntaxDatabase;
use crate::FileId;

salsa::query_group! {
    pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase {
        fn resolve_syntax_ptr(ptr: SyntaxPtr) -> SyntaxNode {
            type ResolveSyntaxPtrQuery;
            // Don't retain syntax trees in memory
            storage volatile;
        }
    }
}

fn resolve_syntax_ptr(db: &impl SyntaxDatabase, ptr: SyntaxPtr) -> SyntaxNode {
    let syntax = db.file_syntax(ptr.file_id);
    ptr.local.resolve(&syntax)
}

/// SyntaxPtr is a cheap `Copy` id which identifies a particular syntax node,
/// without retaining syntax tree in memory. You need to explicitly `resolve`
/// `SyntaxPtr` to get a `SyntaxNode`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct SyntaxPtr {
    file_id: FileId,
    local: LocalSyntaxPtr,
}

impl SyntaxPtr {
    pub(crate) fn new(file_id: FileId, node: SyntaxNodeRef) -> SyntaxPtr {
        let local = LocalSyntaxPtr::new(node);
        SyntaxPtr { file_id, local }
    }
}

/// A pionter to a syntax node inside a file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct LocalSyntaxPtr {
    range: TextRange,
    kind: SyntaxKind,
}

impl LocalSyntaxPtr {
    pub(crate) fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
        LocalSyntaxPtr {
            range: node.range(),
            kind: node.kind(),
        }
    }

    pub(crate) fn resolve(self, file: &File) -> SyntaxNode {
        let mut curr = file.syntax();
        loop {
            if curr.range() == self.range && curr.kind() == self.kind {
                return curr.owned();
            }
            curr = curr
                .children()
                .find(|it| self.range.is_subrange(&it.range()))
                .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
        }
    }

    pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr {
        SyntaxPtr {
            file_id,
            local: self,
        }
    }
}

#[test]
fn test_local_syntax_ptr() {
    let file = File::parse("struct Foo { f: u32, }");
    let field = file
        .syntax()
        .descendants()
        .find_map(ast::NamedFieldDef::cast)
        .unwrap();
    let ptr = LocalSyntaxPtr::new(field.syntax());
    let field_syntax = ptr.resolve(&file);
    assert_eq!(field.syntax(), field_syntax);
}
<commit_msg>Fix test<commit_after>use ra_syntax::{File, SyntaxKind, SyntaxNode, SyntaxNodeRef, TextRange};

use crate::db::SyntaxDatabase;
use crate::FileId;

salsa::query_group! {
    pub(crate) trait SyntaxPtrDatabase: SyntaxDatabase {
        fn resolve_syntax_ptr(ptr: SyntaxPtr) -> SyntaxNode {
            type ResolveSyntaxPtrQuery;
            // Don't retain syntax trees in memory
            storage volatile;
        }
    }
}

fn resolve_syntax_ptr(db: &impl SyntaxDatabase, ptr: SyntaxPtr) -> SyntaxNode {
    let syntax = db.file_syntax(ptr.file_id);
    ptr.local.resolve(&syntax)
}

/// SyntaxPtr is a cheap `Copy` id which identifies a particular syntax node,
/// without retaining syntax tree in memory. You need to explicitly `resolve`
/// `SyntaxPtr` to get a `SyntaxNode`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct SyntaxPtr {
    file_id: FileId,
    local: LocalSyntaxPtr,
}

impl SyntaxPtr {
    pub(crate) fn new(file_id: FileId, node: SyntaxNodeRef) -> SyntaxPtr {
        let local = LocalSyntaxPtr::new(node);
        SyntaxPtr { file_id, local }
    }
}

/// A pionter to a syntax node inside a file.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct LocalSyntaxPtr {
    range: TextRange,
    kind: SyntaxKind,
}

impl LocalSyntaxPtr {
    pub(crate) fn new(node: SyntaxNodeRef) -> LocalSyntaxPtr {
        LocalSyntaxPtr {
            range: node.range(),
            kind: node.kind(),
        }
    }

    pub(crate) fn resolve(self, file: &File) -> SyntaxNode {
        let mut curr = file.syntax();
        loop {
            if curr.range() == self.range && curr.kind() == self.kind {
                return curr.owned();
            }
            curr = curr
                .children()
                .find(|it| self.range.is_subrange(&it.range()))
                .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self))
        }
    }

    pub(crate) fn into_global(self, file_id: FileId) -> SyntaxPtr {
        SyntaxPtr {
            file_id,
            local: self,
        }
    }
}

#[test]
fn test_local_syntax_ptr() {
    use ra_syntax::{ast, AstNode};
    let file = File::parse("struct Foo { f: u32, }");
    let field = file
        .syntax()
        .descendants()
        .find_map(ast::NamedFieldDef::cast)
        .unwrap();
    let ptr = LocalSyntaxPtr::new(field.syntax());
    let field_syntax = ptr.resolve(&file);
    assert_eq!(field.syntax(), field_syntax);
}
<|endoftext|>


<commit_before>extern crate pombase;
extern crate pombase_rc_string;

use std::iter::Iterator;

use hashbrown::HashSet;

use self::pombase::api::query::*;
use self::pombase::api::result::*;
use self::pombase::api::server_data::*;
use self::pombase::api::query_exec::*;
use self::pombase::web::config::TermAndName;
use self::pombase::web::data::{GeneShort, DeletionViability, GeneQueryTermData};

use self::pombase_rc_string::RcString;

fn get_server_data() -> ServerData {
    use std::path::PathBuf;
    let mut search_maps_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    search_maps_path.push("tests/test_search_data.json.gz");
    let mut gene_subsets_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    gene_subsets_path.push("tests/test_gene_subsets.json");
    let mut config_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    config_path.push("tests/test_config.json");
    ServerData::new(config_path.to_str().expect("config"),
                    search_maps_path.to_str().expect("search maps"),
                    gene_subsets_path.to_str().expect("subsets"))
}

fn check_gene_result(query: &Query, genes: Vec<&str>) {
    let server_data = get_server_data();
    let query_exec = QueryExec::new(server_data);
    let result = query_exec.exec(&query);

    let result_genes_iter =
        result.rows.into_iter()
        .map(|row: ResultRow| row.gene_uniquename)
        .collect::<HashSet<_>>();
    let expect_genes_iter =
        genes.iter().cloned()
        .map(|s: &str| RcString::from(s))
        .collect::<HashSet<_>>();
    assert_eq!(result_genes_iter,
               expect_genes_iter);
}

fn check_gene_result_with_viability(query: &Query,
                                    expected_results: &Vec<ResultRow>) {
    let server_data = get_server_data();
    let query_exec = QueryExec::new(server_data);
    let results = query_exec.exec(&query);

    assert_eq!(expected_results, &results.rows);
}

fn make_genes(ids: Vec<&str>) -> Vec<GeneShort> {
    let mut ret = vec![];
    for id in ids {
        ret.push(GeneShort { uniquename: id.into(), name: None, product: None });
    }
    ret
}

#[test]
fn test_and_or_not() {
    let qp1 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC19G12.04", "SPAC1805.15c", "SPAC27E2.05"])
    };
    let qp2 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09"])
    };
    let qp3 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC19G12.04", "SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09"])
    };
    let qp4 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09", "SPRRNA.26"])
    };
    let qp5 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC27E2.05", "SPAC27E2.05", "SPRRNA.26"])
    };
    let and_query_node_1 = QueryNode::And(vec![qp1.clone(), qp2.clone()]);
    let and_query_node_2 = QueryNode::And(vec![qp3.clone(), qp4.clone()]);

    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };

    let and_query =
        Query::new(QueryNode::And(vec![and_query_node_1.clone(), and_query_node_2.clone()]),
                   opts.clone());

    check_gene_result(&and_query, vec!["SPAC1805.15c", "SPAC27E2.05"]);

    let or_query =
        Query::new(QueryNode::Or(vec![and_query_node_1, and_query_node_2]), opts.clone());

    check_gene_result(&or_query, vec!["SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09"]);

    let not_query_node =
        QueryNode::Not { node_a: Box::new(qp1.clone()), node_b: Box::new(qp2.clone()) };
    let not_query = Query::new(not_query_node, opts.clone());
    check_gene_result(&not_query, vec!["SPAC19G12.04"]);

    let not_query_2_node = QueryNode::Not { node_a: Box::new(qp1.clone()), node_b: Box::new(qp5) };
    let not_query_2 = Query::new(not_query_2_node, opts.clone());
    check_gene_result(&not_query_2, vec!["SPAC19G12.04", "SPAC1805.15c"]);
}

#[test]
fn test_output_options() {

    // try extra output options
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned(),
                          "deletion_viability".to_owned(),
                          "go_component".to_owned()],
        sequence: SeqType::None,
    };

    let expected_results =
        vec![
            ResultRow {
                gene_uniquename: RcString::from("SPAC19G12.04"),
                deletion_viability: Some(DeletionViability::Inviable),
                go_component: None,
                go_process_superslim: None,
                go_function: None,
                characterisation_status: None,
                taxonomic_distribution: None,
                ortholog_taxonids: HashSet::new(),
                tmm: None,
                sequence: None,
            },
            ResultRow {
                gene_uniquename: RcString::from("SPAC1805.15c"),
                deletion_viability: Some(DeletionViability::Viable),
                go_component: Some(GeneQueryTermData::Other),
                go_process_superslim: None,
                go_function: None,
                characterisation_status: None,
                taxonomic_distribution: None,
                ortholog_taxonids: HashSet::new(),
                tmm: None,
                sequence: None,
            },
            ResultRow {
                gene_uniquename: RcString::from("SPAC27E2.05"),
                deletion_viability: Some(DeletionViability::DependsOnConditions),
                go_component: Some(GeneQueryTermData::Term(TermAndName {
                    termid: RcString::from("GO:0005634"),
                    name: RcString::from("nucleus"),
                })),
                go_process_superslim: None,
                go_function: None,
                characterisation_status: None,
                taxonomic_distribution: None,
                ortholog_taxonids: HashSet::new(),
                tmm: None,
                sequence: None,
            }];

    let qp1 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC19G12.04", "SPAC1805.15c", "SPAC27E2.05"])
    };

    let query = Query::new(qp1, opts);

    check_gene_result_with_viability(&query, &expected_results);
}

#[test]
fn test_termid() {
    let qp1 = QueryNode::Term { termid: "GO:0044237".into(), name: None,
                                single_or_multi_allele: None, expression: None };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1, vec!["SPAC24B11.06c", "SPAC19G12.03", "SPAC2F3.09", "SPAC27E2.05"]);
}

#[test]
fn test_gene_subset() {
    let qp1 = QueryNode::Subset { subset_name: "PTHR17490:SF9".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1, vec!["SPCC895.03c"]);
}

#[test]
fn test_gene_subset_invert() {
    let qp1 = QueryNode::Subset { subset_name: "!interpro:IPR002906".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1,
                      vec!["SPAC589.10c", "SPAC17H9.16",
                           "SPBC460.01c", "SPBC1652.02", "SPCC736.11",
                           "SPBC19F8.06c", "SPAC6G10.11c",
                           "SPBC359.01", "SPAC1039.09", "SPBC359.03c",
                           "SPAC7D4.10", "SPCC895.03c"]);
}

#[test]
fn test_gene_subset_wildcard() {
    let qp1 = QueryNode::Subset { subset_name: "interpro:IPR*".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1,
                      vec!["SPAC589.10c", "SPCC736.11", "SPAC6G10.11c"]);
}

#[test]
fn test_gene_subset_not_wildcard() {
    let qp1 = QueryNode::Subset { subset_name: "!interpro:IPR*".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1,
                      vec!["SPAC589.10c", "SPAC7D4.10",
                           "SPBC359.01", "SPAC17H9.16", "SPAC1039.09",
                           "SPBC359.03c", "SPCC736.11", "SPBC1652.02",
                           "SPBC460.01c", "SPAC6G10.11c", "SPCC895.03c",
                           "SPBC19F8.06c"]);
}
<commit_msg>Fix failing test<commit_after>extern crate pombase;
extern crate pombase_rc_string;

use std::iter::Iterator;

use hashbrown::HashSet;

use self::pombase::api::query::*;
use self::pombase::api::result::*;
use self::pombase::api::server_data::*;
use self::pombase::api::query_exec::*;
use self::pombase::web::config::TermAndName;
use self::pombase::web::data::{GeneShort, DeletionViability, GeneQueryTermData};

use self::pombase_rc_string::RcString;

fn get_server_data() -> ServerData {
    use std::path::PathBuf;
    let mut search_maps_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    search_maps_path.push("tests/test_search_data.json.gz");
    let mut gene_subsets_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    gene_subsets_path.push("tests/test_gene_subsets.json");
    let mut config_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    config_path.push("tests/test_config.json");
    ServerData::new(config_path.to_str().expect("config"),
                    search_maps_path.to_str().expect("search maps"),
                    gene_subsets_path.to_str().expect("subsets"))
}

fn check_gene_result(query: &Query, genes: Vec<&str>) {
    let server_data = get_server_data();
    let query_exec = QueryExec::new(server_data);
    let result = query_exec.exec(&query);

    let result_genes_iter =
        result.rows.into_iter()
        .map(|row: ResultRow| row.gene_uniquename)
        .collect::<HashSet<_>>();
    let expect_genes_iter =
        genes.iter().cloned()
        .map(|s: &str| RcString::from(s))
        .collect::<HashSet<_>>();
    assert_eq!(result_genes_iter,
               expect_genes_iter);
}

fn check_gene_result_with_viability(query: &Query,
                                    expected_results: &Vec<ResultRow>) {
    let server_data = get_server_data();
    let query_exec = QueryExec::new(server_data);
    let results = query_exec.exec(&query);

    assert_eq!(expected_results, &results.rows);
}

fn make_genes(ids: Vec<&str>) -> Vec<GeneShort> {
    let mut ret = vec![];
    for id in ids {
        ret.push(GeneShort { uniquename: id.into(), name: None, product: None });
    }
    ret
}

#[test]
fn test_and_or_not() {
    let qp1 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC19G12.04", "SPAC1805.15c", "SPAC27E2.05"])
    };
    let qp2 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09"])
    };
    let qp3 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC19G12.04", "SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09"])
    };
    let qp4 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09", "SPRRNA.26"])
    };
    let qp5 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC27E2.05", "SPAC27E2.05", "SPRRNA.26"])
    };
    let and_query_node_1 = QueryNode::And(vec![qp1.clone(), qp2.clone()]);
    let and_query_node_2 = QueryNode::And(vec![qp3.clone(), qp4.clone()]);

    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };

    let and_query =
        Query::new(QueryNode::And(vec![and_query_node_1.clone(), and_query_node_2.clone()]),
                   opts.clone());

    check_gene_result(&and_query, vec!["SPAC1805.15c", "SPAC27E2.05"]);

    let or_query =
        Query::new(QueryNode::Or(vec![and_query_node_1, and_query_node_2]), opts.clone());

    check_gene_result(&or_query, vec!["SPAC1805.15c", "SPAC27E2.05", "SPAC2F3.09"]);

    let not_query_node =
        QueryNode::Not { node_a: Box::new(qp1.clone()), node_b: Box::new(qp2.clone()) };
    let not_query = Query::new(not_query_node, opts.clone());
    check_gene_result(&not_query, vec!["SPAC19G12.04"]);

    let not_query_2_node = QueryNode::Not { node_a: Box::new(qp1.clone()), node_b: Box::new(qp5) };
    let not_query_2 = Query::new(not_query_2_node, opts.clone());
    check_gene_result(&not_query_2, vec!["SPAC19G12.04", "SPAC1805.15c"]);
}

#[test]
fn test_output_options() {

    // try extra output options
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned(),
                          "deletion_viability".to_owned(),
                          "go_component".to_owned()],
        sequence: SeqType::None,
    };

    let expected_results =
        vec![
            ResultRow {
                gene_uniquename: RcString::from("SPAC19G12.04"),
                deletion_viability: Some(DeletionViability::Inviable),
                go_component: None,
                go_process_superslim: None,
                go_function: None,
                characterisation_status: None,
                taxonomic_distribution: None,
                ortholog_taxonids: HashSet::new(),
                tmm: None,
                protein_length_bin: None,
                sequence: None,
            },
            ResultRow {
                gene_uniquename: RcString::from("SPAC1805.15c"),
                deletion_viability: Some(DeletionViability::Viable),
                go_component: Some(GeneQueryTermData::Other),
                go_process_superslim: None,
                go_function: None,
                characterisation_status: None,
                taxonomic_distribution: None,
                ortholog_taxonids: HashSet::new(),
                protein_length_bin: None,
                tmm: None,
                sequence: None,
            },
            ResultRow {
                gene_uniquename: RcString::from("SPAC27E2.05"),
                deletion_viability: Some(DeletionViability::DependsOnConditions),
                go_component: Some(GeneQueryTermData::Term(TermAndName {
                    termid: RcString::from("GO:0005634"),
                    name: RcString::from("nucleus"),
                })),
                go_process_superslim: None,
                go_function: None,
                characterisation_status: None,
                taxonomic_distribution: None,
                ortholog_taxonids: HashSet::new(),
                protein_length_bin: None,
                tmm: None,
                sequence: None,
            }];

    let qp1 = QueryNode::GeneList {
        genes: make_genes(vec!["SPAC19G12.04", "SPAC1805.15c", "SPAC27E2.05"])
    };

    let query = Query::new(qp1, opts);

    check_gene_result_with_viability(&query, &expected_results);
}

#[test]
fn test_termid() {
    let qp1 = QueryNode::Term { termid: "GO:0044237".into(), name: None,
                                single_or_multi_allele: None, expression: None };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1, vec!["SPAC24B11.06c", "SPAC19G12.03", "SPAC2F3.09", "SPAC27E2.05"]);
}

#[test]
fn test_gene_subset() {
    let qp1 = QueryNode::Subset { subset_name: "PTHR17490:SF9".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1, vec!["SPCC895.03c"]);
}

#[test]
fn test_gene_subset_invert() {
    let qp1 = QueryNode::Subset { subset_name: "!interpro:IPR002906".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1,
                      vec!["SPAC589.10c", "SPAC17H9.16",
                           "SPBC460.01c", "SPBC1652.02", "SPCC736.11",
                           "SPBC19F8.06c", "SPAC6G10.11c",
                           "SPBC359.01", "SPAC1039.09", "SPBC359.03c",
                           "SPAC7D4.10", "SPCC895.03c"]);
}

#[test]
fn test_gene_subset_wildcard() {
    let qp1 = QueryNode::Subset { subset_name: "interpro:IPR*".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1,
                      vec!["SPAC589.10c", "SPCC736.11", "SPAC6G10.11c"]);
}

#[test]
fn test_gene_subset_not_wildcard() {
    let qp1 = QueryNode::Subset { subset_name: "!interpro:IPR*".into() };
    let opts = QueryOutputOptions {
        field_names: vec!["gene_uniquename".to_owned()],
        sequence: SeqType::None,
    };
    let q1 = Query::new(qp1, opts);

    check_gene_result(&q1,
                      vec!["SPAC589.10c", "SPAC7D4.10",
                           "SPBC359.01", "SPAC17H9.16", "SPAC1039.09",
                           "SPBC359.03c", "SPCC736.11", "SPBC1652.02",
                           "SPBC460.01c", "SPAC6G10.11c", "SPCC895.03c",
                           "SPBC19F8.06c"]);
}
<|endoftext|>


<commit_before>#![no_std]

#[macro_use]
extern crate static_assertions;

assert_impl!(byte; u8, Send, Sync);
assert_impl!(iter; &[u8], IntoIterator /* TODO: <Item=&u8> */);
assert_impl!(slice; [u8], Send, Sync, AsRef<[u8]>);

#[cfg(feature = "failure")]
assert_impl!(ptr; *const u8, Send, Sync);

#[test]
fn str_impl() {
    assert_impl!(str, Send, Sync, AsRef<[u8]>);
}
<commit_msg>[Tests] Ensure assert_impl works for obscure types<commit_after>#![no_std]

#[macro_use]
extern crate static_assertions;

trait Tri<A: ?Sized, B: ?Sized, C: ?Sized> {}

impl<T, A: ?Sized, B: ?Sized, C: ?Sized> Tri<A, B, C> for T {}

assert_impl!(tri; u64, Tri<[&'static u8], Send, (u16, u16)>);
assert_impl!(byte; u8, Send, Sync);
assert_impl!(iter; &[u8], IntoIterator /* TODO: <Item=&u8> */);
assert_impl!(slice; [u8], Send, Sync, AsRef<[u8]>);

#[cfg(feature = "failure")]
assert_impl!(ptr; *const u8, Send, Sync);

#[test]
fn str_impl() {
    assert_impl!(str, Send, Sync, AsRef<[u8]>);
}
<|endoftext|>


<commit_before>#![no_std]
#![deny(unsafe_code)]

#[macro_use]
extern crate static_assertions;

use core::ops::Range;

trait Tri<A: ?Sized, B: ?Sized, C: ?Sized> {}

impl<T, A: ?Sized, B: ?Sized, C: ?Sized> Tri<A, B, C> for T {}

assert_impl_all!(
    u64: Tri<[&'static u8], dyn Tri<dyn Send, dyn Sync, str>, (u16, u16)>
);
assert_impl_all!(u8: Send, Sync);
assert_impl_all!(&'static [u8]: IntoIterator<Item=&'static u8>);
assert_impl_all!(Range<u8>: Iterator<Item=u8>);
assert_impl_all!([u8]: Send, Sync, AsRef<[u8]>);
assert_impl_all!(str: Send, Sync, AsRef<[u8]>,);

assert_impl_any!((): Send, Sync);
assert_impl_any!((): Send, From<u8>);
assert_impl_any!((): From<u8>, From<u16>, Send);

#[allow(dead_code)]
struct Foo;

trait A {}
trait B {}
trait C {}

impl B for Foo {}

assert_impl_one!(Foo: A, B);
assert_impl_one!(Foo: B, A);
assert_impl_one!(Foo: B, C);
assert_impl_one!(Foo: C, B);
assert_impl_one!(Foo: A, B, C);
assert_impl_one!(Foo: B, C, A);
assert_impl_one!(Foo: C, A, B);

#[derive(Clone)]
struct Test;

assert_impl!(u8: (From<u16>) | (Into<u16>));
assert_impl!((): (From<u8>) | (From<u16>) | Send);
assert_impl!((): (!From<u8>) & !(From<u16>) & Send);
assert_impl!((): Copy | Clone);
assert_impl!((): Copy & Clone);
assert_impl!(Test: Copy | Clone);
assert_impl!(Test: !Copy | Clone);
assert_impl!(Test: !Copy & Clone);
assert_impl!(Test: !Copy & (Clone));
assert_impl!(Test: !(Copy) & Clone);
assert_impl!(Test: !(!Clone));
assert_impl!(Test: !(Copy) & !(!Clone));
assert_impl!(Test: !(Copy & Clone));
assert_impl!(str: !Copy & !Clone);

#[derive(Clone)]
struct Box<T>(T);

assert_impl!(for(T: Clone) Box<T>: Clone);
assert_impl!(for(T: Clone + Send) Box<T>: Clone & Send);
assert_impl!(for(T) PhantomData<T>: Clone);
assert_impl!(for(T: Copy) T: Clone);
assert_impl!(for(T: ?Sized) T: Clone | !Clone);
<commit_msg>Add more generic `assert_impl!` tests<commit_after>#![no_std]
#![deny(unsafe_code)]

#[macro_use]
extern crate static_assertions;

use core::ops::Range;

trait Tri<A: ?Sized, B: ?Sized, C: ?Sized> {}

impl<T, A: ?Sized, B: ?Sized, C: ?Sized> Tri<A, B, C> for T {}

assert_impl_all!(
    u64: Tri<[&'static u8], dyn Tri<dyn Send, dyn Sync, str>, (u16, u16)>
);
assert_impl_all!(u8: Send, Sync);
assert_impl_all!(&'static [u8]: IntoIterator<Item=&'static u8>);
assert_impl_all!(Range<u8>: Iterator<Item=u8>);
assert_impl_all!([u8]: Send, Sync, AsRef<[u8]>);
assert_impl_all!(str: Send, Sync, AsRef<[u8]>,);

assert_impl_any!((): Send, Sync);
assert_impl_any!((): Send, From<u8>);
assert_impl_any!((): From<u8>, From<u16>, Send);

#[allow(dead_code)]
struct Foo;

trait A {}
trait B {}
trait C {}

impl B for Foo {}

assert_impl_one!(Foo: A, B);
assert_impl_one!(Foo: B, A);
assert_impl_one!(Foo: B, C);
assert_impl_one!(Foo: C, B);
assert_impl_one!(Foo: A, B, C);
assert_impl_one!(Foo: B, C, A);
assert_impl_one!(Foo: C, A, B);

#[derive(Clone)]
struct Test;

assert_impl!(u8: (From<u16>) | (Into<u16>));
assert_impl!((): (From<u8>) | (From<u16>) | Send);
assert_impl!((): (!From<u8>) & !(From<u16>) & Send);
assert_impl!((): Copy | Clone);
assert_impl!((): Copy & Clone);
assert_impl!(Test: Copy | Clone);
assert_impl!(Test: !Copy | Clone);
assert_impl!(Test: !Copy & Clone);
assert_impl!(Test: !Copy & (Clone));
assert_impl!(Test: !(Copy) & Clone);
assert_impl!(Test: !(!Clone));
assert_impl!(Test: !(Copy) & !(!Clone));
assert_impl!(Test: !(Copy & Clone));
assert_impl!(str: !Copy & !Clone);

#[derive(Clone)]
struct Box<T>(T);

assert_impl!(for(T: Clone) Box<T>: Clone);
assert_impl!(for(T: Clone + Send) Box<T>: Clone & Send);
assert_impl!(for(T) Box<T>: (From<T>) & (Into<T>));

assert_impl!(for(T) PhantomData<T>: Clone);
assert_impl!(for(T: Copy) T: Clone);
assert_impl!(for(T: ?Sized) T: Clone | !Clone);
assert_impl!(for('a, T: 'a) &'a mut T: !Copy);
<|endoftext|>


<commit_before>//! Dynamically linked symbolic imports

// table of tuples:
// <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend>
// symbol flags are undocumented

use core::ops::Range;
use core::fmt::{self, Debug};
use scroll::{Sleb128, Uleb128, Pread};

use container;
use error;
use mach::load_command;
use mach::bind_opcodes;
use mach::segment;

#[derive(Debug)]
/// Import binding information generated by running the Finite State Automaton programmed via `bind_opcodes`
struct BindInformation<'a> {
  seg_index:              u8,
  seg_offset:             u64,
  bind_type:              u8,
  symbol_library_ordinal: u8,
  symbol_name:            &'a str,
  symbol_flags:           u8,
  addend:                 i64,
  special_dylib:          u8, // seeing self = 0 assuming this means the symbol is imported from itself, because its... libSystem.B.dylib?
}

impl<'a> BindInformation<'a> {
    pub fn new (is_lazy: bool) -> Self {
        let mut bind_info = BindInformation::default();
        let bind_type = if is_lazy { bind_opcodes::BIND_TYPE_POINTER } else { 0x0 };
        bind_info.bind_type = bind_type;
        bind_info
    }
    pub fn is_lazy(&self) -> bool {
        self.bind_type == bind_opcodes::BIND_TYPE_POINTER
    }
}

impl<'a> Default for BindInformation<'a> {
    fn default() -> Self {
        BindInformation {
            seg_index:     0,
            seg_offset:    0x0,
            bind_type:     0x0,
            special_dylib: 1,
            symbol_library_ordinal: 0,
            symbol_name: "",
            symbol_flags: 0,
            addend: 0
        }
    }
}

#[derive(Debug)]
/// An dynamically linked symbolic import
pub struct Import<'a> {
    /// The symbol name dyld uses to resolve this import
    pub name:    &'a str,
    /// The library this symbol belongs to (thanks to two-level namespaces)
    pub dylib:   &'a str,
    ///  Whether the symbol is lazily resolved or not
    pub is_lazy: bool,
    /// The offset in the binary this import is found
    pub offset:  u64,
    /// The size of this import
    pub size:    usize,
}

impl<'a> Import<'a> {
    /// Create a new import from the import binding information in `bi`
    fn new(bi: &BindInformation<'a>, libs: &[&'a str], segments: &[segment::Segment]) -> Import<'a> {
        let offset = {
            let segment = &segments[bi.seg_index as usize];
            segment.fileoff + bi.seg_offset
        };
        let size = if bi.is_lazy() { 8 } else { 0 };
        Import {
            name: bi.symbol_name,
            dylib: libs[bi.symbol_library_ordinal as usize],
            is_lazy: bi.is_lazy(),
            offset: offset,
            size: size,
        }
    }
}

/// An interpreter for mach BIND opcodes.
/// Runs on prebound (non lazy) symbols (usually dylib extern consts and extern variables),
/// and lazy symbols (usually dylib functions)
pub struct BindInterpreter<'a> {
    data: &'a [u8],
    location: Range<usize>,
    lazy_location: Range<usize>,
}

impl<'a> Debug for BindInterpreter<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        writeln!(fmt, "BindInterpreter {{")?;
        writeln!(fmt, "  Location: {:#x}..{:#x}", self.location.start, self.location.end)?;
        writeln!(fmt, "  Lazy Location: {:#x}..{:#x}", self.lazy_location.start, self.lazy_location.end)?;
        writeln!(fmt, "}}")
    }
}

impl<'a> BindInterpreter<'a> {
    /// Construct a new import binding interpreter from `bytes` and the load `command`
    pub fn new(bytes: &'a [u8], command: &load_command::DyldInfoCommand) -> Self {
        let get_pos = |off: u32, size: u32| -> Range<usize> {
            off as usize..(off + size) as usize
        };
        let location = get_pos(command.bind_off, command.bind_size);
        let lazy_location = get_pos(command.lazy_bind_off, command.lazy_bind_size);
        BindInterpreter {
            data: bytes.as_ref(),
            location: location,
            lazy_location: lazy_location,
        }
    }
    /// Return the imports in this binary
    pub fn imports(&self, libs: &[&'a str], segments: &[segment::Segment], ctx: &container::Ctx) -> error::Result<Vec<Import<'a>>>{
        let mut imports = Vec::new();
        self.run(false, libs, segments, ctx, &mut imports)?;
        self.run( true, libs, segments, ctx, &mut imports)?;
        Ok(imports)
    }
    fn run(&self, is_lazy: bool, libs: &[&'a str], segments: &[segment::Segment], ctx: &container::Ctx, imports: &mut Vec<Import<'a>>) -> error::Result<()>{
        use mach::bind_opcodes::*;
        let location = if is_lazy {
            &self.location
        } else {
            &self.lazy_location
        };
        let mut bind_info = BindInformation::new(is_lazy);
        let mut offset = &mut location.start.clone();
        while *offset < location.end {
            let opcode = self.data.gread::<i8>(offset)? as bind_opcodes::Opcode;
            // let mut input = String::new();
            // ::std::io::stdin().read_line(&mut input).unwrap();
            // println!("opcode: {} ({:#x}) offset: {:#x}\n {:?}", opcode_to_str(opcode & BIND_OPCODE_MASK), opcode, *offset - location.start - 1, &bind_info);
            match opcode & BIND_OPCODE_MASK {
                // we do nothing, don't update our records, and add a new, fresh record
                BIND_OPCODE_DONE => {
                    bind_info = BindInformation::new(is_lazy);
                },
                BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => {
	            let symbol_library_ordinal = opcode & BIND_IMMEDIATE_MASK;
	            bind_info.symbol_library_ordinal = symbol_library_ordinal;
                },
                BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB => {
	            let symbol_library_ordinal = Uleb128::read(&self.data, offset)?;
	            bind_info.symbol_library_ordinal = symbol_library_ordinal as u8;
                },
                BIND_OPCODE_SET_DYLIB_SPECIAL_IMM => {
                    // dyld puts the immediate into the symbol_library_ordinal field...
                    let special_dylib = opcode & BIND_IMMEDIATE_MASK;
                    // Printf.printf "special_dylib: 0x%x\n" special_dylib
                    bind_info.special_dylib = special_dylib;
                },
                BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
	            let symbol_flags = opcode & BIND_IMMEDIATE_MASK;
	            let symbol_name = self.data.pread::<&str>(*offset)?;
                    *offset = *offset + symbol_name.len() + 1; // second time this \0 caused debug woes
	            bind_info.symbol_name = symbol_name;
                    bind_info.symbol_flags = symbol_flags;
                },
                BIND_OPCODE_SET_TYPE_IMM => {
	            let bind_type = opcode & BIND_IMMEDIATE_MASK;
	            bind_info.bind_type = bind_type;
                },
                BIND_OPCODE_SET_ADDEND_SLEB => {
                    let addend = Sleb128::read(&self.data, offset)?;
                    bind_info.addend = addend;
                },
                BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
	            let seg_index = opcode & BIND_IMMEDIATE_MASK;
                    // dyld sets the address to the segActualLoadAddress(segIndex) + uleb128
                    // address = segActualLoadAddress(segmentIndex) + read_uleb128(p, end);
	            let seg_offset = Uleb128::read(&self.data, offset)?;
	            bind_info.seg_index = seg_index;
                    bind_info.seg_offset = seg_offset;
                },
                BIND_OPCODE_ADD_ADDR_ULEB => {
	            let addr = Uleb128::read(&self.data, offset)?;
	            let seg_offset = bind_info.seg_offset.wrapping_add(addr);
	            bind_info.seg_offset = seg_offset;
                },
                // record the record by placing its value into our list
                BIND_OPCODE_DO_BIND => {
                    // from dyld:
                    //      if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += sizeof(intptr_t);
                    let seg_offset = bind_info.seg_offset.wrapping_add(ctx.size() as u64);
                    bind_info.seg_offset = seg_offset;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
                    // dyld:
	            // if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += read_uleb128(p, end) + sizeof(intptr_t);
                    // we bind the old record, then increment bind info address for the next guy, plus the ptr offset *)
                    let addr = Uleb128::read(&self.data, offset)?;
                    let seg_offset = bind_info.seg_offset.wrapping_add(addr).wrapping_add(ctx.size() as u64);
                    bind_info.seg_offset = seg_offset;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
                    // dyld:
                    // if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += immediate*sizeof(intptr_t) + sizeof(intptr_t);
	            // break;
                    // similarly, we bind the old record, then perform address manipulation for the next record
	            let scale = opcode & BIND_IMMEDIATE_MASK;
                    let size = ctx.size() as u64;
                    let seg_offset = bind_info.seg_offset.wrapping_add(scale as u64 * size).wrapping_add(size);
                    bind_info.seg_offset = seg_offset;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
                    // dyld:
                    // count = read_uleb128(p, end);
	            // skip = read_uleb128(p, end);
	            // for (uint32_t i=0; i < count; ++i) {
	            // if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += skip + sizeof(intptr_t);
	            // }
	            // break;
                    let count = Uleb128::read(&self.data, offset)?;
                    let skip =  Uleb128::read(&self.data, offset)?;
                    let mut addr = bind_info.seg_offset;
                    for _i  in 0..count {
                        addr += skip + ctx.size() as u64;
                    }
                    bind_info.seg_offset = addr;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                _ => {
                }
            }
        }
        Ok(())
    }
}
<commit_msg>Expose import addend and virtual address<commit_after>//! Dynamically linked symbolic imports

// table of tuples:
// <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend>
// symbol flags are undocumented

use core::ops::Range;
use core::fmt::{self, Debug};
use scroll::{Sleb128, Uleb128, Pread};

use container;
use error;
use mach::load_command;
use mach::bind_opcodes;
use mach::segment;

#[derive(Debug)]
/// Import binding information generated by running the Finite State Automaton programmed via `bind_opcodes`
struct BindInformation<'a> {
  seg_index:              u8,
  seg_offset:             u64,
  bind_type:              u8,
  symbol_library_ordinal: u8,
  symbol_name:            &'a str,
  symbol_flags:           u8,
  addend:                 i64,
  special_dylib:          u8, // seeing self = 0 assuming this means the symbol is imported from itself, because its... libSystem.B.dylib?
}

impl<'a> BindInformation<'a> {
    pub fn new (is_lazy: bool) -> Self {
        let mut bind_info = BindInformation::default();
        let bind_type = if is_lazy { bind_opcodes::BIND_TYPE_POINTER } else { 0x0 };
        bind_info.bind_type = bind_type;
        bind_info
    }
    pub fn is_lazy(&self) -> bool {
        self.bind_type == bind_opcodes::BIND_TYPE_POINTER
    }
}

impl<'a> Default for BindInformation<'a> {
    fn default() -> Self {
        BindInformation {
            seg_index:     0,
            seg_offset:    0x0,
            bind_type:     0x0,
            special_dylib: 1,
            symbol_library_ordinal: 0,
            symbol_name: "",
            symbol_flags: 0,
            addend: 0
        }
    }
}

#[derive(Debug)]
/// An dynamically linked symbolic import
pub struct Import<'a> {
    /// The symbol name dyld uses to resolve this import
    pub name:    &'a str,
    /// The library this symbol belongs to (thanks to two-level namespaces)
    pub dylib:   &'a str,
    ///  Whether the symbol is lazily resolved or not
    pub is_lazy: bool,
    /// The offset in the binary this import is found
    pub offset:  u64,
    /// The size of this import
    pub size:    usize,
    /// The virtual memory address at which this import is found
    pub address: u64,
    /// The addend of this import
    pub addend:  i64,
}

impl<'a> Import<'a> {
    /// Create a new import from the import binding information in `bi`
    fn new(bi: &BindInformation<'a>, libs: &[&'a str], segments: &[segment::Segment]) -> Import<'a> {
        let (offset, address) = {
            let segment = &segments[bi.seg_index as usize];
            (
                segment.fileoff + bi.seg_offset,
                segment.vmaddr + bi.seg_offset
            )
        };
        let size = if bi.is_lazy() { 8 } else { 0 };
        Import {
            name: bi.symbol_name,
            dylib: libs[bi.symbol_library_ordinal as usize],
            is_lazy: bi.is_lazy(),
            offset: offset,
            size: size,
            address: address,
            addend: bi.addend
        }
    }
}

/// An interpreter for mach BIND opcodes.
/// Runs on prebound (non lazy) symbols (usually dylib extern consts and extern variables),
/// and lazy symbols (usually dylib functions)
pub struct BindInterpreter<'a> {
    data: &'a [u8],
    location: Range<usize>,
    lazy_location: Range<usize>,
}

impl<'a> Debug for BindInterpreter<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        writeln!(fmt, "BindInterpreter {{")?;
        writeln!(fmt, "  Location: {:#x}..{:#x}", self.location.start, self.location.end)?;
        writeln!(fmt, "  Lazy Location: {:#x}..{:#x}", self.lazy_location.start, self.lazy_location.end)?;
        writeln!(fmt, "}}")
    }
}

impl<'a> BindInterpreter<'a> {
    /// Construct a new import binding interpreter from `bytes` and the load `command`
    pub fn new(bytes: &'a [u8], command: &load_command::DyldInfoCommand) -> Self {
        let get_pos = |off: u32, size: u32| -> Range<usize> {
            off as usize..(off + size) as usize
        };
        let location = get_pos(command.bind_off, command.bind_size);
        let lazy_location = get_pos(command.lazy_bind_off, command.lazy_bind_size);
        BindInterpreter {
            data: bytes.as_ref(),
            location: location,
            lazy_location: lazy_location,
        }
    }
    /// Return the imports in this binary
    pub fn imports(&self, libs: &[&'a str], segments: &[segment::Segment], ctx: &container::Ctx) -> error::Result<Vec<Import<'a>>>{
        let mut imports = Vec::new();
        self.run(false, libs, segments, ctx, &mut imports)?;
        self.run( true, libs, segments, ctx, &mut imports)?;
        Ok(imports)
    }
    fn run(&self, is_lazy: bool, libs: &[&'a str], segments: &[segment::Segment], ctx: &container::Ctx, imports: &mut Vec<Import<'a>>) -> error::Result<()>{
        use mach::bind_opcodes::*;
        let location = if is_lazy {
            &self.location
        } else {
            &self.lazy_location
        };
        let mut bind_info = BindInformation::new(is_lazy);
        let mut offset = &mut location.start.clone();
        while *offset < location.end {
            let opcode = self.data.gread::<i8>(offset)? as bind_opcodes::Opcode;
            // let mut input = String::new();
            // ::std::io::stdin().read_line(&mut input).unwrap();
            // println!("opcode: {} ({:#x}) offset: {:#x}\n {:?}", opcode_to_str(opcode & BIND_OPCODE_MASK), opcode, *offset - location.start - 1, &bind_info);
            match opcode & BIND_OPCODE_MASK {
                // we do nothing, don't update our records, and add a new, fresh record
                BIND_OPCODE_DONE => {
                    bind_info = BindInformation::new(is_lazy);
                },
                BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => {
	            let symbol_library_ordinal = opcode & BIND_IMMEDIATE_MASK;
	            bind_info.symbol_library_ordinal = symbol_library_ordinal;
                },
                BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB => {
	            let symbol_library_ordinal = Uleb128::read(&self.data, offset)?;
	            bind_info.symbol_library_ordinal = symbol_library_ordinal as u8;
                },
                BIND_OPCODE_SET_DYLIB_SPECIAL_IMM => {
                    // dyld puts the immediate into the symbol_library_ordinal field...
                    let special_dylib = opcode & BIND_IMMEDIATE_MASK;
                    // Printf.printf "special_dylib: 0x%x\n" special_dylib
                    bind_info.special_dylib = special_dylib;
                },
                BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
	            let symbol_flags = opcode & BIND_IMMEDIATE_MASK;
	            let symbol_name = self.data.pread::<&str>(*offset)?;
                    *offset = *offset + symbol_name.len() + 1; // second time this \0 caused debug woes
	            bind_info.symbol_name = symbol_name;
                    bind_info.symbol_flags = symbol_flags;
                },
                BIND_OPCODE_SET_TYPE_IMM => {
	            let bind_type = opcode & BIND_IMMEDIATE_MASK;
	            bind_info.bind_type = bind_type;
                },
                BIND_OPCODE_SET_ADDEND_SLEB => {
                    let addend = Sleb128::read(&self.data, offset)?;
                    bind_info.addend = addend;
                },
                BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
	            let seg_index = opcode & BIND_IMMEDIATE_MASK;
                    // dyld sets the address to the segActualLoadAddress(segIndex) + uleb128
                    // address = segActualLoadAddress(segmentIndex) + read_uleb128(p, end);
	            let seg_offset = Uleb128::read(&self.data, offset)?;
	            bind_info.seg_index = seg_index;
                    bind_info.seg_offset = seg_offset;
                },
                BIND_OPCODE_ADD_ADDR_ULEB => {
	            let addr = Uleb128::read(&self.data, offset)?;
	            let seg_offset = bind_info.seg_offset.wrapping_add(addr);
	            bind_info.seg_offset = seg_offset;
                },
                // record the record by placing its value into our list
                BIND_OPCODE_DO_BIND => {
                    // from dyld:
                    //      if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += sizeof(intptr_t);
                    let seg_offset = bind_info.seg_offset.wrapping_add(ctx.size() as u64);
                    bind_info.seg_offset = seg_offset;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB => {
                    // dyld:
	            // if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += read_uleb128(p, end) + sizeof(intptr_t);
                    // we bind the old record, then increment bind info address for the next guy, plus the ptr offset *)
                    let addr = Uleb128::read(&self.data, offset)?;
                    let seg_offset = bind_info.seg_offset.wrapping_add(addr).wrapping_add(ctx.size() as u64);
                    bind_info.seg_offset = seg_offset;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED => {
                    // dyld:
                    // if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += immediate*sizeof(intptr_t) + sizeof(intptr_t);
	            // break;
                    // similarly, we bind the old record, then perform address manipulation for the next record
	            let scale = opcode & BIND_IMMEDIATE_MASK;
                    let size = ctx.size() as u64;
                    let seg_offset = bind_info.seg_offset.wrapping_add(scale as u64 * size).wrapping_add(size);
                    bind_info.seg_offset = seg_offset;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB => {
                    // dyld:
                    // count = read_uleb128(p, end);
	            // skip = read_uleb128(p, end);
	            // for (uint32_t i=0; i < count; ++i) {
	            // if ( address >= segmentEndAddress )
	            // throwBadBindingAddress(address, segmentEndAddress, segmentIndex, start, end, p);
	            // (this->*handler)(context, address, type, symbolName, symboFlags, addend, libraryOrdinal, "", &last);
	            // address += skip + sizeof(intptr_t);
	            // }
	            // break;
                    let count = Uleb128::read(&self.data, offset)?;
                    let skip =  Uleb128::read(&self.data, offset)?;
                    let mut addr = bind_info.seg_offset;
                    for _i  in 0..count {
                        addr += skip + ctx.size() as u64;
                    }
                    bind_info.seg_offset = addr;
                    imports.push(Import::new(&bind_info, libs, segments));
                },
                _ => {
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate log;
extern crate log4rs;

extern crate pencil;
use pencil::{Pencil, Request, Response, PencilResult};

#[macro_use] extern crate hyper;
use hyper::header::ContentLength;

use std::io::Read;

extern crate url;
use url::form_urlencoded;

extern crate core;
use core::ops::Deref;

fn hello(request: &mut Request) -> PencilResult {
    let length = {
		let ref req = request.request;
		req.headers.get::<ContentLength>().unwrap().deref();
	};
    println!("{:?}", length);
    let mut buffer = String::new();
    request.request.read_to_string(&mut buffer);
	println!("{:?}", buffer);
	let mut parse = form_urlencoded::parse(buffer.as_bytes());
	println!("{:?}", parse.find(|k| k.0 == "url"));
    Ok(Response::from("Hello World!"))
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();
    let mut app = Pencil::new("/web/hello");
    app.set_debug(true);
    app.set_log_level();
    app.post("/", "hello", hello);
    app.run("127.0.0.1:8000");
}
<commit_msg>Properly extract url from args<commit_after>#[macro_use] extern crate log;
extern crate log4rs;

extern crate pencil;
use pencil::{Pencil, Request, Response, PencilResult, PenHTTPError};
use pencil::http_errors::BadRequest;

#[macro_use] extern crate hyper;
use hyper::header::ContentLength;

use std::io::Read;

extern crate url;
use url::form_urlencoded;

extern crate core;
use core::ops::Deref;

fn streams(request: &mut Request) -> PencilResult {
	let mut buffer = String::new();
	request.request.read_to_string(&mut buffer);
	let mut parse = form_urlencoded::parse(buffer.as_bytes());
	let url = match parse.find(|k| k.0 == "url") {
		Some((_, value)) => value,
		None => return Err(PenHTTPError(BadRequest))
	};
    Ok(Response::from("Hello World!"))
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();
    let mut app = Pencil::new("");
    app.set_debug(true);
    app.set_log_level();
    app.post("/streams", "streams", streams);
    app.run("127.0.0.1:8000");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate log4rs;

#[macro_use]
extern crate nickel;
use nickel::{Request, Response, MiddlewareResult, Nickel, MediaType};
use nickel::status::StatusCode;
use nickel::router::http_router::HttpRouter;

extern crate modifier;
use modifier::Modifier;

#[macro_use]
extern crate hyper;
use hyper::header::ContentLength;

use std::io::Read;

extern crate url;
use url::form_urlencoded;

extern crate webdriver;
use webdriver::response::{WebDriverResponse, ValueResponse};

use std::time;
use std::thread;

extern crate core;

extern crate rustc_serialize;

extern crate image;
use image::GenericImage;
use std::io::Cursor;

extern crate get_if_addrs;

extern crate plugin;
extern crate typemap;

mod chromedriver;
use chromedriver::{WebdriverRequestExtensions, WebdriverSession};

use core::ops::Deref;
extern crate rand;
extern crate regex;
#[macro_use]
extern crate lazy_static;

header! { (XExtra, "X-Extra") => [String] }

impl<'a, D> Modifier<Response<'a, D>> for XExtra {
    fn modify(self, res: &mut Response<'a, D>) {
        res.headers_mut().set(self)
    }
}

fn xpath_helper(session: &WebdriverSession, xpath: String) -> Result<ValueResponse, String> {
    match session.find_element_by_xpath(xpath) {
        Err(val) => Err(format!("Error while trying to get element: {:?}", val)),
        Ok(val) => {
            match val {
                WebDriverResponse::Generic(obj) => Ok(obj),
                _ => Err(format!("Didn't expect {:?}", val)),
            }
        }
    }
}

fn streams<'a, D>(request: &mut Request<D>, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let mut buffer = String::new();
    request.origin.read_to_string(&mut buffer).unwrap();
    let mut parse = form_urlencoded::parse(buffer.as_bytes());
    let mut url = match parse.find(|k| k.0 == "url") {
        Some((_, value)) => value.into_owned(),
        None => return res.error(StatusCode::BadRequest, "No URL in request"),

    };
    let request_url = match url::Url::parse(&url) {
        Ok(value) => value,
        Err(_) => {
            return res.error(StatusCode::BadRequest,
                             format!("Request URL was dodgy: '{}'", url))
        }

    };
    let host = request_url.host_str().unwrap();
    let mut device_name: &str = "Laptop with HiDPI screen";
    let extra_fn: fn(WebdriverSession) -> String;
    let xpath = match host {
            "livestream.com" => {
                fn extra(session: WebdriverSession) -> String {
                    lazy_static! {
                        static ref RE: regex::Regex =
                            regex::Regex::new(
                                r"app-argument=http://livestream.com/accounts/(\d+)/events/(\d+)")
                        .unwrap();
                    }
                    let source = session.get_page_source();
                    let caps = RE.captures(&source).unwrap();
                    format!("[\"{}\",\"{}\"]", &caps[1], &caps[2])
                }
                extra_fn = extra;
                device_name = "Apple iPhone 5";
                "//img[@class='thumbnail_image']"
            }
            "www.ustream.tv" => {
                fn extra(session: WebdriverSession) -> String {
                    let res = xpath_helper(&session, "//video[@id='UViewer']".to_string());
                    match res {
                        Ok(val) => format!("\"{}\"", session.get_element_attribute(&val, "src")),
                        Err(val) => {
                            warn!("Error while trying to get Ustream extra data {}", val);
                            "".to_string()
                        }
                    }
                }
                extra_fn = extra;
                device_name = "Apple iPhone 5";
                "//video[@id='UViewer']"
            }
            "www.youtube.com" => {
                fn extra(_: WebdriverSession) -> String {
                    "".to_string()
                }
                extra_fn = extra;
                url = url + "?autoplay=1";
                "//div[@id='player']"
            }
            _ => {
                return res.error(StatusCode::BadRequest,
                                 format!("Request URL host ({}) wasn't in known list: '{}'",
                                         host,
                                         url))
            }

        }
        .to_string();
    let session = request.webdriver().deref().make_session(device_name);
    session.goto_url(url);
    thread::sleep(time::Duration::from_secs(5));
    let element: ValueResponse = match session.find_element_by_xpath(xpath) {
        Err(val) => {
            return res.error(StatusCode::BadRequest,
                             format!("Error while trying to get element: {:?}", val))
        }
        Ok(val) => {
            match val {
                WebDriverResponse::Generic(obj) => obj,
                _ => return res.error(StatusCode::BadRequest, format!("Didn't expect {:?}", val)),
            }
        }
    };
    let element_location = {
        let loc = session.get_element_location(&element);
        loc.unwrap()
            .find("value")
            .expect("value")
            .clone()
    };
    let element_size = {
        let size = session.get_element_size(&element);
        size.unwrap()
            .find("value")
            .expect("value")
            .clone()
    };
    let screenshot = {
        let png = session.get_screenshot_as_png();
        png.unwrap()
    };

    let cursor = Cursor::new(&screenshot);
    let mut loaded_image = image::load(cursor, image::ImageFormat::PNG).unwrap();
    let (width, height) = loaded_image.dimensions();
    debug!("Loaded image dimensions: {} x {}", width, height);
    let cropped = loaded_image.crop(
		element_location.find("x").expect("x").as_u64().expect("numeric x") as u32,
		element_location.find("y").expect("y").as_u64().expect("numeric y") as u32,
		element_size.find("width").expect("width").as_u64().expect("numeric width") as u32,
		element_size.find("height").expect("height").as_u64().expect("numeric height") as u32);

    let mut output_buffer: Vec<u8> = Vec::new();
    cropped.save(&mut output_buffer, image::ImageFormat::PNG).unwrap();

    let extra = extra_fn(session);
    res.set(XExtra(extra));

    res.set(MediaType::Png);
    res.set(ContentLength(output_buffer.len() as u64));
    res.send(output_buffer)
}

fn run(ip: std::net::IpAddr, port: u16, client: chromedriver::Webdriver) {
    let mut server = Nickel::new();
    server.utilize(chromedriver::WebdriverMiddleware::new(client));
    server.post("/streams", streams);
    server.listen((ip, port));
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();
    let port = 8000;
    let mut handles = Vec::new();
    for iface in get_if_addrs::get_if_addrs().unwrap() {
        handles.push(::std::thread::spawn(move || {
            let client = chromedriver::Webdriver::new();
            let ip = iface.ip();
            info!("Listening on {}:{} for {}", ip, port, iface.name);
            run(ip, port, client);
        }));
    }

    info!("All listeners spawned");

    for handle in handles {
        handle.join().unwrap();
    }
}
<commit_msg>Cope with floating-point size/locations<commit_after>#[macro_use]
extern crate log;
extern crate log4rs;

#[macro_use]
extern crate nickel;
use nickel::{Request, Response, MiddlewareResult, Nickel, MediaType};
use nickel::status::StatusCode;
use nickel::router::http_router::HttpRouter;

extern crate modifier;
use modifier::Modifier;

#[macro_use]
extern crate hyper;
use hyper::header::ContentLength;

use std::io::Read;

extern crate url;
use url::form_urlencoded;

extern crate webdriver;
use webdriver::response::{WebDriverResponse, ValueResponse};

use std::time;
use std::thread;

extern crate core;

extern crate rustc_serialize;

extern crate image;
use image::GenericImage;
use std::io::Cursor;

extern crate get_if_addrs;

extern crate plugin;
extern crate typemap;

mod chromedriver;
use chromedriver::{WebdriverRequestExtensions, WebdriverSession};

use core::ops::Deref;
extern crate rand;
extern crate regex;
#[macro_use]
extern crate lazy_static;

header! { (XExtra, "X-Extra") => [String] }

impl<'a, D> Modifier<Response<'a, D>> for XExtra {
    fn modify(self, res: &mut Response<'a, D>) {
        res.headers_mut().set(self)
    }
}

fn xpath_helper(session: &WebdriverSession, xpath: String) -> Result<ValueResponse, String> {
    match session.find_element_by_xpath(xpath) {
        Err(val) => Err(format!("Error while trying to get element: {:?}", val)),
        Ok(val) => {
            match val {
                WebDriverResponse::Generic(obj) => Ok(obj),
                _ => Err(format!("Didn't expect {:?}", val)),
            }
        }
    }
}

fn streams<'a, D>(request: &mut Request<D>, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> {
    let mut buffer = String::new();
    request.origin.read_to_string(&mut buffer).unwrap();
    let mut parse = form_urlencoded::parse(buffer.as_bytes());
    let mut url = match parse.find(|k| k.0 == "url") {
        Some((_, value)) => value.into_owned(),
        None => return res.error(StatusCode::BadRequest, "No URL in request"),

    };
    let request_url = match url::Url::parse(&url) {
        Ok(value) => value,
        Err(_) => {
            return res.error(StatusCode::BadRequest,
                             format!("Request URL was dodgy: '{}'", url))
        }

    };
    let host = request_url.host_str().unwrap();
    let mut device_name: &str = "Laptop with HiDPI screen";
    let extra_fn: fn(WebdriverSession) -> String;
    let xpath = match host {
            "livestream.com" => {
                fn extra(session: WebdriverSession) -> String {
                    lazy_static! {
                        static ref RE: regex::Regex =
                            regex::Regex::new(
                                r"app-argument=http://livestream.com/accounts/(\d+)/events/(\d+)")
                        .unwrap();
                    }
                    let source = session.get_page_source();
                    let caps = RE.captures(&source).unwrap();
                    format!("[\"{}\",\"{}\"]", &caps[1], &caps[2])
                }
                extra_fn = extra;
                device_name = "Apple iPhone 5";
                "//img[@class='thumbnail_image']"
            }
            "www.ustream.tv" => {
                fn extra(session: WebdriverSession) -> String {
                    let res = xpath_helper(&session, "//video[@id='UViewer']".to_string());
                    match res {
                        Ok(val) => format!("\"{}\"", session.get_element_attribute(&val, "src")),
                        Err(val) => {
                            warn!("Error while trying to get Ustream extra data {}", val);
                            "".to_string()
                        }
                    }
                }
                extra_fn = extra;
                device_name = "Apple iPhone 5";
                "//video[@id='UViewer']"
            }
            "www.youtube.com" => {
                fn extra(_: WebdriverSession) -> String {
                    "".to_string()
                }
                extra_fn = extra;
                url = url + "?autoplay=1";
                "//div[@id='player']"
            }
            _ => {
                return res.error(StatusCode::BadRequest,
                                 format!("Request URL host ({}) wasn't in known list: '{}'",
                                         host,
                                         url))
            }

        }
        .to_string();
    let session = request.webdriver().deref().make_session(device_name);
    session.goto_url(url);
    thread::sleep(time::Duration::from_secs(5));
    let element: ValueResponse = match session.find_element_by_xpath(xpath) {
        Err(val) => {
            return res.error(StatusCode::BadRequest,
                             format!("Error while trying to get element: {:?}", val))
        }
        Ok(val) => {
            match val {
                WebDriverResponse::Generic(obj) => obj,
                _ => return res.error(StatusCode::BadRequest, format!("Didn't expect {:?}", val)),
            }
        }
    };
    let element_location = {
        let loc = session.get_element_location(&element);
        loc.unwrap()
            .find("value")
            .expect("value")
            .clone()
    };
    let element_size = {
        let size = session.get_element_size(&element);
        size.unwrap()
            .find("value")
            .expect("value")
            .clone()
    };
    let screenshot = {
        let png = session.get_screenshot_as_png();
        png.unwrap()
    };

    let cursor = Cursor::new(&screenshot);
    let mut loaded_image = image::load(cursor, image::ImageFormat::PNG).unwrap();
    let (width, height) = loaded_image.dimensions();
    debug!("Loaded image dimensions: {} x {}", width, height);
    let cropped = loaded_image.crop(
		element_location.find("x").expect("x").as_f64().expect("numeric x") as u32,
		element_location.find("y").expect("y").as_f64().expect("numeric y") as u32,
		element_size.find("width").expect("width").as_f64().expect("numeric width") as u32,
		element_size.find("height").expect("height").as_f64().expect("numeric height") as u32);

    let mut output_buffer: Vec<u8> = Vec::new();
    cropped.save(&mut output_buffer, image::ImageFormat::PNG).unwrap();

    let extra = extra_fn(session);
    res.set(XExtra(extra));

    res.set(MediaType::Png);
    res.set(ContentLength(output_buffer.len() as u64));
    res.send(output_buffer)
}

fn run(ip: std::net::IpAddr, port: u16, client: chromedriver::Webdriver) {
    let mut server = Nickel::new();
    server.utilize(chromedriver::WebdriverMiddleware::new(client));
    server.post("/streams", streams);
    server.listen((ip, port));
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();
    let port = 8000;
    let mut handles = Vec::new();
    for iface in get_if_addrs::get_if_addrs().unwrap() {
        handles.push(::std::thread::spawn(move || {
            let client = chromedriver::Webdriver::new();
            let ip = iface.ip();
            info!("Listening on {}:{} for {}", ip, port, iface.name);
            run(ip, port, client);
        }));
    }

    info!("All listeners spawned");

    for handle in handles {
        handle.join().unwrap();
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::CString;
use std::path::PathBuf;
use std::process::{Command, exit, Stdio};
use std::time::Instant;

use crate::argument::Argument;
use crate::core::*;

const TMUX: &str = "tmux";

pub struct Tmux<'a> {
    nmk_dir: &'a PathBuf,
    tmux_dir: PathBuf,
    bin: String,
    version: String,
}

impl<'a> Tmux<'a> {
    pub fn new(nmk_dir: &PathBuf, tmux_dir: PathBuf) -> Tmux {
        let mut version: String;

        if let Ok(o) = Command::new(TMUX).arg("-V").output() {
            if !o.status.success() {
                match o.status.code() {
                    Some(i) => error!("tmux exit with status: {}", i),
                    None => error!("terminated by signal"),
                };
                exit(1);
            }
            let res = String::from_utf8_lossy(&o.stdout);
            let sp: Vec<_> = res.trim().split(" ").collect();
            if sp.len() != 2 {
                error!("can't find tmux version from: {}", res);
                exit(1);
            }
            version = String::from(sp[1]);
        } else {
            error!("{} not found", TMUX);
            exit(1);
        }
        Tmux {
            nmk_dir,
            tmux_dir,
            bin: which::which(TMUX).unwrap().to_str().unwrap().to_string(),
            version,
        }
    }

    pub fn version(&self) -> &str {
        &self.version
    }

    fn conf(&self) -> PathBuf {
        let conf_file = format!("{}.conf", &self.version);
        let conf_path = self.tmux_dir.join(conf_file);
        if !conf_path.exists() {
            error!("tmux {} is not supported", &self.version)
        }
        conf_path
    }

    pub fn setup(&self, arg: &Argument) {
        set_env("NMK_TMUX_DEFAULT_SHELL", which::which("zsh").expect("zsh not found"));
        set_env("NMK_TMUX_DETACH_ON_DESTROY", on_off!(arg.detach_on_destroy));
        set_env("NMK_TMUX_HISTORY", self.nmk_dir.join("tmux").join(".tmux_history"));
        set_env("NMK_TMUX_VERSION", &self.version);
    }

    fn print_usage_time(&self, arg: &Argument, start: &Instant) {
        let before_exec = start.elapsed().as_millis();
        if arg.usage {
            println!("{}", before_exec);
        } else {
            debug!("usage time: {}ms", before_exec);
        }
    }

    pub fn login_shell(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();

        vec.push(self.bin.as_str());
        vec.push("-L");
        vec.push(arg.socket());
        if arg.force256color {
            vec.push("-2");
        }
        vec.push("-f");
        let config = self.conf();
        vec.push(config.to_str().unwrap());
        vec.push("-c");
        vec.push("exec zsh --login");
        let exec_args: Vec<_> = vec.into_iter().flat_map(|x| CString::new(x)).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execvp(&exec_name, &exec_args).is_err() {
            error!("Can't start login shell")
        }
        // this code is never reach if exec success
        exit(1);
    }

    pub fn exec(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();
        let config = self.conf();
        vec.push(self.bin.as_str());
        vec.push("-L");
        let socket = arg.socket();
        vec.push(socket);
        if arg.force256color {
            vec.push("-2");
        }
        let tmux_args = arg.tmux_args();
        if is_running(socket) {
            if tmux_args.len() > 0 {
                vec.extend(tmux_args);
            } else {
                if env::var_os("TMUX").is_some() && !arg.inception {
                    warn!("add --inception to allow nested tmux sessions");
                    exit(1);
                }
                vec.push("attach");
            }
        } else {
            vec.push("-f");
            vec.push(config.to_str().unwrap());
            vec.extend(tmux_args);
        }
        let exec_args: Vec<_> = vec.into_iter().flat_map(|x| CString::new(x)).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execvp(&exec_name, &exec_args).is_err() {
            error!("Can't start tmux")
        }
        // this code is never reach if exec success
        exit(1);
    }
}

pub fn is_running(socket: &str) -> bool {
    let running = Command::new(TMUX)
        .arg("-L")
        .arg(socket)
        .arg("list-sessions")
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
        .map(|o| o.success())
        .unwrap_or_default();
    debug!("server {} running", if running { "is" } else { "is not" });
    running
}

pub fn dir(nmk_dir: &PathBuf) -> PathBuf {
    let path = nmk_dir.join("tmux");
    if !path.exists() {
        panic!("{:?} doesn't exist", path);
    }
    path
}
<commit_msg>nmk.rs: remove from_utf8_lossy<commit_after>use std::env;
use std::ffi::CString;
use std::path::PathBuf;
use std::process::{Command, exit, Stdio};
use std::time::Instant;

use crate::argument::Argument;
use crate::core::*;

const TMUX: &str = "tmux";

pub struct Tmux<'a> {
    nmk_dir: &'a PathBuf,
    tmux_dir: PathBuf,
    bin: String,
    version: String,
}

impl<'a> Tmux<'a> {
    pub fn new(nmk_dir: &PathBuf, tmux_dir: PathBuf) -> Tmux {
        Tmux {
            nmk_dir,
            tmux_dir,
            bin: which::which(TMUX).unwrap().to_str().unwrap().to_string(),
            version: Tmux::call_check_version(),
        }
    }

    pub fn version(&self) -> &str {
        &self.version
    }

    fn conf(&self) -> PathBuf {
        let conf_file = format!("{}.conf", &self.version);
        let conf_path = self.tmux_dir.join(conf_file);
        if !conf_path.exists() {
            error!("tmux {} is not supported", &self.version)
        }
        conf_path
    }

    pub fn setup(&self, arg: &Argument) {
        set_env("NMK_TMUX_DEFAULT_SHELL", which::which("zsh").expect("zsh not found"));
        set_env("NMK_TMUX_DETACH_ON_DESTROY", on_off!(arg.detach_on_destroy));
        set_env("NMK_TMUX_HISTORY", self.nmk_dir.join("tmux").join(".tmux_history"));
        set_env("NMK_TMUX_VERSION", &self.version);
    }

    fn print_usage_time(&self, arg: &Argument, start: &Instant) {
        let before_exec = start.elapsed().as_millis();
        if arg.usage {
            println!("{}", before_exec);
        } else {
            debug!("usage time: {}ms", before_exec);
        }
    }

    fn call_check_version() -> String {
        if let Ok(o) = Command::new(TMUX).arg("-V").output() {
            if !o.status.success() {
                match o.status.code() {
                    Some(i) => error!("tmux exit with status: {}", i),
                    None => error!("terminated by signal"),
                };
                exit(1);
            }
            let version_output = String::from_utf8(o.stdout)
                .expect("tmux version output contain non utf-8");
            version_output.trim().split(" ")
                .nth(1).expect(&format!("bad output: {}", version_output))
                .to_string()
        } else {
            error!("{} not found", TMUX);
            exit(1);
        }
    }

    pub fn login_shell(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();

        vec.push(self.bin.as_str());
        vec.push("-L");
        vec.push(arg.socket());
        if arg.force256color {
            vec.push("-2");
        }
        vec.push("-f");
        let config = self.conf();
        vec.push(config.to_str().unwrap());
        vec.push("-c");
        vec.push("exec zsh --login");
        let exec_args: Vec<_> = vec.into_iter().flat_map(|x| CString::new(x)).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execvp(&exec_name, &exec_args).is_err() {
            error!("Can't start login shell")
        }
        // this code is never reach if exec success
        exit(1);
    }

    pub fn exec(&self, arg: Argument, start: Instant) -> ! {
        let mut vec = Vec::new();
        let config = self.conf();
        vec.push(self.bin.as_str());
        vec.push("-L");
        let socket = arg.socket();
        vec.push(socket);
        if arg.force256color {
            vec.push("-2");
        }
        let tmux_args = arg.tmux_args();
        if is_running(socket) {
            if tmux_args.len() > 0 {
                vec.extend(tmux_args);
            } else {
                if env::var_os("TMUX").is_some() && !arg.inception {
                    warn!("add --inception to allow nested tmux sessions");
                    exit(1);
                }
                vec.push("attach");
            }
        } else {
            vec.push("-f");
            vec.push(config.to_str().unwrap());
            vec.extend(tmux_args);
        }
        let exec_args: Vec<_> = vec.into_iter().flat_map(|x| CString::new(x)).collect();
        let exec_name = CString::new(self.bin.as_bytes()).unwrap();
        debug!("{:#?}", exec_name);
        debug!("{:#?}", exec_args);
        self.print_usage_time(&arg, &start);
        if nix::unistd::execvp(&exec_name, &exec_args).is_err() {
            error!("Can't start tmux")
        }
        // this code is never reach if exec success
        exit(1);
    }
}

pub fn is_running(socket: &str) -> bool {
    let running = Command::new(TMUX)
        .arg("-L")
        .arg(socket)
        .arg("list-sessions")
        .stderr(Stdio::null())
        .stdout(Stdio::null())
        .status()
        .map(|o| o.success())
        .unwrap_or_default();
    debug!("server {} running", if running { "is" } else { "is not" });
    running
}

pub fn dir(nmk_dir: &PathBuf) -> PathBuf {
    let path = nmk_dir.join("tmux");
    if !path.exists() {
        panic!("{:?} doesn't exist", path);
    }
    path
}
<|endoftext|>


<commit_before>use alloc::boxed::Box;

use schemes::{Result, KScheme, Resource, Url, VecResource};

pub struct InterruptScheme;

impl KScheme for InterruptScheme {
    fn scheme(&self) -> &str {
        "interrupt"
    }

    fn open(&mut self, _: &Url, _: usize) -> Result<Box<Resource>> {
        let mut string = format!("{:<6}{:<16}{}", "INT", "COUNT", "DESCRIPTION");

        {
            let interrupts = ::env().interrupts.lock();
            for interrupt in 0..interrupts.len() {
                let count = interrupts[interrupt];

                if count > 0 {
                    let description = match interrupt {
                        0x20 => "Programmable Interrupt Timer",
                        0x21 => "Keyboard",
                        0x22 => "Cascade",
                        0x23 => "Serial 2 and 4",
                        0x24 => "Serial 1 and 3",
                        0x25 => "Parallel 2",
                        0x26 => "Floppy",
                        0x27 => "Parallel 1",
                        0x28 => "Realtime Clock",
                        0x29 => "PCI 1",
                        0x2A => "PCI 2",
                        0x2B => "PCI 3",
                        0x2C => "Mouse",
                        0x2D => "Coprocessor",
                        0x2E => "IDE Primary",
                        0x2F => "IDE Secondary",
                        0x80 => "System Call",
                        0x0 => "Divide by zero exception",
                        0x1 => "Debug exception",
                        0x2 => "Non-maskable interrupt",
                        0x3 => "Breakpoint exception",
                        0x4 => "Overflow exception",
                        0x5 => "Bound range exceeded exception",
                        0x6 => "Invalid opcode exception",
                        0x7 => "Device not available exception",
                        0x8 => "Double fault",
                        0xA => "Invalid TSS exception",
                        0xB => "Segment not present exception",
                        0xC => "Stack-segment fault",
                        0xD => "General protection fault",
                        0xE => "Page fault",
                        0x10 => "x87 floating-point exception",
                        0x11 => "Alignment check exception",
                        0x12 => "Machine check exception",
                        0x13 => "SIMD floating-point exception",
                        0x14 => "Virtualization exception",
                        0x1E => "Security exception",
                        _ => "Unknown Interrupt",
                    };

                    string = string + "\n" + &format!("{:<6X}{:<16}{}", interrupt, count, description);
                }
            }
        }

        Ok(box VecResource::new(Url::from_str("interrupt:"), string.into_bytes()))
    }
}
<commit_msg>Correct mispelling of PIT<commit_after>use alloc::boxed::Box;

use schemes::{Result, KScheme, Resource, Url, VecResource};

pub struct InterruptScheme;

impl KScheme for InterruptScheme {
    fn scheme(&self) -> &str {
        "interrupt"
    }

    fn open(&mut self, _: &Url, _: usize) -> Result<Box<Resource>> {
        let mut string = format!("{:<6}{:<16}{}", "INT", "COUNT", "DESCRIPTION");

        {
            let interrupts = ::env().interrupts.lock();
            for interrupt in 0..interrupts.len() {
                let count = interrupts[interrupt];

                if count > 0 {
                    let description = match interrupt {
                        0x20 => "Programmable Interval Timer",
                        0x21 => "Keyboard",
                        0x22 => "Cascade",
                        0x23 => "Serial 2 and 4",
                        0x24 => "Serial 1 and 3",
                        0x25 => "Parallel 2",
                        0x26 => "Floppy",
                        0x27 => "Parallel 1",
                        0x28 => "Realtime Clock",
                        0x29 => "PCI 1",
                        0x2A => "PCI 2",
                        0x2B => "PCI 3",
                        0x2C => "Mouse",
                        0x2D => "Coprocessor",
                        0x2E => "IDE Primary",
                        0x2F => "IDE Secondary",
                        0x80 => "System Call",
                        0x0 => "Divide by zero exception",
                        0x1 => "Debug exception",
                        0x2 => "Non-maskable interrupt",
                        0x3 => "Breakpoint exception",
                        0x4 => "Overflow exception",
                        0x5 => "Bound range exceeded exception",
                        0x6 => "Invalid opcode exception",
                        0x7 => "Device not available exception",
                        0x8 => "Double fault",
                        0xA => "Invalid TSS exception",
                        0xB => "Segment not present exception",
                        0xC => "Stack-segment fault",
                        0xD => "General protection fault",
                        0xE => "Page fault",
                        0x10 => "x87 floating-point exception",
                        0x11 => "Alignment check exception",
                        0x12 => "Machine check exception",
                        0x13 => "SIMD floating-point exception",
                        0x14 => "Virtualization exception",
                        0x1E => "Security exception",
                        _ => "Unknown Interrupt",
                    };

                    string = string + "\n" + &format!("{:<6X}{:<16}{}", interrupt, count, description);
                }
            }
        }

        Ok(box VecResource::new(Url::from_str("interrupt:"), string.into_bytes()))
    }
}
<|endoftext|>