<commit_before>
mod dt;
mod error;

// xxx : remove include
mod former
{
  include!( "./former/front_test.rs" );
}

mod derive;
mod meta;
mod options;
mod string;
mod test;
mod time;

mod typing
{
  #[ cfg_attr( feature = "nightly", feature( type_name_of_val ) ) ]
  mod implements_test
  {
    #[ allow( unused_imports ) ]
    use wtools::typing as TheModule;
    include!( "./typing/common/implements_test.rs" );
  }
  mod is_slice_test
  {
    #[ allow( unused_imports ) ]
    use wtools::typing as TheModule;
    include!( "./typing/common/is_slice_test.rs" );
  }
  mod inspect_type_test
  {
    #[ allow( unused_imports ) ]
    use wtools::typing as TheModule;
    include!( "./typing/common/inspect_type_test.rs" );
  }
}

// #[ cfg( feature = "proc_macro" ) ]
// mod proc_macro;
// mod vector;
<commit_msg>Improve tests of module `wtools`, disable unused feature<commit_after>
mod dt;
mod error;

// xxx : remove include
mod former
{
  include!( "./former/front_test.rs" );
}

mod derive;
mod meta;
mod options;
mod string;
mod test;
mod time;

mod typing
{
  // #![ cfg_attr( feature = "nightly", feature( type_name_of_val ) ) ]
  mod implements_test
  {
    #[ allow( unused_imports ) ]
    use wtools::typing as TheModule;
    include!( "./typing/common/implements_test.rs" );
  }
  mod is_slice_test
  {
    #[ allow( unused_imports ) ]
    use wtools::typing as TheModule;
    include!( "./typing/common/is_slice_test.rs" );
  }
  mod inspect_type_test
  {
    #[ allow( unused_imports ) ]
    use wtools::typing as TheModule;
    include!( "./typing/common/inspect_type_test.rs" );
  }
}

// #[ cfg( feature = "proc_macro" ) ]
// mod proc_macro;
// mod vector;
<|endoftext|>


<commit_before>extern crate time;

use std::io::File;
use std::io::BufferedReader;
use time::precise_time_ns;

#[deriving(Clone, Show)]
struct Route{
  dest: i32,
  cost: i32
}

#[deriving(Clone, Show)]
struct Node {
  neighbours: Vec<Route>
}

fn read_places(num_nodes: &mut uint) ->Vec<Node>{
  let path = Path::new("agraph");
  let mut file = BufferedReader::new(File::open(&path));
  let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
  *num_nodes = from_str(lines[0].as_slice().trim()).expect("Error, first line of file should describe the amount of nodes");
  let mut nodes: Vec<Node> = Vec::from_fn(*num_nodes, |_| Node{neighbours: vec![]});
  for ln in lines.slice(1,lines.len()).iter(){
    let nums: Vec<&str> = ln.as_slice().split(' ').collect();
    if nums.len() < 3{
      break;
    }
    let node: uint = from_str(nums[0]).expect("Error: node id was not a uint");
    let neighbour: i32 = from_str(nums[1]).expect("Error: neighbour id was not an int");
    let cost: i32 = from_str(nums[2]).expect("Error: route cost was not an int");
    let mut newnode = nodes[node].clone();
    newnode.neighbours.push(Route{dest: neighbour, cost: cost});
    let mut newnodes = Vec::with_capacity(*num_nodes);
    for i in range(0u, *num_nodes){
      newnodes.push(if i == node{ newnode.clone()} else {nodes[i].clone()});
    }
    nodes = newnodes;
  }
  nodes
}

fn get_longest_path(nodes: &Vec<Node>, nodeID: i32, visited: *const bool) -> i32{
  let uintID = nodeID.to_uint().expect("Error, something had a negative node id");
  unsafe{
    let newAddr: uint = (visited as uint) + (uintID as uint);
    let newAddrP: *mut bool = newAddr as *mut bool;
    *newAddrP = true;
  }
  let mut dist: i32;
  let mut max: i32 = 0;
  for neighbour in nodes[uintID].neighbours.iter(){
    let udest = neighbour.dest.to_uint().expect("Almost done..");
    let isVisited: bool;
    unsafe{
      let newAddr: uint = udest + (visited as uint);
      let newAddrP: *mut bool = newAddr as *mut bool;
      isVisited = *newAddrP
    }
    if !isVisited{
      dist = neighbour.cost + get_longest_path(nodes, neighbour.dest, visited);
      if dist > max{
	max = dist;
      }
    }
  }
  unsafe{
    let newAddr: uint = (visited as uint) + (uintID as uint);
    let newAddrP: *mut bool = newAddr as *mut bool;
    *newAddrP = false;
  }
  max
}

fn main(){
   let mut num_nodes = 0;
   let nodes = read_places(&mut num_nodes);
   let mut visited: Vec<bool> = Vec::from_fn(num_nodes, |_| false);
   let startTime = precise_time_ns();
   let path = get_longest_path(&nodes, 0, &visited[0] as *const bool);
   let duration = (precise_time_ns() - startTime) / 1000000;
   println!("{} LANGUAGE Rust {}", path, duration);
}<commit_msg>Remove unsafe code and use as for type conversions.<commit_after>extern crate time;

use std::io::File;
use std::io::BufferedReader;
use time::precise_time_ns;

#[deriving(Clone, Show)]
struct Route{
  dest: i32,
  cost: i32
}

#[deriving(Clone, Show)]
struct Node {
  neighbours: Vec<Route>
}

fn read_places(num_nodes: &mut uint) ->Vec<Node>{
  let path = Path::new("agraph");
  let mut file = BufferedReader::new(File::open(&path));
  let lines: Vec<String> = file.lines().map(|x| x.unwrap()).collect();
  *num_nodes = from_str(lines[0].as_slice().trim()).expect("Error, first line of file should describe the amount of nodes");
  let mut nodes: Vec<Node> = Vec::from_fn(*num_nodes, |_| Node{neighbours: vec![]});
  for ln in lines.slice(1,lines.len()).iter(){
    let nums: Vec<&str> = ln.as_slice().split(' ').collect();
    if nums.len() < 3{
      break;
    }
    let node: uint = from_str(nums[0]).expect("Error: node id was not a uint");
    let neighbour: i32 = from_str(nums[1]).expect("Error: neighbour id was not an int");
    let cost: i32 = from_str(nums[2]).expect("Error: route cost was not an int");
    let mut newnode = nodes[node].clone();
    newnode.neighbours.push(Route{dest: neighbour, cost: cost});
    let mut newnodes = Vec::with_capacity(*num_nodes);
    for i in range(0u, *num_nodes){
      newnodes.push(if i == node{ newnode.clone()} else {nodes[i].clone()});
    }
    nodes = newnodes;
  }
  nodes
}

fn get_longest_path(nodes: &Vec<Node>, node_id: uint, visited: &mut [bool]) -> i32 {
    visited[node_id] = true;
    let mut max: i32 = 0;
    for neighbour in nodes[node_id].neighbours.iter() {
        let is_visited = visited[neighbour.dest as uint];
        if !is_visited {
            let dist = neighbour.cost + get_longest_path(nodes, neighbour.dest as uint, visited);
            if dist > max{
                max = dist;
            }
        }
    }
    visited[node_id] = false;
    max
}

fn main(){
   let mut num_nodes = 0;
   let nodes = read_places(&mut num_nodes);
   let mut visited: Vec<bool> = Vec::from_fn(num_nodes, |_| false);
   let startTime = precise_time_ns();
   let path = get_longest_path(&nodes, 0, visited.as_mut_slice());
   let duration = (precise_time_ns() - startTime) / 1000000;
   println!("{} LANGUAGE Rust {}", path, duration);
}
<|endoftext|>


<commit_before>use std::collections::hash_set::HashSet;
use std::iter::FromIterator;

use api::server_data::ServerData;
use api::result::*;
use web::data::APIGeneSummary;

use types::GeneUniquename;

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum IntRangeType {
#[serde(rename = "genome_range_contains")]
    GenomeRangeContains,
#[serde(rename = "protein_length")]
    ProteinLength,
#[serde(rename = "tm_domain_count")]
    TMDomainCount,
#[serde(rename = "exon_count")]
    ExonCount,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum FloatRangeType {
#[serde(rename = "protein_mol_weight")]
    ProteinMolWeight,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum SingleOrMultiAllele {
#[serde(rename = "single")]
    Single,
#[serde(rename = "multi")]
    Multi,
#[serde(rename = "both")]
    Both,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum QueryExpressionFilter {
#[serde(rename = "any")]
    Any,
#[serde(rename = "null")]
    Null,
#[serde(rename = "wt-overexpressed")]
    WtOverexpressed,
}

type TermName = String;
type QueryRowsResult = Result<Vec<ResultRow>, String>;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum QueryNode {
#[serde(rename = "or")]
    Or(Vec<QueryNode>),
#[serde(rename = "and")]
    And(Vec<QueryNode>),
#[serde(rename = "not")]
    Not { node_a: Box<QueryNode>, node_b: Box<QueryNode> },
#[serde(rename = "term")]
    Term {
        termid: String,
        name: Option<TermName>,
        single_or_multi_allele: Option<SingleOrMultiAllele>,
        expression: Option<QueryExpressionFilter>,
    },
#[serde(rename = "subset")]
    Subset { subset_name: String },
#[serde(rename = "gene_list")]
    GeneList { ids: Vec<GeneUniquename> },
#[serde(rename = "int_range")]
    IntRange { range_type: IntRangeType, start: Option<u64>, end: Option<u64> },
#[serde(rename = "float_range")]
    FloatRange { range_type: FloatRangeType, start: Option<f64>, end: Option<f64> },
}

fn exec_or(server_data: &ServerData, nodes: &Vec<QueryNode>) -> QueryRowsResult {
    if nodes.len() == 0 {
        return Err("illegal query: OR operator has no nodes".into());
    }

    let mut seen_genes = HashSet::new();
    let mut or_rows = vec![];

    for node in nodes {
        let exec_rows = node.exec(server_data)?;

        for node_row in &exec_rows {
            if !seen_genes.contains(&node_row.gene_uniquename) {
                or_rows.push(ResultRow {
                    sequence: None,
                    gene_uniquename: node_row.gene_uniquename.clone(),
                });
                seen_genes.insert(node_row.gene_uniquename.clone());
            }
        }
    }

    Ok(or_rows)
}

fn exec_and(server_data: &ServerData, nodes: &Vec<QueryNode>) -> QueryRowsResult {
    if nodes.len() == 0 {
        return Err("illegal query: AND operator has no nodes".into());
    }

    let first_node_result = nodes[0].exec(server_data)?;

    let current_genes =
        first_node_result.into_iter().map(|row| row.gene_uniquename);

    let mut current_gene_set =
        HashSet::from_iter(current_genes);

    for node in nodes[1..].iter() {
        let node_result = node.exec(server_data)?;

        let node_genes =
            node_result.into_iter().map(|row| row.gene_uniquename)
            .collect::<HashSet<_>>();

        current_gene_set = current_gene_set.intersection(&node_genes).cloned().collect();
    }

    Ok(current_gene_set.iter().map(|gene_uniquename| ResultRow {
        sequence: None,
        gene_uniquename: gene_uniquename.clone()
    }).collect())
}

fn exec_not(server_data: &ServerData, node_a: &QueryNode, node_b: &QueryNode)
            -> QueryRowsResult
{
    let node_b_result = node_b.exec(server_data)?;

    let node_b_gene_set: HashSet<GeneUniquename> =
        HashSet::from_iter(node_b_result.into_iter().map(|row| row.gene_uniquename));

    let node_a_result = node_a.exec(server_data)?;

    let mut not_rows = vec![];

    for row in &node_a_result {
        if !node_b_gene_set.contains(&row.gene_uniquename) {
            not_rows.push(ResultRow {
                sequence: None,
                gene_uniquename: row.gene_uniquename.clone(),
            });
        }
    }

    Ok(not_rows)
}

fn results_from_gene_vec(genes: Vec<GeneUniquename>) -> QueryRowsResult {
    Ok(genes.into_iter()
       .map(|gene_uniquename| ResultRow {
           sequence: None,
           gene_uniquename: gene_uniquename,
       }).collect::<Vec<_>>())
}

fn exec_termid(server_data: &ServerData, term_id: &str,
               maybe_single_or_multi_allele: &Option<SingleOrMultiAllele>,
               expression: &Option<QueryExpressionFilter>) -> QueryRowsResult {
    if let Some(ref single_or_multi_allele) = *maybe_single_or_multi_allele {
        let genes = server_data.genes_of_genotypes(term_id, single_or_multi_allele,
                                                   expression);
        Ok(genes.into_iter()
           .map(|gene_uniquename| ResultRow {
               sequence: None,
               gene_uniquename: gene_uniquename.clone(),
           }).collect::<Vec<_>>())
    } else {
        results_from_gene_vec(server_data.genes_of_termid(term_id))
    }
}

fn exec_subset(server_data: &ServerData, subset_name: &str) -> QueryRowsResult {
    results_from_gene_vec(server_data.genes_of_subset(subset_name))
}

fn exec_gene_list(gene_uniquenames: &Vec<GeneUniquename>) -> QueryRowsResult {
    results_from_gene_vec(gene_uniquenames.clone())
}

fn exec_genome_range_overlaps(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                              -> QueryRowsResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if let Some(ref location) = gene.location {
                (range_end.is_none() || location.start_pos as u64 <= range_end.unwrap()) &&
                (range_start.is_none() || location.end_pos as u64 >= range_start.unwrap())
            } else {
                false
            }
        });
    results_from_gene_vec(gene_uniquenames)
}

fn exec_protein_length_range(server_data: &ServerData,
                             range_start: Option<u64>, range_end: Option<u64>)
                             -> QueryRowsResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() || protein.sequence.len() as u64 >= range_start.unwrap()) &&
                    (range_end.is_none() || protein.sequence.len() as u64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    results_from_gene_vec(gene_uniquenames)
}

fn exec_tm_domain_count_range(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                              -> QueryRowsResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.tm_domain_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.tm_domain_count as u64 <= range_end.unwrap())
        });
    results_from_gene_vec(gene_uniquenames)
}

fn exec_exon_count_range(server_data: &ServerData,
                         range_start: Option<u64>, range_end: Option<u64>)
                         -> QueryRowsResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.exon_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.exon_count as u64 <= range_end.unwrap())
        });
    results_from_gene_vec(gene_uniquenames)
}

fn exec_int_range(server_data: &ServerData, range_type: &IntRangeType,
                  start: Option<u64>, end: Option<u64>) -> QueryRowsResult {
    match *range_type {
        IntRangeType::GenomeRangeContains => exec_genome_range_overlaps(server_data, start, end),
        IntRangeType::ProteinLength => exec_protein_length_range(server_data, start, end),
        IntRangeType::TMDomainCount => exec_tm_domain_count_range(server_data, start, end),
        IntRangeType::ExonCount => exec_exon_count_range(server_data, start, end),
    }
}

fn exec_mol_weight_range(server_data: &ServerData, range_start: Option<f64>, range_end: Option<f64>)
                         -> QueryRowsResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() ||
                        protein.molecular_weight as f64 >= range_start.unwrap()) &&
                    (range_end.is_none() ||
                        protein.molecular_weight as f64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    results_from_gene_vec(gene_uniquenames)
}

fn exec_float_range(server_data: &ServerData, range_type: &FloatRangeType,
                    start: Option<f64>, end: Option<f64>) -> QueryRowsResult {
    match *range_type {
        FloatRangeType::ProteinMolWeight => exec_mol_weight_range(server_data, start, end)
    }
}

impl QueryNode {
    pub fn exec(&self, server_data: &ServerData) -> QueryRowsResult {
        use self::QueryNode::*;
        match *self {
            Or(ref nodes) => exec_or(server_data, nodes),
            And(ref nodes) => exec_and(server_data, nodes),
            Not { ref node_a, ref node_b } => exec_not(server_data, node_a, node_b),
            Term {
                ref termid,
                name: _,
                ref single_or_multi_allele,
                ref expression,
            } => exec_termid(server_data, termid, single_or_multi_allele, expression),
            Subset { ref subset_name } => exec_subset(server_data, subset_name),
            GeneList { ref ids } => exec_gene_list(ids),
            IntRange { ref range_type, start, end } =>
                exec_int_range(server_data, range_type, start, end),
            FloatRange { ref range_type, start, end } =>
                exec_float_range(server_data, range_type, start, end),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SeqType {
#[serde(rename = "protein")]
    Protein,
#[serde(rename = "nucleotide")]
    Nucleotide {
        include_introns: bool,
        include_5_prime_utr: bool,
        include_3_prime_utr: bool,
    },
    None,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct QueryOutputOptions {
    pub sequence: SeqType,
    pub field_names: Vec<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Query {
    output_options: QueryOutputOptions,
    constraints: QueryNode,
}

impl Query {
    pub fn new(constraints: QueryNode, output_options: QueryOutputOptions) -> Query {
        Query {
            output_options: output_options,
            constraints: constraints
        }
    }

    pub fn exec(&self, server_data: &ServerData) -> QueryRowsResult {
        self.constraints.exec(server_data)
    }
}
<commit_msg>Simplify the query exec() code in the genes case<commit_after>use std::collections::hash_set::HashSet;
use std::iter::FromIterator;

use api::server_data::ServerData;
use api::result::*;
use web::data::APIGeneSummary;

use types::GeneUniquename;

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum IntRangeType {
#[serde(rename = "genome_range_contains")]
    GenomeRangeContains,
#[serde(rename = "protein_length")]
    ProteinLength,
#[serde(rename = "tm_domain_count")]
    TMDomainCount,
#[serde(rename = "exon_count")]
    ExonCount,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum FloatRangeType {
#[serde(rename = "protein_mol_weight")]
    ProteinMolWeight,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum SingleOrMultiAllele {
#[serde(rename = "single")]
    Single,
#[serde(rename = "multi")]
    Multi,
#[serde(rename = "both")]
    Both,
}

#[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)]
pub enum QueryExpressionFilter {
#[serde(rename = "any")]
    Any,
#[serde(rename = "null")]
    Null,
#[serde(rename = "wt-overexpressed")]
    WtOverexpressed,
}

type TermName = String;
type QueryRowsResult = Result<Vec<ResultRow>, String>;
type GeneUniquenameVecResult = Result<Vec<GeneUniquename>, String>;

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum QueryNode {
#[serde(rename = "or")]
    Or(Vec<QueryNode>),
#[serde(rename = "and")]
    And(Vec<QueryNode>),
#[serde(rename = "not")]
    Not { node_a: Box<QueryNode>, node_b: Box<QueryNode> },
#[serde(rename = "term")]
    Term {
        termid: String,
        name: Option<TermName>,
        single_or_multi_allele: Option<SingleOrMultiAllele>,
        expression: Option<QueryExpressionFilter>,
    },
#[serde(rename = "subset")]
    Subset { subset_name: String },
#[serde(rename = "gene_list")]
    GeneList { ids: Vec<GeneUniquename> },
#[serde(rename = "int_range")]
    IntRange { range_type: IntRangeType, start: Option<u64>, end: Option<u64> },
#[serde(rename = "float_range")]
    FloatRange { range_type: FloatRangeType, start: Option<f64>, end: Option<f64> },
}

fn exec_or(server_data: &ServerData, nodes: &Vec<QueryNode>) -> GeneUniquenameVecResult {
    if nodes.len() == 0 {
        return Err("illegal query: OR operator has no nodes".into());
    }

    let mut seen_genes = HashSet::new();
    let mut or_rows = vec![];

    for node in nodes {
        let exec_rows = node.exec(server_data)?;

        for row_gene_uniquename in &exec_rows {
            if !seen_genes.contains(row_gene_uniquename) {
                or_rows.push(row_gene_uniquename.clone());
                seen_genes.insert(row_gene_uniquename.clone());
            }
        }
    }

    Ok(or_rows)
}

fn exec_and(server_data: &ServerData, nodes: &Vec<QueryNode>) -> GeneUniquenameVecResult {
    if nodes.len() == 0 {
        return Err("illegal query: AND operator has no nodes".into());
    }

    let first_node_genes = nodes[0].exec(server_data)?;

    let current_genes = first_node_genes;

    let mut current_gene_set = HashSet::from_iter(current_genes);

    for node in nodes[1..].iter() {
        let node_result_rows = node.exec(server_data)?;
        let node_genes = node_result_rows.into_iter().collect::<HashSet<_>>();

        current_gene_set = current_gene_set.intersection(&node_genes).cloned().collect();
    }

    Ok(current_gene_set.into_iter().collect())
}

fn exec_not(server_data: &ServerData, node_a: &QueryNode, node_b: &QueryNode)
             -> GeneUniquenameVecResult
{
    let node_b_result = node_b.exec(server_data)?;

    let node_b_gene_set: HashSet<GeneUniquename> =
        HashSet::from_iter(node_b_result.into_iter());

    let node_a_result = node_a.exec(server_data)?;

    let mut not_rows = vec![];

    for row_gene_uniquename in &node_a_result {
        if !node_b_gene_set.contains(row_gene_uniquename) {
            not_rows.push(row_gene_uniquename.clone());
        }
    }

    Ok(not_rows)
}

fn exec_termid(server_data: &ServerData, term_id: &str,
               maybe_single_or_multi_allele: &Option<SingleOrMultiAllele>,
               expression: &Option<QueryExpressionFilter>)  -> GeneUniquenameVecResult {
    if let Some(ref single_or_multi_allele) = *maybe_single_or_multi_allele {
        let genes = server_data.genes_of_genotypes(term_id, single_or_multi_allele,
                                                   expression);
        Ok(genes)
    } else {
        Ok(server_data.genes_of_termid(term_id))
    }
}

fn exec_subset(server_data: &ServerData, subset_name: &str)  -> GeneUniquenameVecResult {
    Ok(server_data.genes_of_subset(subset_name))
}

fn exec_gene_list(gene_uniquenames: &Vec<GeneUniquename>)  -> GeneUniquenameVecResult {
    Ok(gene_uniquenames.clone())
}

fn exec_genome_range_overlaps(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                               -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if let Some(ref location) = gene.location {
                (range_end.is_none() || location.start_pos as u64 <= range_end.unwrap()) &&
                (range_start.is_none() || location.end_pos as u64 >= range_start.unwrap())
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_protein_length_range(server_data: &ServerData,
                             range_start: Option<u64>, range_end: Option<u64>)
                              -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() || protein.sequence.len() as u64 >= range_start.unwrap()) &&
                    (range_end.is_none() || protein.sequence.len() as u64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_tm_domain_count_range(server_data: &ServerData,
                              range_start: Option<u64>, range_end: Option<u64>)
                               -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.tm_domain_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.tm_domain_count as u64 <= range_end.unwrap())
        });
    Ok(gene_uniquenames)
}

fn exec_exon_count_range(server_data: &ServerData,
                         range_start: Option<u64>, range_end: Option<u64>)
                         -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            (range_start.is_none() || gene.exon_count as u64 >= range_start.unwrap()) &&
            (range_end.is_none() || gene.exon_count as u64 <= range_end.unwrap())
        });
    Ok(gene_uniquenames)
}

fn exec_int_range(server_data: &ServerData, range_type: &IntRangeType,
                  start: Option<u64>, end: Option<u64>) -> GeneUniquenameVecResult {
    match *range_type {
        IntRangeType::GenomeRangeContains => exec_genome_range_overlaps(server_data, start, end),
        IntRangeType::ProteinLength => exec_protein_length_range(server_data, start, end),
        IntRangeType::TMDomainCount => exec_tm_domain_count_range(server_data, start, end),
        IntRangeType::ExonCount => exec_exon_count_range(server_data, start, end),
    }
}

fn exec_mol_weight_range(server_data: &ServerData, range_start: Option<f64>, range_end: Option<f64>)
                         -> GeneUniquenameVecResult
{
    let gene_uniquenames =
        server_data.filter_genes(&|gene: &APIGeneSummary| {
            if gene.transcripts.len() > 0 {
                if let Some(ref protein) = gene.transcripts[0].protein {
                    (range_start.is_none() ||
                        protein.molecular_weight as f64 >= range_start.unwrap()) &&
                    (range_end.is_none() ||
                        protein.molecular_weight as f64 <= range_end.unwrap())
                } else {
                    false
                }
            } else {
                false
            }
        });
    Ok(gene_uniquenames)
}

fn exec_float_range(server_data: &ServerData, range_type: &FloatRangeType,
                    start: Option<f64>, end: Option<f64>) -> GeneUniquenameVecResult {
    match *range_type {
        FloatRangeType::ProteinMolWeight => exec_mol_weight_range(server_data, start, end)
    }
}

impl QueryNode {
    pub fn exec(&self, server_data: &ServerData) -> GeneUniquenameVecResult {
        use self::QueryNode::*;
        match *self {
            Or(ref nodes) => exec_or(server_data, nodes),
            And(ref nodes) => exec_and(server_data, nodes),
            Not { ref node_a, ref node_b } => exec_not(server_data, node_a, node_b),
            Term {
                ref termid,
                name: _,
                ref single_or_multi_allele,
                ref expression,
            } => exec_termid(server_data, termid, single_or_multi_allele, expression),
            Subset { ref subset_name } => exec_subset(server_data, subset_name),
            GeneList { ref ids } => exec_gene_list(ids),
            IntRange { ref range_type, start, end } =>
                exec_int_range(server_data, range_type, start, end),
            FloatRange { ref range_type, start, end } =>
                exec_float_range(server_data, range_type, start, end),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum SeqType {
#[serde(rename = "protein")]
    Protein,
#[serde(rename = "nucleotide")]
    Nucleotide {
        include_introns: bool,
        include_5_prime_utr: bool,
        include_3_prime_utr: bool,
    },
#[serde(rename = "none")]
    None,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct QueryOutputOptions {
    pub sequence: SeqType,
    pub field_names: Vec<String>,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Query {
    output_options: QueryOutputOptions,
    constraints: QueryNode,
}

impl Query {
    pub fn new(constraints: QueryNode, output_options: QueryOutputOptions) -> Query {
        Query {
            output_options: output_options,
            constraints: constraints
        }
    }

    fn make_result_rows(&self, genes: Vec<String>) -> QueryRowsResult {
        Ok(genes.into_iter()
           .map(|gene_uniquename| ResultRow {
               sequence: None,
               gene_uniquename: gene_uniquename,
           }).collect::<Vec<_>>())
    }

    pub fn exec(&self, server_data: &ServerData) -> QueryRowsResult {
        let genes_result = self.constraints.exec(server_data);

        match genes_result {
            Ok(genes) => self.make_result_rows(genes),
            Err(err) => Err(err)
        }
    }
}
<|endoftext|>


<commit_before>//#[cfg(test)] use racer::testutils::{rejustify, slice};

pub fn rejustify(src: &str) -> String {
    let s = &src[1..]; // remove the newline
    let mut sb = String::new();
    for l in s.lines() {
        let tabless = &l[4..];
        sb.push_str(tabless);
        if tabless.len() != 0 {
            sb.push_str("\n");
        }
    }
    let newlen = sb.len()-1; // remove the trailing newline
    sb.truncate(newlen);
    sb
}

pub fn slice(src: &str, (begin, end): (usize, usize)) -> &str{
    &src[begin..end]
}

#[derive(Copy)]
enum State {
    StateCode,
    StateComment,
    StateCommentBlock,
    StateString,
    StateRawString,
    StateChar,
    StateFinished
}

#[derive(Copy)]
pub struct CodeIndicesIter<'a> {
    src: &'a str,
    pos: usize,
    state: State
}

impl<'a> Iterator for CodeIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let res = match self.state {
            State::StateCode => Some(code(self)),
            State::StateComment => Some(comment(self)),
            State::StateCommentBlock  => Some(comment_block(self)),
            State::StateString => Some(string(self)),
            State::StateRawString => Some(raw_string(self)),
            State::StateChar => Some(char(self)),
            State::StateFinished => None
        };
        res
    }
}

fn code(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let start = match self_.state {
        State::StateString |
        State::StateRawString |
        State::StateChar => { self_.pos-1 }, // include quote
        _ => { self_.pos }
    };
    let src_bytes = self_.src.as_bytes();
    for &b in src_bytes[self_.pos..].iter(){
        self_.pos += 1;
        match b {
            b'/' => match src_bytes[self_.pos] {
                b'/' => {
                    self_.state = State::StateComment;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                b'*' => {
                    self_.state = State::StateCommentBlock;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                _ => {}
            },
            b'r' => {
                if src_bytes.len() > self_.pos + 1 && src_bytes[self_.pos] == b'"' {
                    self_.pos +=1;
                    self_.state = State::StateRawString;
                    return (start, self_.pos); // include dblquotes
                }
            }
            b'"' => {    // "
                self_.state = State::StateString;
                return (start, self_.pos); // include dblquotes
            },
            b'\'' => {
                // single quotes are also used for lifetimes, so we need to
                // be confident that this is not a lifetime.
                // Look for closing quote:
                if src_bytes.len() > self_.pos + 2 &&
                    (src_bytes[self_.pos+1] == b'\'' ||
                     src_bytes[self_.pos+2] == b'\'') {
                    self_.state = State::StateChar;
                    return (start, self_.pos); // include single quote
                }
            },
            _ => {}
        }
    }

    self_.state = State::StateFinished;
    (start, self_.src.len())
}

fn comment(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'\n' { break; }
    }
    code(self_)
}

fn comment_block(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let mut nesting_level = 0u16; // should be enough
    let mut prev = b' ';
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'/' if prev == b'*' => {
                if nesting_level == 0 {
                    break;
                } else {
                    nesting_level -= 1;
                }
            },
            b'*' if prev == b'/' => {
                nesting_level += 1;
            },
            _ => { prev = b; }
        }
    }
    code(self_)
}

fn raw_string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'"' {
            break;
        }
    }
    code(self_)
}

fn string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'"' if is_not_escaped  => { break; }, // "
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

fn char(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'\'' if is_not_escaped  => { break; },
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

/// Returns indices of chunks of code (minus comments and string contents)
pub fn code_chunks<'a>(src: &'a str) -> CodeIndicesIter<'a> {
    CodeIndicesIter { src: src, state: State::StateCode, pos: 0 }
}

#[test]
fn removes_a_comment() {
    let src = &rejustify("
    this is some code // this is a comment
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents() {
    let src = &rejustify("
    this is some code \"this is a string\" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_char_contents() {
    let src = &rejustify("
    this is some code \'\"\' more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \'", slice(src, it.next().unwrap()));
    assert_eq!("\' more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents_with_a_comment_in_it() {
    let src = &rejustify("
    this is some code \"string with a // fake comment \" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_a_comment_with_a_dbl_quote_in_it() {
    let src = &rejustify("
    this is some code // comment with \" double quote
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_multiline_comment() {
    let src = &rejustify("
    this is some code /* this is a
    \"multiline\" comment */some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_nesting_of_block_comments() {
    let src = &rejustify("
    this is some code /* nested /* block */ comment */ some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!(" some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with a \\\" escaped dblquote fake comment \" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_raw_string_with_dangling_escape_in_it() {
    let src = &rejustify("
    this is some code br\" escaped dblquote raw string \\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code br\"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_slash_before_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with an escaped slash, so dbl quote does end the string after all \\\\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_tricky_bit_from_str_rs() {
    let src = &rejustify("
        before(\"\\\\\'\\\\\\\"\\\\\\\\\");
        more_code(\" skip me \")
    ")[];

    for (start,end) in code_chunks(src) {
        println!("BLOB |{}|",&src[start..end]);
        if (&src[start..end]).contains("skip me") {
            panic!("{}", &src[start..end]);
        }
    }
}

// fn main() {
//     use std::old_io::BufferedReader;
//     use std::old_io::File;
//     use std::str;

//     let filetxt = BufferedReader::new(File::open(&Path::new("/tmp/testcode.rs"))).read_to_end().unwrap();
//     let src = str::from_utf8(filetxt.as_slice()).unwrap();

//     for (start,end) in code_chunks(src) {
//         println!("BLOB |{}|",src.slice(start,end));
//     }

// }
<commit_msg>Move raw string management in string function<commit_after>//#[cfg(test)] use racer::testutils::{rejustify, slice};

pub fn rejustify(src: &str) -> String {
    let s = &src[1..]; // remove the newline
    let mut sb = String::new();
    for l in s.lines() {
        let tabless = &l[4..];
        sb.push_str(tabless);
        if tabless.len() != 0 {
            sb.push_str("\n");
        }
    }
    let newlen = sb.len()-1; // remove the trailing newline
    sb.truncate(newlen);
    sb
}

pub fn slice(src: &str, (begin, end): (usize, usize)) -> &str{
    &src[begin..end]
}

#[derive(Copy)]
enum State {
    StateCode,
    StateComment,
    StateCommentBlock,
    StateString,
    StateChar,
    StateFinished
}

#[derive(Copy)]
pub struct CodeIndicesIter<'a> {
    src: &'a str,
    pos: usize,
    state: State
}

impl<'a> Iterator for CodeIndicesIter<'a> {
    type Item = (usize, usize);

    #[inline]
    fn next(&mut self) -> Option<(usize, usize)> {
        let res = match self.state {
            State::StateCode => Some(code(self)),
            State::StateComment => Some(comment(self)),
            State::StateCommentBlock  => Some(comment_block(self)),
            State::StateString => Some(string(self)),
            State::StateChar => Some(char(self)),
            State::StateFinished => None
        };
        res
    }
}

fn code(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let start = match self_.state {
        State::StateString |
        State::StateChar => { self_.pos-1 }, // include quote
        _ => { self_.pos }
    };
    let src_bytes = self_.src.as_bytes();
    for &b in src_bytes[self_.pos..].iter(){
        self_.pos += 1;
        match b {
            b'/' => match src_bytes[self_.pos] {
                b'/' => {
                    self_.state = State::StateComment;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                b'*' => {
                    self_.state = State::StateCommentBlock;
                    self_.pos +=1;
                    return (start, self_.pos-2);
                },
                _ => {}
            },
            b'"' => {    // "
                self_.state = State::StateString;
                return (start, self_.pos); // include dblquotes
            },
            b'\'' => {
                // single quotes are also used for lifetimes, so we need to
                // be confident that this is not a lifetime.
                // Look for closing quote:
                if src_bytes.len() > self_.pos + 2 &&
                    (src_bytes[self_.pos+1] == b'\'' ||
                     src_bytes[self_.pos+2] == b'\'') {
                    self_.state = State::StateChar;
                    return (start, self_.pos); // include single quote
                }
            },
            _ => {}
        }
    }

    self_.state = State::StateFinished;
    (start, self_.src.len())
}

fn comment(self_: &mut CodeIndicesIter) -> (usize,usize) {
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        if b == b'\n' { break; }
    }
    code(self_)
}

fn comment_block(self_: &mut CodeIndicesIter) -> (usize,usize) {

    let mut nesting_level = 0u16; // should be enough
    let mut prev = b' ';
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'/' if prev == b'*' => {
                if nesting_level == 0 {
                    break;
                } else {
                    nesting_level -= 1;
                }
            },
            b'*' if prev == b'/' => {
                nesting_level += 1;
            },
            _ => { prev = b; }
        }
    }
    code(self_)
}

fn string(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let src_bytes = self_.src.as_bytes();
    if self_.pos > 1 && src_bytes[self_.pos-2] == b'r' {
        // raw string (eg br"\"): no escape
        match src_bytes[self_.pos..].iter().position(|&b| b == b'"') {
            Some(p) => self_.pos += p+1,
            None    => self_.pos = src_bytes.len()
        }
    } else {
        let mut is_not_escaped = true;
        for &b in src_bytes[self_.pos..].iter() {
            self_.pos += 1;
            match b {
                b'"' if is_not_escaped  => { break; }, // "
                b'\\' => { is_not_escaped = !is_not_escaped; },
                _ => { is_not_escaped = true; }
            }
        }
    }
    code(self_)
}

fn char(self_: &mut CodeIndicesIter) -> (usize,usize) {
    let mut is_not_escaped = true;
    for &b in self_.src.as_bytes()[self_.pos..].iter() {
        self_.pos += 1;
        match b {
            b'\'' if is_not_escaped  => { break; },
            b'\\' => { is_not_escaped = !is_not_escaped; },
            _ => { is_not_escaped = true; }
        }
    }
    code(self_)
}

/// Returns indices of chunks of code (minus comments and string contents)
pub fn code_chunks<'a>(src: &'a str) -> CodeIndicesIter<'a> {
    CodeIndicesIter { src: src, state: State::StateCode, pos: 0 }
}

#[test]
fn removes_a_comment() {
    let src = &rejustify("
    this is some code // this is a comment
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents() {
    let src = &rejustify("
    this is some code \"this is a string\" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_char_contents() {
    let src = &rejustify("
    this is some code \'\"\' more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \'", slice(src, it.next().unwrap()));
    assert_eq!("\' more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_contents_with_a_comment_in_it() {
    let src = &rejustify("
    this is some code \"string with a // fake comment \" more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_a_comment_with_a_dbl_quote_in_it() {
    let src = &rejustify("
    this is some code // comment with \" double quote
    some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_multiline_comment() {
    let src = &rejustify("
    this is some code /* this is a
    \"multiline\" comment */some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!("some more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_nesting_of_block_comments() {
    let src = &rejustify("
    this is some code /* nested /* block */ comment */ some more code
    ")[];
    let mut it = code_chunks(src);
    assert_eq!("this is some code ", slice(src, it.next().unwrap()));
    assert_eq!(" some more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with a \\\" escaped dblquote fake comment \" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_raw_string_with_dangling_escape_in_it() {
    let src = &rejustify("
    this is some code br\" escaped dblquote raw string \\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code br\"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn removes_string_with_escaped_slash_before_dblquote_in_it() {
    let src = &rejustify("
    this is some code \"string with an escaped slash, so dbl quote does end the string after all \\\\\" more code
    ")[];

    let mut it = code_chunks(src);
    assert_eq!("this is some code \"", slice(src, it.next().unwrap()));
    assert_eq!("\" more code", slice(src, it.next().unwrap()));
}

#[test]
fn handles_tricky_bit_from_str_rs() {
    let src = &rejustify("
        before(\"\\\\\'\\\\\\\"\\\\\\\\\");
        more_code(\" skip me \")
    ")[];

    for (start,end) in code_chunks(src) {
        println!("BLOB |{}|",&src[start..end]);
        if (&src[start..end]).contains("skip me") {
            panic!("{}", &src[start..end]);
        }
    }
}

// fn main() {
//     use std::old_io::BufferedReader;
//     use std::old_io::File;
//     use std::str;

//     let filetxt = BufferedReader::new(File::open(&Path::new("/tmp/testcode.rs"))).read_to_end().unwrap();
//     let src = str::from_utf8(filetxt.as_slice()).unwrap();

//     for (start,end) in code_chunks(src) {
//         println!("BLOB |{}|",src.slice(start,end));
//     }

// }
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{relative_rectangle, margin_rectangle,
rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle};
use {RectangleColorContext};
use {AddColor};
use {RelativeRectangle};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context, AddRectangle};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

impl<'a> RelativeRectangle<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(margin_rectangle(self.rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(relative_rectangle(self.rect.get(), x, y)),
        }
    }
}

<commit_msg>Implemented `AddRound` for `RectangleContext`<commit_after>
use {Field, Borrowed, Value};
use vecmath::{relative_rectangle, margin_rectangle,
rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Rectangle};
use {RectangleColorContext};
use {AddColor, AddRound};
use {RelativeRectangle};
use {RoundRectangleContext};

/// A rectangle context.
pub struct RectangleContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current rectangle.
    pub rect: Field<'a, Rectangle>,
}

impl<'a> Transform2d<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn trans_local(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(self.transform.get(), &trans))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn rot_rad_local(&'a self, angle: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(self.transform.get(), &rot))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn scale_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(self.transform.get(), &scale))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            rect: Borrowed(self.rect.get()),
        }
    }

    #[inline(always)]
    fn shear_local(&'a self, sx: f64, sy: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(self.transform.get(), &shear))
            },
            rect: Borrowed(self.rect.get()),
        }
    }
}

impl<'a> AddColor<'a, RectangleColorContext<'a>> for RectangleContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
            rect: Borrowed(self.rect.get()),
        }
    }
}

#[test]
fn test_rgba() {
    use {Context, AddRectangle};

    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 100.0);
    let e = d.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(e.color.get()[0], 1.0);
}

impl<'a> RelativeRectangle<'a> for RectangleContext<'a> {
    #[inline(always)]
    fn margin(&'a self, m: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(margin_rectangle(self.rect.get(), m)),
        }
    }

    #[inline(always)]
    fn rel(&'a self, x: f64, y: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value(relative_rectangle(self.rect.get(), x, y)),
        }
    }
}

impl<'a> AddRound<'a, RoundRectangleContext<'a>> for RectangleContext<'a> {
    #[inline(always)]
    fn round(&'a self, radius: f64) -> RoundRectangleContext<'a> {
        RoundRectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            round_rect: {
                let rect = self.rect.get();
                Value([rect[0], rect[1], rect[2], rect[3], radius])
            },
        }
    }
}

<|endoftext|>


<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

use mimir;

use geojson;
use geo;
use std::rc::Rc;

#[derive(Serialize, Deserialize, Debug)]
pub struct Geocoding {
    version: String,
    query: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Feature {
    #[serde(rename="type")]
    pub feature_type: String,
    pub geometry: geojson::Geometry,
    pub properties: Properties,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Properties {
    pub geocoding: GeocodingResponse,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct GeocodingResponse {
    pub id: String,
    #[serde(rename="type")]
    pub place_type: String, /* TODO enum cf https://github.com/geocoders/geocodejson-spec/blob/master/draft/README.md#feature-object */
    pub label: Option<String>,
    pub name: Option<String>,
    pub housenumber: Option<String>,
    pub street: Option<String>,
    pub postcode: Option<String>,
    pub city: Option<String>,
    //pub accuracy: Option<i32>,
    //pub district: Option<String>,
    //pub county: Option<String>,
    //pub state: Option<String>,
    //pub country: Option<String>,
    pub administrative_regions: Vec<Rc<mimir::Admin>>,
    //pub geohash: Option<String>
}

trait ToGeom {
    fn to_geom(&self) -> geojson::Geometry;
}

impl ToGeom for mimir::Place {
    fn to_geom(&self) -> geojson::Geometry {
        match self {
            &mimir::Place::Admin(ref admin) => admin.coord.to_geom(),
            &mimir::Place::Street(ref street) => street.coord.to_geom(),
            &mimir::Place::Addr(ref addr) => addr.coord.to_geom(),
            &mimir::Place::Poi(ref poi) => poi.coord.to_geom(),
        }
    }
}

impl ToGeom for geo::Coordinate {
    fn to_geom(&self) -> geojson::Geometry {
        geojson::Geometry::new(geojson::Value::Point(vec![self.y, self.x]))
    }
}

impl From<mimir::Place> for Feature {
    fn from(other: mimir::Place) -> Feature {
        let geom = other.to_geom();
        let geocoding = match other {
            mimir::Place::Admin(admin) => GeocodingResponse::from(admin),
            mimir::Place::Street(street) => GeocodingResponse::from(street),
            mimir::Place::Addr(addr) => GeocodingResponse::from(addr),
            mimir::Place::Poi(poi) => GeocodingResponse::from(poi),
        };
        Feature {
            feature_type: "Feature".to_string(),
            geometry: geom,
            properties: Properties { geocoding: geocoding },
        }
    }
}

impl From<mimir::Admin> for GeocodingResponse {
    fn from(other: mimir::Admin) -> GeocodingResponse {
        let type_ = "city".to_string(); //to be improved: it can be something else
        let name = Some(other.label);
        let postcode = if other.zip_codes.is_empty() { None } else { Some(other.zip_codes.join(";")) };
        let label = name.clone();
        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: None,
            administrative_regions: vec![]
        }
    }
}

fn get_city_name(admins: &Vec<Rc<mimir::Admin>>) -> Option<String> {
    // for the moment for the 'postcode' and the 'city', we take first admin
    // that has a postcode
    // TODO: change this (with a 'city tag in the admin ?')
    admins.iter()
          .find(|a| ! a.zip_codes.is_empty())
          .or_else(|| admins.iter().next())
          .map(|admin| admin.label.clone())
}

impl From<mimir::Street> for GeocodingResponse {
    fn from(other: mimir::Street) -> GeocodingResponse {
        let type_ = "street".to_string();
        let name = Some(other.street_name);
        let label = Some(other.label);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() { None } else { Some(other.zip_codes.join(";")) };

        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins
        }
    }
}

impl From<mimir::Addr> for GeocodingResponse {
    fn from(other: mimir::Addr) -> GeocodingResponse {
        let type_ = "house".to_string();
        let label = Some(other.label);
        let housenumber = Some(other.house_number.to_string());
        let street_name = Some(other.street.street_name.to_string());
        let name = Some(format!("{} {}", other.house_number, other.street.street_name));
        let admins = other.street.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() { None } else { Some(other.zip_codes.join(";")) };

        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: housenumber,
            street: street_name,
            city: city,
            administrative_regions: admins
        }
    }
}

impl From<mimir::Poi> for GeocodingResponse {
    fn from(other: mimir::Poi) -> GeocodingResponse {
        let type_ = "poi".to_string();
        let label = Some(other.label);
        let name = label.clone();
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);

        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: None,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Autocomplete {
    #[serde(rename="type")]
    format_type: String,
    geocoding: Geocoding,
    features: Vec<Feature>,
}

impl Autocomplete {
    pub fn new(q: String, features: Vec<Feature>) -> Autocomplete {
        // TODO couldn't we mode this function ? in Autocomplete ?
        Autocomplete {
            format_type: "FeatureCollection".to_string(),
            geocoding: Geocoding {
                version: "0.1.0".to_string(),
                query: Some(q),
            },
            features: features,
        }
    }
}

impl From<Vec<mimir::Place>> for Autocomplete {
    fn from(places: Vec<mimir::Place>) -> Autocomplete {
        Autocomplete::new("".to_string(),
                          places.into_iter().map(|p| Feature::from(p)).collect())
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Coord {
    pub lat: f64,
    pub lon: f64,
}

pub mod v1 {
    use mimir;
    use rs_es;

    // Note: I think this should be in api.rs but with the serde stuff it's easier for all
    // serde struct to be in the same file

    #[derive(Serialize, Deserialize, Debug)]
    pub struct EndPoint {
        pub description: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct CustomError {
        pub short: String,
        pub long: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub enum V1Reponse {
        Error(CustomError),
        Response {
            description: String,
        },
    }
    #[derive(Debug)]
    pub enum AutocompleteResponse {
        Error(CustomError),
        Autocomplete(super::Autocomplete),
    }

    use serde;
    impl serde::Serialize for AutocompleteResponse {
        fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer{
            match self {
                &AutocompleteResponse::Autocomplete(ref a) => serializer.serialize_some(a),
                &AutocompleteResponse::Error(ref e) => serializer.serialize_some(e)
            }
        }
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct Status {
        pub version: String,
        pub es: String,
        pub status: String,
    }

    impl From<Result<Vec<mimir::Place>, rs_es::error::EsError>> for AutocompleteResponse {
        fn from(r: Result<Vec<mimir::Place>, rs_es::error::EsError>) -> AutocompleteResponse {
            match r {
                Ok(places) => AutocompleteResponse::Autocomplete(super::Autocomplete::from(places)),
                Err(e) => {
                    AutocompleteResponse::Error(CustomError {
                        short: "query error".to_string(),
                        long: format!("invalid query {:?}", e),
                    })
                }
            }
        }
    }
}
<commit_msg>fixed name of POI<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

use mimir;

use geojson;
use geo;
use std::rc::Rc;

#[derive(Serialize, Deserialize, Debug)]
pub struct Geocoding {
    version: String,
    query: Option<String>,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Feature {
    #[serde(rename="type")]
    pub feature_type: String,
    pub geometry: geojson::Geometry,
    pub properties: Properties,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Properties {
    pub geocoding: GeocodingResponse,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct GeocodingResponse {
    pub id: String,
    #[serde(rename="type")]
    pub place_type: String, /* TODO enum cf https://github.com/geocoders/geocodejson-spec/blob/master/draft/README.md#feature-object */
    pub label: Option<String>,
    pub name: Option<String>,
    pub housenumber: Option<String>,
    pub street: Option<String>,
    pub postcode: Option<String>,
    pub city: Option<String>,
    //pub accuracy: Option<i32>,
    //pub district: Option<String>,
    //pub county: Option<String>,
    //pub state: Option<String>,
    //pub country: Option<String>,
    pub administrative_regions: Vec<Rc<mimir::Admin>>,
    //pub geohash: Option<String>
}

trait ToGeom {
    fn to_geom(&self) -> geojson::Geometry;
}

impl ToGeom for mimir::Place {
    fn to_geom(&self) -> geojson::Geometry {
        match self {
            &mimir::Place::Admin(ref admin) => admin.coord.to_geom(),
            &mimir::Place::Street(ref street) => street.coord.to_geom(),
            &mimir::Place::Addr(ref addr) => addr.coord.to_geom(),
            &mimir::Place::Poi(ref poi) => poi.coord.to_geom(),
        }
    }
}

impl ToGeom for geo::Coordinate {
    fn to_geom(&self) -> geojson::Geometry {
        geojson::Geometry::new(geojson::Value::Point(vec![self.y, self.x]))
    }
}

impl From<mimir::Place> for Feature {
    fn from(other: mimir::Place) -> Feature {
        let geom = other.to_geom();
        let geocoding = match other {
            mimir::Place::Admin(admin) => GeocodingResponse::from(admin),
            mimir::Place::Street(street) => GeocodingResponse::from(street),
            mimir::Place::Addr(addr) => GeocodingResponse::from(addr),
            mimir::Place::Poi(poi) => GeocodingResponse::from(poi),
        };
        Feature {
            feature_type: "Feature".to_string(),
            geometry: geom,
            properties: Properties { geocoding: geocoding },
        }
    }
}

impl From<mimir::Admin> for GeocodingResponse {
    fn from(other: mimir::Admin) -> GeocodingResponse {
        let type_ = "city".to_string(); //to be improved: it can be something else
        let name = Some(other.label);
        let postcode = if other.zip_codes.is_empty() { None } else { Some(other.zip_codes.join(";")) };
        let label = name.clone();
        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: None,
            administrative_regions: vec![]
        }
    }
}

fn get_city_name(admins: &Vec<Rc<mimir::Admin>>) -> Option<String> {
    // for the moment for the 'postcode' and the 'city', we take first admin
    // that has a postcode
    // TODO: change this (with a 'city tag in the admin ?')
    admins.iter()
          .find(|a| ! a.zip_codes.is_empty())
          .or_else(|| admins.iter().next())
          .map(|admin| admin.label.clone())
}

impl From<mimir::Street> for GeocodingResponse {
    fn from(other: mimir::Street) -> GeocodingResponse {
        let type_ = "street".to_string();
        let name = Some(other.street_name);
        let label = Some(other.label);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() { None } else { Some(other.zip_codes.join(";")) };

        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins
        }
    }
}

impl From<mimir::Addr> for GeocodingResponse {
    fn from(other: mimir::Addr) -> GeocodingResponse {
        let type_ = "house".to_string();
        let label = Some(other.label);
        let housenumber = Some(other.house_number.to_string());
        let street_name = Some(other.street.street_name.to_string());
        let name = Some(format!("{} {}", other.house_number, other.street.street_name));
        let admins = other.street.administrative_regions;
        let city = get_city_name(&admins);
        let postcode = if other.zip_codes.is_empty() { None } else { Some(other.zip_codes.join(";")) };

        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: postcode,
            label: label,
            housenumber: housenumber,
            street: street_name,
            city: city,
            administrative_regions: admins
        }
    }
}

impl From<mimir::Poi> for GeocodingResponse {
    fn from(other: mimir::Poi) -> GeocodingResponse {
        let type_ = "poi".to_string();
        let label = Some(other.label);
        let name = Some(other.name);
        let admins = other.administrative_regions;
        let city = get_city_name(&admins);

        GeocodingResponse {
            id: other.id,
            place_type: type_,
            name: name,
            postcode: None,
            label: label,
            housenumber: None,
            street: None,
            city: city,
            administrative_regions: admins
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Autocomplete {
    #[serde(rename="type")]
    format_type: String,
    geocoding: Geocoding,
    features: Vec<Feature>,
}

impl Autocomplete {
    pub fn new(q: String, features: Vec<Feature>) -> Autocomplete {
        // TODO couldn't we mode this function ? in Autocomplete ?
        Autocomplete {
            format_type: "FeatureCollection".to_string(),
            geocoding: Geocoding {
                version: "0.1.0".to_string(),
                query: Some(q),
            },
            features: features,
        }
    }
}

impl From<Vec<mimir::Place>> for Autocomplete {
    fn from(places: Vec<mimir::Place>) -> Autocomplete {
        Autocomplete::new("".to_string(),
                          places.into_iter().map(|p| Feature::from(p)).collect())
    }
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Coord {
    pub lat: f64,
    pub lon: f64,
}

pub mod v1 {
    use mimir;
    use rs_es;

    // Note: I think this should be in api.rs but with the serde stuff it's easier for all
    // serde struct to be in the same file

    #[derive(Serialize, Deserialize, Debug)]
    pub struct EndPoint {
        pub description: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct CustomError {
        pub short: String,
        pub long: String,
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub enum V1Reponse {
        Error(CustomError),
        Response {
            description: String,
        },
    }
    #[derive(Debug)]
    pub enum AutocompleteResponse {
        Error(CustomError),
        Autocomplete(super::Autocomplete),
    }

    use serde;
    impl serde::Serialize for AutocompleteResponse {
        fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer{
            match self {
                &AutocompleteResponse::Autocomplete(ref a) => serializer.serialize_some(a),
                &AutocompleteResponse::Error(ref e) => serializer.serialize_some(e)
            }
        }
    }

    #[derive(Serialize, Deserialize, Debug)]
    pub struct Status {
        pub version: String,
        pub es: String,
        pub status: String,
    }

    impl From<Result<Vec<mimir::Place>, rs_es::error::EsError>> for AutocompleteResponse {
        fn from(r: Result<Vec<mimir::Place>, rs_es::error::EsError>) -> AutocompleteResponse {
            match r {
                Ok(places) => AutocompleteResponse::Autocomplete(super::Autocomplete::from(places)),
                Err(e) => {
                    AutocompleteResponse::Error(CustomError {
                        short: "query error".to_string(),
                        long: format!("invalid query {:?}", e),
                    })
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>
use std;
import std::io;
import result;

type reader = obj {
    fn read_row() -> result::t<[str], str>;
};

fn mk_reader(f: std::io::reader, delim: char, quote: char, has_header: bool) -> reader {
    tag state {
        start;
        field([char]);
        escapedfield([char]);
        inquote([char]);
    };
    type readerstate = {
        f: std::io::reader,
        delim: char,
        quote: char,
        has_header: bool,
        mutable buf : [char],
        mutable offset : uint,
        mutable state : state,
    };
    obj reader(st: readerstate) {
        fn read_row() -> result::t<[str], str> {
            fn row_from_buf(st: readerstate, &row: [str]) -> bool {
                while st.offset < vec::len(st.buf) {
                    let c : char = st.buf[st.offset];
                    st.offset += 1u;
                    /* bug: trailing commas don't generate a field */
                    alt st.state {
                        start() {
                            //io::println(#fmt("start - %c", c));
                            if c == st.quote {
                                st.state = escapedfield([]);
                            } else if c == '\n' {
                                ret true;
                            } else if c == st.delim {
                                st.state = start;
                                row += [""];
                            } else {
                                st.state = field([c]);
                            }
                        }
                        field(x) {
                            //io::println(#fmt("field - %c", c));
                            if c == '\n' {
                                row += [str::from_chars(x)];
                                ret true;
                            } else if c == st.delim {
                                st.state = start;
                                row += [str::from_chars(x)];
                            } else {
                                st.state = field(x + [c]);
                            }
                        }
                        escapedfield(x) {
                            //io::println(#fmt("escapefield - %c", c));
                            if c == st.quote {
                                st.state = inquote(x);
                            } else if c == st.delim {
                                st.state = start;
                                row += [str::from_chars(x)];
                            } else {
                                st.state = escapedfield(x + [c]);
                            }
                        }
                        inquote(x) {
                            //io::println(#fmt("inquote - %c", c));
                            if c == '\n' {
                                row += [str::from_chars(x)];
                                ret true;
                            } else if c == st.quote {
                                st.state = escapedfield(x + [st.quote]);
                            } else if c == st.delim {
                                st.state = start;
                                row += [str::from_chars(x)];
                            }
                            // swallow odd chars, eg. space between field and "
                        }
                    }
                }
                ret false;
            }

            let row: [str] = [];
            st.state = start;
            while true {
                if st.offset >= vec::len(st.buf) {
                    st.offset = 0u;
                    st.buf = st.f.read_chars(1024u);
                    /* should probably use a result */
                    if vec::len(st.buf) == 0u {
                        ret result::err("EOF");
                    }
                }
                if (row_from_buf(st, row)) {
                    ret result::ok(row);
                }
            }
            ret result::err("EOF");
        }
    }

    let st = { f: f, delim: delim, quote: quote, has_header: has_header, mutable buf: [], mutable offset: 0u, mutable state: start };
    let r = reader(st);
    ret r;
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let r = mk_reader(f, ',', '"', true);
    while true {
        let res = r.read_row();
        if result::failure(res) {
            break;
        }
        io::println("---------------");
        for field in result::get(res) {
            io::println("FIELD: " + field);
        }
    }
}

<commit_msg>fix trailing comma problem<commit_after>
use std;
import std::io;
import result;

type reader = obj {
    fn read_row() -> result::t<[str], str>;
};

fn mk_reader(f: std::io::reader, delim: char, quote: char, has_header: bool) -> reader {
    tag state {
        start(bool);
        field([char]);
        escapedfield([char]);
        inquote([char]);
    };
    type readerstate = {
        f: std::io::reader,
        delim: char,
        quote: char,
        has_header: bool,
        mutable buf : [char],
        mutable offset : uint,
        mutable state : state,
    };
    obj reader(st: readerstate) {
        fn read_row() -> result::t<[str], str> {
            fn row_from_buf(st: readerstate, &row: [str]) -> bool {
                while st.offset < vec::len(st.buf) {
                    let c : char = st.buf[st.offset];
                    st.offset += 1u;
                    /* bug: trailing commas don't generate a field */
                    alt st.state {
                        start(after_delim) {
                            //io::println(#fmt("start - %c", c));
                            if c == st.quote {
                                st.state = escapedfield([]);
                            } else if c == '\n' {
                                if after_delim {
                                    row += [""];
                                }
                                ret true;
                            } else if c == st.delim {
                                st.state = start(true);
                                row += [""];
                            } else {
                                st.state = field([c]);
                            }
                        }
                        field(x) {
                            //io::println(#fmt("field - %c", c));
                            if c == '\n' {
                                row += [str::from_chars(x)];
                                ret true;
                            } else if c == st.delim {
                                st.state = start(true);
                                row += [str::from_chars(x)];
                            } else {
                                st.state = field(x + [c]);
                            }
                        }
                        escapedfield(x) {
                            //io::println(#fmt("escapefield - %c", c));
                            if c == st.quote {
                                st.state = inquote(x);
                            } else if c == st.delim {
                                st.state = start(true);
                                row += [str::from_chars(x)];
                            } else {
                                st.state = escapedfield(x + [c]);
                            }
                        }
                        inquote(x) {
                            //io::println(#fmt("inquote - %c", c));
                            if c == '\n' {
                                row += [str::from_chars(x)];
                                ret true;
                            } else if c == st.quote {
                                st.state = escapedfield(x + [st.quote]);
                            } else if c == st.delim {
                                st.state = start(true);
                                row += [str::from_chars(x)];
                            }
                            // swallow odd chars, eg. space between field and "
                        }
                    }
                }
                ret false;
            }

            let row: [str] = [];
            st.state = start(false);
            while true {
                if st.offset >= vec::len(st.buf) {
                    st.offset = 0u;
                    st.buf = st.f.read_chars(1024u);
                    /* should probably use a result */
                    if vec::len(st.buf) == 0u {
                        ret result::err("EOF");
                    }
                }
                if (row_from_buf(st, row)) {
                    ret result::ok(row);
                }
            }
            ret result::err("EOF");
        }
    }

    let st = { f: f, delim: delim, quote: quote, has_header: has_header, mutable buf: [], mutable offset: 0u, mutable state: start(false) };
    let r = reader(st);
    ret r;
}

fn main(args : [str])
{
    if (vec::len(args) != 2u) {
        ret;
    }
    let f : io::reader = result::get(io::file_reader(args[1]));
    let r = mk_reader(f, ',', '"', true);
    while true {
        let res = r.read_row();
        if result::failure(res) {
            break;
        }
        io::println("---------------");
        for field in result::get(res) {
            io::println("FIELD: " + field);
        }
    }
}

<|endoftext|>