<commit_before>extern crate num;
use std::cmp::min;

use raytracer::compositor::{ColorRGBA, SurfaceFactory};

pub struct Surface {
    pub width: uint,
    pub height: uint,
    pub x_off: uint,
    pub y_off: uint,
    pub background: ColorRGBA,
    pub buffer: Vec<ColorRGBA>
}

#[allow(dead_code)]
impl Surface {
    pub fn new(width: uint, height: uint, background: ColorRGBA) -> Surface {
        Surface {
            width: width,
            height: height,
            x_off: 0,
            y_off: 0,
            background: background,
            buffer: Vec::from_elem(width * height, background)
        }
    }

    pub fn with_offset(width: uint, height: uint, x_off: uint, y_off: uint,
                       background: ColorRGBA) -> Surface {
        Surface {
            width: width,
            height: height,
            x_off: x_off,
            y_off: y_off,
            background: background,
            buffer: Vec::from_elem(width * height, background)
        }
    }

    pub fn divide(&self, tile_width: uint, tile_height: uint) -> SubsurfaceIterator {
        SubsurfaceIterator {
            parent_width: self.width,
            parent_height: self.height,
            background: self.background,
            x_delta: tile_width,
            y_delta: tile_height,
            x_off: 0,
            y_off: 0,
        }
    }

    pub fn overrender_size(&self, tile_width: uint, tile_height: uint) -> (uint, uint) {
        let mut width = self.width;
        let width_partial_tile = width % tile_width;
        if width_partial_tile > 0 {
            width -= width_partial_tile;
            width += tile_width;
        }

        let mut height = self.height;
        let height_partial_tile = height % tile_height;
        if height_partial_tile > 0 {
            height -= height_partial_tile;
            height += tile_height;
        }

        (width, height)
    }

    pub fn merge(&mut self, tile: Box<Surface>) -> () {
        let x_len: uint = min(tile.width, self.width - tile.x_off);
        let y_len: uint = min(tile.height, self.height - tile.y_off);

        for src_y in range(0, y_len) {
            let dst_y = tile.y_off + src_y;
            for src_x in range(0, x_len) {
                let dst_x = tile.x_off + src_x;
                *self.get_mut(dst_x, dst_y) = tile.get(src_x, src_y)
            }
        }
    }

    #[inline]
    pub fn pixel_count(&self) -> uint {
        self.buffer.len()
    }

    #[inline]
    fn get_idx(&self, x: uint, y: uint) -> uint {
        if self.width <= x {
            fail!("`x` out of bounds (0 <= {} < {}", x, self.width);
        }
        if self.height <= y {
            fail!("`y` out of bounds (0 <= {} < {}", y, self.height);
        }
        self.width * y + x
    }

    #[inline]
    pub fn get(&self, x: uint, y: uint) -> ColorRGBA {
        let idx = self.get_idx(x, y);
        *self.buffer.get(idx)
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, x: uint, y: uint) -> &'a mut ColorRGBA {
        let idx = self.get_idx(x, y);
        self.buffer.get_mut(idx)
    }
}

struct SubsurfaceIterator {
    x_delta: uint,
    x_off: uint,
    y_delta: uint,
    y_off: uint,
    parent_width: uint,
    parent_height: uint,
    background: ColorRGBA,
}

impl SubsurfaceIterator {
    fn incr_tile(&mut self) {
        if self.x_off + self.x_delta < self.parent_width {
            self.x_off += self.x_delta;
        } else {
            self.x_off = 0;
            self.y_off += self.y_delta;
        }
    }

    fn current_tile(&self) -> Option<SurfaceFactory> {
        if self.x_off < self.parent_width && self.y_off < self.parent_height {
            Some(SurfaceFactory::new(
                self.x_delta,
                self.y_delta,
                self.x_off,
                self.y_off,
                self.background
            ))
        } else {
            None
        }
    }
}

impl Iterator<SurfaceFactory> for SubsurfaceIterator {
    fn next(&mut self) -> Option<SurfaceFactory> {
        let tile = self.current_tile();
        self.incr_tile();
        tile
    }
}

#[test]
fn test_measurement() {
    let width = 800;
    let height = 600;
    let width_tile = 128;
    let height_tile = 8;

    let background: ColorRGBA = ColorRGBA::new_rgb(0, 0, 0);
    let surf: Surface = Surface::new(width, height, background);

    let mut total_pixels = 0;

    for tile_factory in surf.divide(width_tile, height_tile) {
        total_pixels += tile_factory.create().pixel_count();
    }

    let (or_width, or_height) = surf.overrender_size(width_tile, height_tile);

    assert_eq!(or_width * or_height, total_pixels);
}

#[test]
fn test_paint_it_red() {
    let width = 800;
    let height = 600;
    let width_tile = 128;
    let height_tile = 8;

    let background: ColorRGBA = ColorRGBA::new_rgb(0, 0, 0);
    let mut surf: Surface = Surface::new(width, height, background);

    for tile_factory in surf.divide(width_tile, height_tile) {
        let mut tile = tile_factory.create();
        for y in range(0, tile.height) {
            for x in range(0, tile.width) {
                *tile.get_mut(x, y) = ColorRGBA::new_rgb(255, 0, 0);
            }
        }
        for y in range(0, tile.height) {
            for x in range(0, tile.width) {
                assert_eq!(tile.get(x, y).r, 255);
                assert_eq!(tile.get(x, y).g, 0);
                assert_eq!(tile.get(x, y).b, 0);
            }
        }
        surf.merge(*tile);
    }

    for y in range(0, surf.height) {
        for x in range(0, surf.width) {
            let color = surf.get(x, y);
            if color.r != 255 {
                fail!("wrong pixel at {}x{}", x, y);
            }
            if color.g != 0 {
                fail!("wrong pixel at {}x{}", x, y);
            }
            if color.b != 0 {
                fail!("wrong pixel at {}x{}", x, y);
            }
        }
    }

    // Check the iterator too
    for color in surf.buffer.iter() {
        assert_eq!(color.r, 255);
        assert_eq!(color.g, 0);
        assert_eq!(color.b, 0);
    }
}
<commit_msg>Fix tests<commit_after>extern crate num;
use std::cmp::min;

use raytracer::compositor::{ColorRGBA, SurfaceFactory};

pub struct Surface {
    pub width: uint,
    pub height: uint,
    pub x_off: uint,
    pub y_off: uint,
    pub background: ColorRGBA,
    pub buffer: Vec<ColorRGBA>
}

#[allow(dead_code)]
impl Surface {
    pub fn new(width: uint, height: uint, background: ColorRGBA) -> Surface {
        Surface {
            width: width,
            height: height,
            x_off: 0,
            y_off: 0,
            background: background,
            buffer: Vec::from_elem(width * height, background)
        }
    }

    pub fn with_offset(width: uint, height: uint, x_off: uint, y_off: uint,
                       background: ColorRGBA) -> Surface {
        Surface {
            width: width,
            height: height,
            x_off: x_off,
            y_off: y_off,
            background: background,
            buffer: Vec::from_elem(width * height, background)
        }
    }

    pub fn divide(&self, tile_width: uint, tile_height: uint) -> SubsurfaceIterator {
        SubsurfaceIterator {
            parent_width: self.width,
            parent_height: self.height,
            background: self.background,
            x_delta: tile_width,
            y_delta: tile_height,
            x_off: 0,
            y_off: 0,
        }
    }

    pub fn overrender_size(&self, tile_width: uint, tile_height: uint) -> (uint, uint) {
        let mut width = self.width;
        let width_partial_tile = width % tile_width;
        if width_partial_tile > 0 {
            width -= width_partial_tile;
            width += tile_width;
        }

        let mut height = self.height;
        let height_partial_tile = height % tile_height;
        if height_partial_tile > 0 {
            height -= height_partial_tile;
            height += tile_height;
        }

        (width, height)
    }

    pub fn merge(&mut self, tile: Box<Surface>) -> () {
        let x_len: uint = min(tile.width, self.width - tile.x_off);
        let y_len: uint = min(tile.height, self.height - tile.y_off);

        for src_y in range(0, y_len) {
            let dst_y = tile.y_off + src_y;
            for src_x in range(0, x_len) {
                let dst_x = tile.x_off + src_x;
                *self.get_mut(dst_x, dst_y) = tile.get(src_x, src_y)
            }
        }
    }

    #[inline]
    pub fn pixel_count(&self) -> uint {
        self.buffer.len()
    }

    #[inline]
    fn get_idx(&self, x: uint, y: uint) -> uint {
        if self.width <= x {
            fail!("`x` out of bounds (0 <= {} < {}", x, self.width);
        }
        if self.height <= y {
            fail!("`y` out of bounds (0 <= {} < {}", y, self.height);
        }
        self.width * y + x
    }

    #[inline]
    pub fn get(&self, x: uint, y: uint) -> ColorRGBA {
        let idx = self.get_idx(x, y);
        *self.buffer.get(idx)
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, x: uint, y: uint) -> &'a mut ColorRGBA {
        let idx = self.get_idx(x, y);
        self.buffer.get_mut(idx)
    }
}

struct SubsurfaceIterator {
    x_delta: uint,
    x_off: uint,
    y_delta: uint,
    y_off: uint,
    parent_width: uint,
    parent_height: uint,
    background: ColorRGBA,
}

impl SubsurfaceIterator {
    fn incr_tile(&mut self) {
        if self.x_off + self.x_delta < self.parent_width {
            self.x_off += self.x_delta;
        } else {
            self.x_off = 0;
            self.y_off += self.y_delta;
        }
    }

    fn current_tile(&self) -> Option<SurfaceFactory> {
        if self.x_off < self.parent_width && self.y_off < self.parent_height {
            Some(SurfaceFactory::new(
                self.x_delta,
                self.y_delta,
                self.x_off,
                self.y_off,
                self.background
            ))
        } else {
            None
        }
    }
}

impl Iterator<SurfaceFactory> for SubsurfaceIterator {
    fn next(&mut self) -> Option<SurfaceFactory> {
        let tile = self.current_tile();
        self.incr_tile();
        tile
    }
}

#[test]
fn test_measurement() {
    let width = 800;
    let height = 600;
    let width_tile = 128;
    let height_tile = 8;

    let background: ColorRGBA = ColorRGBA::new_rgb(0, 0, 0);
    let surf: Surface = Surface::new(width, height, background);

    let mut total_pixels = 0;

    for tile_factory in surf.divide(width_tile, height_tile) {
        total_pixels += tile_factory.create().pixel_count();
    }

    let (or_width, or_height) = surf.overrender_size(width_tile, height_tile);

    assert_eq!(or_width * or_height, total_pixels);
}

#[test]
fn test_paint_it_red() {
    let width = 800;
    let height = 600;
    let width_tile = 128;
    let height_tile = 8;

    let background: ColorRGBA = ColorRGBA::new_rgb(0, 0, 0);
    let mut surf: Surface = Surface::new(width, height, background);

    for tile_factory in surf.divide(width_tile, height_tile) {
        let mut tile = tile_factory.create();
        for y in range(0, tile.height) {
            for x in range(0, tile.width) {
                *tile.get_mut(x, y) = ColorRGBA::new_rgb(255, 0, 0);
            }
        }
        for y in range(0, tile.height) {
            for x in range(0, tile.width) {
                assert_eq!(tile.get(x, y).r, 255);
                assert_eq!(tile.get(x, y).g, 0);
                assert_eq!(tile.get(x, y).b, 0);
            }
        }
        surf.merge(box tile);
    }

    for y in range(0, surf.height) {
        for x in range(0, surf.width) {
            let color = surf.get(x, y);
            if color.r != 255 {
                fail!("wrong pixel at {}x{}", x, y);
            }
            if color.g != 0 {
                fail!("wrong pixel at {}x{}", x, y);
            }
            if color.b != 0 {
                fail!("wrong pixel at {}x{}", x, y);
            }
        }
    }

    // Check the iterator too
    for color in surf.buffer.iter() {
        assert_eq!(color.r, 255);
        assert_eq!(color.g, 0);
        assert_eq!(color.b, 0);
    }
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use regex::Regex;
use reqwest;
use rust_htslib::bcf;
use rust_htslib::bcf::Read;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::str;

#[derive(Serialize, Deserialize, Debug)]
struct Dgidb {
    #[serde(rename = "matchedTerms")]
    matched_terms: Vec<MatchedTerm>,
}

#[derive(Serialize, Deserialize, Debug)]
struct MatchedTerm {
    #[serde(rename = "geneName")]
    gene_name: String,
    interactions: Vec<Interaction>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Interaction {
    #[serde(rename = "drugName")]
    drug_name: String,
    #[serde(rename = "interactionTypes")]
    interaction_types: Vec<String>,
}

pub fn annotate_dgidb(
    vcf_path: &str,
    api_path: String,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let gene_drug_interactions = request_interaction_drugs(vcf_path, api_path)?;
    modify_vcf_entries(vcf_path, gene_drug_interactions, field_name)
}

fn request_interaction_drugs(
    vcf_path: &str,
    mut api_path: String,
) -> Result<HashMap<String, Vec<(String, Vec<String>)>>, Box<dyn Error>> {
    let mut genes = collect_genes(vcf_path)?;
    api_path.push_str(genes.drain().join(",").as_str());
    let res: Dgidb = reqwest::get(&api_path)?.json()?;

    let mut gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>> = HashMap::new();
    for term in res.matched_terms {
        if !term.interactions.is_empty() {
            gene_drug_interactions.insert(
                term.gene_name,
                term.interactions
                    .iter()
                    .map(|interaction| {
                        (
                            interaction.drug_name.clone(),
                            interaction.interaction_types.clone(),
                        )
                    })
                    .collect(),
            );
        }
    }
    Ok(gene_drug_interactions)
}

//TODO Remove split by ',' when updating to latest htslib release
fn collect_genes(vcf_path: &str) -> Result<HashSet<String>, Box<dyn Error>> {
    let mut total_genes = HashSet::new();
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    //let all_genes = HashSet::new();
    for result in reader.records() {
        let mut rec = result?;
        let genes_opt = extract_genes(&mut rec)?;
        match genes_opt {
            Some(genes) => {
                for gene in genes {
                    total_genes.insert(gene);
                }
            }
            None => {}
        }
    }
    Ok(total_genes)
}

//TODO Remove split by ',' when updating to latest htslib release
fn extract_genes<'a>(
    rec: &'a mut bcf::Record,
) -> Result<Option<impl Iterator<Item = String> + 'a>, Box<dyn Error>> {
    let annotation = rec.info("ANN".as_bytes()).string()?;
    match annotation {
        Some(transcripts) => Ok(Some(transcripts[0].split(|c| *c == b',').map(
            |transcript| {
                str::from_utf8(transcript.split(|c| *c == b'|').nth(3).unwrap())
                    .unwrap()
                    .to_owned()
            },
        ))),
        None => Ok(None),
    }
}

fn modify_vcf_entries(
    vcf_path: &str,
    gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>>,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    let mut header = bcf::header::Header::from_template(reader.header());
    header.push_record(format!("##INFO=<ID={},Number=.,Type=String,Description=\"Combination of gene, drug, interaction types extracted from dgiDB. Each combination is pipe-seperated annotated as GENE|DRUG|TYPE\">", field_name).as_bytes());
    let mut writer = bcf::Writer::from_stdout(&header, true, true)?;

    for result in reader.records() {
        let mut rec = result?;
        writer.translate(&mut rec);
        let genes = extract_genes(&mut rec)?.map(|genes| genes.collect_vec());
        if let Some(genes) = genes {
            let field_entries = build_dgidb_field(&gene_drug_interactions, genes)?;
            let field_entries: Vec<&[u8]> = field_entries.iter().map(|v| v.as_slice()).collect();
            rec.push_info_string(field_name.as_bytes(), &field_entries[..])?;
        }
        writer.write(&rec)?;
    }
    Ok(())
}

fn build_dgidb_field(
    gene_drug_interactions: &HashMap<String, Vec<(String, Vec<String>)>>,
    genes: Vec<String>,
) -> Result<Vec<Vec<u8>>, Box<dyn Error>> {
    let mut field_entries: Vec<Vec<u8>> = Vec::new();
    let re = Regex::new(r"\s\(\w+\)").unwrap();
    for gene in genes.iter() {
        match gene_drug_interactions.get(gene) {
            Some(drug_interactions) => {
                drug_interactions
                    .iter()
                    .for_each(|(drug, interaction_types)| {
                        if !interaction_types.is_empty(){
                        interaction_types.iter().for_each(|interaction_type| {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|{t}",
                                    g = gene,
                                    d = re.replace(drug, ""),
                                    t = interaction_type
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        })} else {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|.",
                                    g = gene,
                                    d = re.replace(drug, "")
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        }

                    });
            }
            None => field_entries.push(format!("{g}|.|.", g = gene).as_bytes().to_vec()),
        }
    }
    Ok(field_entries)
}
<commit_msg>Removed duplicates<commit_after>use itertools::Itertools;
use regex::Regex;
use reqwest;
use rust_htslib::bcf;
use rust_htslib::bcf::Read;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::str;

#[derive(Serialize, Deserialize, Debug)]
struct Dgidb {
    #[serde(rename = "matchedTerms")]
    matched_terms: Vec<MatchedTerm>,
}

#[derive(Serialize, Deserialize, Debug)]
struct MatchedTerm {
    #[serde(rename = "geneName")]
    gene_name: String,
    interactions: Vec<Interaction>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Interaction {
    #[serde(rename = "drugName")]
    drug_name: String,
    #[serde(rename = "interactionTypes")]
    interaction_types: Vec<String>,
}

pub fn annotate_dgidb(
    vcf_path: &str,
    api_path: String,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let gene_drug_interactions = request_interaction_drugs(vcf_path, api_path)?;
    modify_vcf_entries(vcf_path, gene_drug_interactions, field_name)
}

fn request_interaction_drugs(
    vcf_path: &str,
    mut api_path: String,
) -> Result<HashMap<String, Vec<(String, Vec<String>)>>, Box<dyn Error>> {
    let mut genes = collect_genes(vcf_path)?;
    api_path.push_str(genes.drain().join(",").as_str());
    let res: Dgidb = reqwest::get(&api_path)?.json()?;

    let mut gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>> = HashMap::new();
    for term in res.matched_terms {
        if !term.interactions.is_empty() {
            gene_drug_interactions.insert(
                term.gene_name,
                term.interactions
                    .iter()
                    .map(|interaction| {
                        (
                            interaction.drug_name.clone(),
                            interaction.interaction_types.clone(),
                        )
                    })
                    .collect(),
            );
        }
    }
    Ok(gene_drug_interactions)
}

//TODO Remove split by ',' when updating to latest htslib release
fn collect_genes(vcf_path: &str) -> Result<HashSet<String>, Box<dyn Error>> {
    let mut total_genes = HashSet::new();
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    //let all_genes = HashSet::new();
    for result in reader.records() {
        let mut rec = result?;
        let genes_opt = extract_genes(&mut rec)?;
        match genes_opt {
            Some(genes) => {
                for gene in genes {
                    total_genes.insert(gene);
                }
            }
            None => {}
        }
    }
    Ok(total_genes)
}

//TODO Remove split by ',' when updating to latest htslib release
fn extract_genes<'a>(
    rec: &'a mut bcf::Record,
) -> Result<Option<impl Iterator<Item = String> + 'a>, Box<dyn Error>> {
    let annotation = rec.info("ANN".as_bytes()).string()?;
    match annotation {
        Some(transcripts) => Ok(Some(transcripts[0].split(|c| *c == b',').map(
            |transcript| {
                str::from_utf8(transcript.split(|c| *c == b'|').nth(3).unwrap())
                    .unwrap()
                    .to_owned()
            },
        ))),
        None => Ok(None),
    }
}

fn modify_vcf_entries(
    vcf_path: &str,
    gene_drug_interactions: HashMap<String, Vec<(String, Vec<String>)>>,
    field_name: &str,
) -> Result<(), Box<dyn Error>> {
    let mut reader = bcf::Reader::from_path(vcf_path)?;
    let mut header = bcf::header::Header::from_template(reader.header());
    header.push_record(format!("##INFO=<ID={},Number=.,Type=String,Description=\"Combination of gene, drug, interaction types extracted from dgiDB. Each combination is pipe-seperated annotated as GENE|DRUG|TYPE\">", field_name).as_bytes());
    let mut writer = bcf::Writer::from_stdout(&header, true, true)?;

    for result in reader.records() {
        let mut rec = result?;
        writer.translate(&mut rec);
        let genes = extract_genes(&mut rec)?.map(|genes| genes.collect());
        if let Some(genes) = genes {
            let field_entries = build_dgidb_field(&gene_drug_interactions, genes)?;
            let field_entries: Vec<&[u8]> = field_entries.iter().map(|v| v.as_slice()).collect();
            rec.push_info_string(field_name.as_bytes(), &field_entries[..])?;
        }
        writer.write(&rec)?;
    }
    Ok(())
}

fn build_dgidb_field(
    gene_drug_interactions: &HashMap<String, Vec<(String, Vec<String>)>>,
    genes: HashSet<String>,
) -> Result<Vec<Vec<u8>>, Box<dyn Error>> {
    let mut field_entries: Vec<Vec<u8>> = Vec::new();
    let re = Regex::new(r"\s\(\w+\)").unwrap();
    for gene in genes.iter() {
        match gene_drug_interactions.get(gene) {
            Some(drug_interactions) => {
                drug_interactions
                    .iter()
                    .for_each(|(drug, interaction_types)| {
                        if !interaction_types.is_empty(){
                        interaction_types.iter().for_each(|interaction_type| {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|{t}",
                                    g = gene,
                                    d = re.replace(drug, ""),
                                    t = interaction_type
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        })} else {
                            field_entries.push(
                                format!(
                                    "{g}|{d}|.",
                                    g = gene,
                                    d = re.replace(drug, "")
                                )
                                .as_bytes()
                                .to_vec(),
                            )
                        }

                    });
            }
            None => field_entries.push(format!("{g}|.|.", g = gene).as_bytes().to_vec()),
        }
    }
    Ok(field_entries)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate pumpkindb;

extern crate config;
extern crate nom;
extern crate rustyline;
extern crate ansi_term;
extern crate uuid;

use pumpkindb::script;
use pumpkindb::script::compose::*;
use pumpkindb::script::compose::Item::*;

extern crate byteorder;

use std::io::prelude::*;
use std::net::TcpStream;

use byteorder::{ByteOrder, BigEndian};

use rustyline::error::ReadlineError;
use rustyline::Editor;

use std::fmt::Write;
use std::io::Write as IoWrite;

use ansi_term::Colour::Red;

use std::str;

use uuid::Uuid;

fn main() {
    let _ = config::merge(config::Environment::new("pumpkindb"));
    let _ = config::set_default("prompt", "PumpkinDB> ");

    let mut stream = TcpStream::connect("0.0.0.0:9981").unwrap();

    let mut rl = Editor::<()>::new();
    let mut r = Vec::new();

    loop {
        match rl.readline(format!("{}", config::get_str("prompt").unwrap()).as_str()) {
            Ok(text) => {
                rl.add_history_entry(&text);
                match script::parse(text.as_str()) {
                    Ok(compiled) => {
                        let uuid = Uuid::new_v4();
                        let msg : Vec<u8> = Program(vec![
                            Data(&compiled), Word("TRY"),
                            Data(uuid.as_bytes()), WordRef("topic"), Word("SET"),
                            Word("topic"),
                            Word("SUBSCRIBE"), Word("STACK"), Word("topic"), Word("SEND"),
                            Word("topic"), Word("UNSUBSCRIBE")
                        ]).into();
                        let mut buf = [0u8; 4];

                        BigEndian::write_u32(&mut buf, msg.len() as u32);
                        stream.write_all(buf.as_ref()).unwrap();
                        stream.write_all(msg.as_ref()).unwrap();

                        stream.read(&mut buf).unwrap();

                        let msg_len = BigEndian::read_u32(&mut buf);

                        let s_ref = <TcpStream as Read>::by_ref(&mut stream);

                        r.clear();

                        match s_ref.take(msg_len as u64).read_to_end(&mut r) {
                            Ok(0) => {
                            },
                            Ok(_) => {
                                let mut input = r.clone();
                                let mut top_level = true;
                                let mut s = String::new();
                                while input.len()> 0 {
                                    match script::binparser::data(input.clone().as_slice()) {
                                        nom::IResult::Done(rest, data) => {
                                            let (_, size) = script::binparser::data_size(data).unwrap();
                                            let data = &data[script::offset_by_size(size)..];

                                            input = Vec::from(rest);

                                            if rest.len() == 0 && top_level {
                                                top_level = false;
                                                if data.len() > 0 {
                                                    let _ = write!(&mut s, "{}", Red.paint("Error: "));
                                                    input = Vec::from(data);
                                                }
                                            } else {
                                                if data.iter().all(|c| *c >= 0x20 && *c <= 0x7e) {
                                                    let _ = write!(&mut s, "{:?} ", str::from_utf8(data).unwrap());
                                                } else {
                                                    let _ = write!(&mut s, "0x");
                                                    for b in Vec::from(data) {
                                                        let _ = write!(&mut s, "{:02x}", b);
                                                    }
                                                    let _ = write!(&mut s, " ");
                                                }
                                            }
                                        },
                                        e => {
                                            panic!("{:?}", e);
                                        }
                                    }
                                }
                                println!("{}", s);
                            },
                            Err(e) => {
                                panic!("{}", e);
                            }
                        }
                    },
                    Err(err) => {
                        println!("Script error: {:?}", err);
                    }
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("Aborted");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("Exiting");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }

    }
}<commit_msg>Problem: No way to paste multiline scripts into PumpkinDB Term<commit_after>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate pumpkindb;

extern crate config;
extern crate nom;
extern crate rustyline;
extern crate ansi_term;
extern crate uuid;

use pumpkindb::script;
use pumpkindb::script::compose::*;
use pumpkindb::script::compose::Item::*;

extern crate byteorder;

use std::io::prelude::*;
use std::net::TcpStream;

use byteorder::{ByteOrder, BigEndian};

use rustyline::error::ReadlineError;
use rustyline::Editor;
use rustyline::history::History;

use std::fmt::Write;
use std::io::Write as IoWrite;

use ansi_term::Colour::Red;

use std::str;

use uuid::Uuid;

fn main() {
    let _ = config::merge(config::Environment::new("pumpkindb"));
    let _ = config::set_default("prompt", "PumpkinDB> ");
    let formatted_prompt = format!("{}", config::get_str("prompt").unwrap());
    let mut current_prompt = formatted_prompt.as_str();

    let mut stream = TcpStream::connect("0.0.0.0:9981").unwrap();

    let mut rl = Editor::<()>::new();
    let mut r = Vec::new();

    let mut multine = History::new();
    println!("Connected to PumpkinDB at 0.0.0.0:9981");
    println!("Type ?h for help.");
    loop {
        match rl.readline(current_prompt) {
            Ok(text) => {
                let mut program = String::new();
                let text_str = text.as_str();
                let text_bytes = text_str.as_bytes();
                if text_bytes.len() >= 2 && text_bytes[0] == 63u8 {
                    if text_bytes[1] == 104u8 {
                        println!("\nTo end a statement, type `.`.");
                        println!("To quit, hit ^C");
                        println!("Further help online at http://pumpkindb.org/doc/");
                        println!("Missing a feature? Let us know at https://github.com/PumpkinDB/PumpkinDB/issues/\n");
                    }
                } else if text_bytes[text_str.len() - 1] == 46u8 {
                    let rest = str::from_utf8(&text.as_bytes()[..text_str.len() - 1]).unwrap();
                    multine.add(&rest);
                    for i in 0..multine.len() {
                        program.push_str(multine.get(i).unwrap().as_str());
                    }
                    multine.clear();
                    current_prompt = formatted_prompt.as_str();
                } else {
                    multine.add(&text);
                    multine.add(&" ");
                    current_prompt = "..> ";
                }
                if program.len() > 0 {
                    rl.add_history_entry(&program);
                    match script::parse(&program) {
                        Ok(compiled) => {
                            let uuid = Uuid::new_v4();
                            let msg : Vec<u8> = Program(vec![
                                Data(&compiled), Word("TRY"),
                                Data(uuid.as_bytes()), WordRef("topic"), Word("SET"),
                                Word("topic"),
                                Word("SUBSCRIBE"), Word("STACK"), Word("topic"), Word("SEND"),
                                Word("topic"), Word("UNSUBSCRIBE")
                            ]).into();
                            let mut buf = [0u8; 4];

                            BigEndian::write_u32(&mut buf, msg.len() as u32);
                            stream.write_all(buf.as_ref()).unwrap();
                            stream.write_all(msg.as_ref()).unwrap();

                            stream.read(&mut buf).unwrap();

                            let msg_len = BigEndian::read_u32(&mut buf);

                            let s_ref = <TcpStream as Read>::by_ref(&mut stream);

                            r.clear();

                            match s_ref.take(msg_len as u64).read_to_end(&mut r) {
                                Ok(0) => {
                                },
                                Ok(_) => {
                                    let mut input = r.clone();
                                    let mut top_level = true;
                                    let mut s = String::new();
                                    while input.len()> 0 {
                                        match script::binparser::data(input.clone().as_slice()) {
                                            nom::IResult::Done(rest, data) => {
                                                let (_, size) = script::binparser::data_size(data).unwrap();
                                                let data = &data[script::offset_by_size(size)..];

                                                input = Vec::from(rest);

                                                if rest.len() == 0 && top_level {
                                                    top_level = false;
                                                    if data.len() > 0 {
                                                        let _ = write!(&mut s, "{}", Red.paint("Error: "));
                                                        input = Vec::from(data);
                                                    }
                                                } else {
                                                    if data.iter().all(|c| *c >= 0x20 && *c <= 0x7e) {
                                                        let _ = write!(&mut s, "{:?} ", str::from_utf8(data).unwrap());
                                                    } else {
                                                        let _ = write!(&mut s, "0x");
                                                        for b in Vec::from(data) {
                                                            let _ = write!(&mut s, "{:02x}", b);
                                                        }
                                                        let _ = write!(&mut s, " ");
                                                    }
                                                }
                                            },
                                            e => {
                                                panic!("{:?}", e);
                                            }
                                        }
                                    }
                                    println!("{}", s);
                                },
                                Err(e) => {
                                    panic!("{}", e);
                                }
                            }
                        },
                        Err(err) => {
                            println!("Script error: {:?}", err);
                        }
                    }
                }
            }
            Err(ReadlineError::Interrupted) => {
                println!("Aborted");
                break
            },
            Err(ReadlineError::Eof) => {
                println!("Exiting");
                break
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }

    }
}<|endoftext|>


<commit_before>use std::collections::HashSet;
use super::helpers;
use super::error::Result;

pub fn depend_on_messages(folders: &[&str], messages: &[&str]) -> Result<String> {
    let mut output = Vec::<String>::new();
    output.push("#[macro_use]\nextern crate serde_derive;".into());
    output.push("pub mod msg {".into());
    let mut message_pairs = Vec::<(&str, &str)>::new();
    for message in messages {
        message_pairs.push(string_into_pair(message)?);
    }
    let message_map = helpers::get_message_map(folders, &message_pairs)?;
    let hashes = helpers::calculate_md5(&message_map)?;
    let packages = message_map
        .messages
        .iter()
        .map(|(&(ref pack, ref _name), ref _value)| pack.clone())
        .chain(message_map
                   .services
                   .iter()
                   .map(|&(ref pack, ref _name)| pack.clone()))
        .collect::<HashSet<String>>();
    for package in packages {
        output.push(format!("    pub mod {} {{", package));
        let names = message_map
            .messages
            .iter()
            .filter(|&(&(ref pack, ref _name), ref _value)| pack == &package)
            .map(|(&(ref _pack, ref name), ref _value)| name.clone())
            .collect::<HashSet<String>>();
        for name in &names {
            let key = (package.clone(), name.clone());
            let message = message_map
                .messages
                .get(&key)
                .expect("Internal implementation contains mismatch in map keys");
            let hash = hashes
                .get(&key)
                .expect("Internal implementation contains mismatch in map keys");
            let definition = helpers::generate_message_definition(&message_map.messages, &message)?;
            output.push(message.struct_string());
            output.push(format!("        impl ::rosrust::Message for {} {{", message.name));
            output.push(create_function("msg_definition", &definition));
            output.push(create_function("md5sum", &hash));
            output.push(create_function("msg_type", &message.get_type()));
            output.push("        }".into());
            output.push(format!("        impl {} {{", message.name));
            output.push(message.new_string());
            output.push("        }".into());
        }
        output.push("        #[allow(non_snake_case)]".into());
        output.push("        pub mod CONST {".into());
        for name in &names {
            let message = message_map
                .messages
                .get(&(package.clone(), name.clone()))
                .expect("Internal implementation contains mismatch in map keys");
            output.push(message.const_string());
        }
        output.push("        }".into());
        let names = message_map
            .services
            .iter()
            .filter(|&&(ref pack, ref _name)| pack == &package)
            .map(|&(ref _pack, ref name)| name.clone())
            .collect::<HashSet<String>>();
        for name in &names {
            let hash = hashes
                .get(&(package.clone(), name.clone()))
                .expect("Internal implementation contains mismatch in map keys");
            output.push("        #[allow(dead_code,non_camel_case_types,non_snake_case)]".into());
            output.push("        #[derive(Serialize,Deserialize,Debug)]".into());
            output.push(format!("        pub struct {} {{}}", name));
            output.push(format!("        impl ::rosrust::Message for {} {{", name));
            output.push(create_function("msg_definition", ""));
            output.push(create_function("md5sum", &hash));
            output.push(create_function("msg_type", &format!("{}/{}", package, name)));
            output.push("        }".into());

            output.push(format!("        impl ::rosrust::Service for {} {{", name));
            output.push(format!("            type Request = {}Req;", name));
            output.push(format!("            type Response = {}Res;", name));
            output.push("        }".into());
        }
        output.push("    }".into());
    }
    output.push("}".into());
    Ok(output.join("\n"))
}

fn create_function(name: &str, value: &str) -> String {
    format!(r#"
            fn {}() -> String {{
                {:?}.into()
            }}"#,
            name,
            value)
}

fn string_into_pair<'a>(input: &'a str) -> Result<(&'a str, &'a str)> {
    let mut parts = input.splitn(2, '/');
    let package = match parts.next() {
        Some(v) => v,
        None => bail!("Package string constains no parts: {}", input),
    };
    let name = match parts.next() {
        Some(v) => v,
        None => {
            bail!("Package string needs to be in package/name format: {}",
                  input)
        }
    };
    Ok((package, name))
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;

    lazy_static! {
        static ref FILEPATH: String = Path::new(file!())
            .parent().unwrap()
            .join("msg_examples")
            .to_str().unwrap()
            .into();
    }

    #[test]
    fn depend_on_messages_printout() {
        let data = depend_on_messages(&[&FILEPATH],
                                      &["geometry_msgs/PoseStamped", "sensor_msgs/Imu"])
                .unwrap();
        println!("{}", data);
        // TODO: actually test this output data
    }

    #[test]
    fn benchmark_genmsg() {
        let data = depend_on_messages(&[&FILEPATH], &["benchmark_msgs/Overall"]).unwrap();
        println!("{}", data);
        // TODO: actually test this output data
    }

    #[test]
    fn benchmark_genmsg_service() {
        let data = depend_on_messages(&[&FILEPATH], &["simple_srv/Something"]).unwrap();
        println!("{}", data);
        // TODO: actually test this output data
    }
}
<commit_msg>Use ::std::string::String for return type of create_function<commit_after>use std::collections::HashSet;
use super::helpers;
use super::error::Result;

pub fn depend_on_messages(folders: &[&str], messages: &[&str]) -> Result<String> {
    let mut output = Vec::<String>::new();
    output.push("#[macro_use]\nextern crate serde_derive;".into());
    output.push("pub mod msg {".into());
    let mut message_pairs = Vec::<(&str, &str)>::new();
    for message in messages {
        message_pairs.push(string_into_pair(message)?);
    }
    let message_map = helpers::get_message_map(folders, &message_pairs)?;
    let hashes = helpers::calculate_md5(&message_map)?;
    let packages = message_map
        .messages
        .iter()
        .map(|(&(ref pack, ref _name), ref _value)| pack.clone())
        .chain(message_map
                   .services
                   .iter()
                   .map(|&(ref pack, ref _name)| pack.clone()))
        .collect::<HashSet<String>>();
    for package in packages {
        output.push(format!("    pub mod {} {{", package));
        let names = message_map
            .messages
            .iter()
            .filter(|&(&(ref pack, ref _name), ref _value)| pack == &package)
            .map(|(&(ref _pack, ref name), ref _value)| name.clone())
            .collect::<HashSet<String>>();
        for name in &names {
            let key = (package.clone(), name.clone());
            let message = message_map
                .messages
                .get(&key)
                .expect("Internal implementation contains mismatch in map keys");
            let hash = hashes
                .get(&key)
                .expect("Internal implementation contains mismatch in map keys");
            let definition = helpers::generate_message_definition(&message_map.messages, &message)?;
            output.push(message.struct_string());
            output.push(format!("        impl ::rosrust::Message for {} {{", message.name));
            output.push(create_function("msg_definition", &definition));
            output.push(create_function("md5sum", &hash));
            output.push(create_function("msg_type", &message.get_type()));
            output.push("        }".into());
            output.push(format!("        impl {} {{", message.name));
            output.push(message.new_string());
            output.push("        }".into());
        }
        output.push("        #[allow(non_snake_case)]".into());
        output.push("        pub mod CONST {".into());
        for name in &names {
            let message = message_map
                .messages
                .get(&(package.clone(), name.clone()))
                .expect("Internal implementation contains mismatch in map keys");
            output.push(message.const_string());
        }
        output.push("        }".into());
        let names = message_map
            .services
            .iter()
            .filter(|&&(ref pack, ref _name)| pack == &package)
            .map(|&(ref _pack, ref name)| name.clone())
            .collect::<HashSet<String>>();
        for name in &names {
            let hash = hashes
                .get(&(package.clone(), name.clone()))
                .expect("Internal implementation contains mismatch in map keys");
            output.push("        #[allow(dead_code,non_camel_case_types,non_snake_case)]".into());
            output.push("        #[derive(Serialize,Deserialize,Debug)]".into());
            output.push(format!("        pub struct {} {{}}", name));
            output.push(format!("        impl ::rosrust::Message for {} {{", name));
            output.push(create_function("msg_definition", ""));
            output.push(create_function("md5sum", &hash));
            output.push(create_function("msg_type", &format!("{}/{}", package, name)));
            output.push("        }".into());

            output.push(format!("        impl ::rosrust::Service for {} {{", name));
            output.push(format!("            type Request = {}Req;", name));
            output.push(format!("            type Response = {}Res;", name));
            output.push("        }".into());
        }
        output.push("    }".into());
    }
    output.push("}".into());
    Ok(output.join("\n"))
}

fn create_function(name: &str, value: &str) -> String {
    format!(r#"
            fn {}() -> ::std::string::String {{
                {:?}.into()
            }}"#,
            name,
            value)
}

fn string_into_pair<'a>(input: &'a str) -> Result<(&'a str, &'a str)> {
    let mut parts = input.splitn(2, '/');
    let package = match parts.next() {
        Some(v) => v,
        None => bail!("Package string constains no parts: {}", input),
    };
    let name = match parts.next() {
        Some(v) => v,
        None => {
            bail!("Package string needs to be in package/name format: {}",
                  input)
        }
    };
    Ok((package, name))
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::Path;

    lazy_static! {
        static ref FILEPATH: String = Path::new(file!())
            .parent().unwrap()
            .join("msg_examples")
            .to_str().unwrap()
            .into();
    }

    #[test]
    fn depend_on_messages_printout() {
        let data = depend_on_messages(&[&FILEPATH],
                                      &["geometry_msgs/PoseStamped", "sensor_msgs/Imu"])
                .unwrap();
        println!("{}", data);
        // TODO: actually test this output data
    }

    #[test]
    fn benchmark_genmsg() {
        let data = depend_on_messages(&[&FILEPATH], &["benchmark_msgs/Overall"]).unwrap();
        println!("{}", data);
        // TODO: actually test this output data
    }

    #[test]
    fn benchmark_genmsg_service() {
        let data = depend_on_messages(&[&FILEPATH], &["simple_srv/Something"]).unwrap();
        println!("{}", data);
        // TODO: actually test this output data
    }
}
<|endoftext|>


<commit_before>use std::cmp;
use std::fmt::{mod, Show, Formatter};
use std::io::fs;
use glob::Pattern;

use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use ops;
use util::{CargoResult, internal, internal_error, process};

pub struct PathSource {
    id: SourceId,
    path: Path,
    updated: bool,
    packages: Vec<Package>
}

// TODO: Figure out if packages should be discovered in new or self should be
// mut and packages are discovered in update
impl PathSource {

    pub fn for_path(path: &Path) -> CargoResult<PathSource> {
        log!(5, "PathSource::for_path; path={}", path.display());
        Ok(PathSource::new(path, &try!(SourceId::for_path(path))))
    }

    /// Invoked with an absolute path to a directory that contains a Cargo.toml.
    /// The source will read the manifest and find any other packages contained
    /// in the directory structure reachable by the root manifest.
    pub fn new(path: &Path, id: &SourceId) -> PathSource {
        log!(5, "new; id={}", id);

        PathSource {
            id: id.clone(),
            path: path.clone(),
            updated: false,
            packages: Vec::new()
        }
    }

    pub fn get_root_package(&self) -> CargoResult<Package> {
        log!(5, "get_root_package; source={}", self);

        if !self.updated {
            return Err(internal("source has not been updated"))
        }

        match self.packages.as_slice().head() {
            Some(pkg) => Ok(pkg.clone()),
            None => Err(internal("no package found in source"))
        }
    }

    fn read_packages(&self) -> CargoResult<Vec<Package>> {
        if self.updated {
            Ok(self.packages.clone())
        } else {
            ops::read_packages(&self.path, &self.id)
        }
    }

    /// List all files relevant to building this package inside this source.
    ///
    /// This function will use the appropriate methods to determine what is the
    /// set of files underneath this source's directory which are relevant for
    /// building `pkg`.
    ///
    /// The basic assumption of this method is that all files in the directory
    /// are relevant for building this package, but it also contains logic to
    /// use other methods like .gitignore to filter the list of files.
    pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
        let candidates = try!(if self.path.join(".git").exists() {
            self.list_files_git(pkg)
        } else {
            self.list_files_walk(pkg)
        });

        let pats = pkg.get_manifest().get_exclude().iter().map(|p| {
            Pattern::new(p.as_slice())
        }).collect::<Vec<Pattern>>();

        let root = pkg.get_manifest_path().dir_path();
        Ok(candidates.move_iter().filter(|candidate| {
            let candidate = candidate.path_relative_from(&root).unwrap();
            !pats.iter().any(|p| p.matches_path(&candidate)) &&
                candidate.is_file()
        }).collect())
    }

    fn list_files_git(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
        let cwd = pkg.get_manifest_path().dir_path();
        let mut cmd = process("git").cwd(cwd.clone());
        cmd = cmd.arg("ls-files").arg("-z")
                 .arg("-x").arg("/target")
                 .arg("-x").arg("/Cargo.lock");

        // Filter out all other packages with a filter directive
        for pkg in self.packages.iter().filter(|p| *p != pkg) {
            if cwd.is_ancestor_of(pkg.get_manifest_path()) {
                let filter = pkg.get_manifest_path().dir_path()
                                .path_relative_from(&self.path).unwrap();
                cmd = cmd.arg("-x").arg(filter);
            }
        }

        log!(5, "listing git files with: {}", cmd);
        let output = try!(cmd.arg(".").exec_with_output());
        let output = output.output.as_slice();
        Ok(output.split(|x| *x == 0).map(|p| cwd.join(p)).collect())
    }

    fn list_files_walk(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
        let mut ret = Vec::new();
        for pkg in self.packages.iter().filter(|p| *p == pkg) {
            let loc = pkg.get_manifest_path().dir_path();
            try!(walk(&loc, &mut ret, true));
        }
        return Ok(ret);

        fn walk(path: &Path, ret: &mut Vec<Path>,
                is_root: bool) -> CargoResult<()> {
            if !path.is_dir() {
                ret.push(path.clone());
                return Ok(())
            }
            // Don't recurse into any sub-packages that we have
            if !is_root && path.join("Cargo.toml").exists() { return Ok(()) }
            for dir in try!(fs::readdir(path)).iter() {
                match (is_root, dir.filename_str()) {
                    (_,    Some(".git")) |
                    (true, Some("target")) |
                    (true, Some("Cargo.lock")) => continue,
                    _ => {}
                }
                try!(walk(dir, ret, false));
            }
            return Ok(())
        }
    }
}

impl Show for PathSource {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "the paths source")
    }
}

impl Registry for PathSource {
    fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
        let mut summaries: Vec<Summary> = self.packages.iter()
                                              .map(|p| p.get_summary().clone())
                                              .collect();
        summaries.query(dep)
    }
}

impl Source for PathSource {
    fn update(&mut self) -> CargoResult<()> {
        if !self.updated {
            let packages = try!(self.read_packages());
            self.packages.push_all_move(packages);
            self.updated = true;
        }

        Ok(())
    }

    fn download(&self, _: &[PackageId])  -> CargoResult<()>{
        // TODO: assert! that the PackageId is contained by the source
        Ok(())
    }

    fn get(&self, ids: &[PackageId]) -> CargoResult<Vec<Package>> {
        log!(5, "getting packages; ids={}", ids);

        Ok(self.packages.iter()
           .filter(|pkg| ids.iter().any(|id| pkg.get_package_id() == id))
           .map(|pkg| pkg.clone())
           .collect())
    }

    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
        if !self.updated {
            return Err(internal_error("BUG: source was not updated", ""));
        }

        let mut max = 0;
        for file in try!(self.list_files(pkg)).iter() {
            // An fs::stat error here is either because path is a
            // broken symlink, a permissions error, or a race
            // condition where this path was rm'ed - either way,
            // we can ignore the error and treat the path's mtime
            // as 0.
            max = cmp::max(max, file.stat().map(|s| s.modified).unwrap_or(0));
        }
        log!(5, "fingerprint {}: {}", self.path.display(), max);
        Ok(max.to_string())
    }
}
<commit_msg>Use libgit2 for `git ls-files`<commit_after>use std::cmp;
use std::fmt::{mod, Show, Formatter};
use std::io::fs;
use glob::Pattern;
use git2;

use core::{Package, PackageId, Summary, SourceId, Source, Dependency, Registry};
use ops;
use util::{CargoResult, internal, internal_error};

pub struct PathSource {
    id: SourceId,
    path: Path,
    updated: bool,
    packages: Vec<Package>
}

// TODO: Figure out if packages should be discovered in new or self should be
// mut and packages are discovered in update
impl PathSource {

    pub fn for_path(path: &Path) -> CargoResult<PathSource> {
        log!(5, "PathSource::for_path; path={}", path.display());
        Ok(PathSource::new(path, &try!(SourceId::for_path(path))))
    }

    /// Invoked with an absolute path to a directory that contains a Cargo.toml.
    /// The source will read the manifest and find any other packages contained
    /// in the directory structure reachable by the root manifest.
    pub fn new(path: &Path, id: &SourceId) -> PathSource {
        log!(5, "new; id={}", id);

        PathSource {
            id: id.clone(),
            path: path.clone(),
            updated: false,
            packages: Vec::new()
        }
    }

    pub fn get_root_package(&self) -> CargoResult<Package> {
        log!(5, "get_root_package; source={}", self);

        if !self.updated {
            return Err(internal("source has not been updated"))
        }

        match self.packages.as_slice().head() {
            Some(pkg) => Ok(pkg.clone()),
            None => Err(internal("no package found in source"))
        }
    }

    fn read_packages(&self) -> CargoResult<Vec<Package>> {
        if self.updated {
            Ok(self.packages.clone())
        } else {
            ops::read_packages(&self.path, &self.id)
        }
    }

    /// List all files relevant to building this package inside this source.
    ///
    /// This function will use the appropriate methods to determine what is the
    /// set of files underneath this source's directory which are relevant for
    /// building `pkg`.
    ///
    /// The basic assumption of this method is that all files in the directory
    /// are relevant for building this package, but it also contains logic to
    /// use other methods like .gitignore to filter the list of files.
    pub fn list_files(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
        let candidates = match git2::Repository::open(&self.path) {
            Ok(repo) => try!(self.list_files_git(pkg, repo)),
            Err(..) => try!(self.list_files_walk(pkg)),
        };

        let pats = pkg.get_manifest().get_exclude().iter().map(|p| {
            Pattern::new(p.as_slice())
        }).collect::<Vec<Pattern>>();

        let root = pkg.get_manifest_path().dir_path();
        Ok(candidates.move_iter().filter(|candidate| {
            let candidate = candidate.path_relative_from(&root).unwrap();
            !pats.iter().any(|p| p.matches_path(&candidate)) &&
                candidate.is_file()
        }).collect())
    }

    fn list_files_git(&self, pkg: &Package, repo: git2::Repository)
                      -> CargoResult<Vec<Path>> {
        let index = try!(repo.index());
        let mut ret = Vec::new();
        'outer: for i in range(0, index.len()) {
            let entry = match index.get(i) { Some(e) => e, None => continue };
            let fname = entry.path.as_bytes_no_nul();
            let path = pkg.get_manifest_path().dir_path().join(fname);

            // Filter out Cargo.lock and target always
            if fname == b"Cargo.lock" { continue }
            if fname == b"target" { continue }

            // Filter out all other packages
            for pkg in self.packages.iter().filter(|p| *p != pkg) {
                let pkg_path = pkg.get_manifest_path().dir_path();
                if pkg_path.is_ancestor_of(&path) { continue 'outer; }
            }

            // We found a file!
            ret.push(path);
        }
        Ok(ret)
    }

    fn list_files_walk(&self, pkg: &Package) -> CargoResult<Vec<Path>> {
        let mut ret = Vec::new();
        for pkg in self.packages.iter().filter(|p| *p == pkg) {
            let loc = pkg.get_manifest_path().dir_path();
            try!(walk(&loc, &mut ret, true));
        }
        return Ok(ret);

        fn walk(path: &Path, ret: &mut Vec<Path>,
                is_root: bool) -> CargoResult<()> {
            if !path.is_dir() {
                ret.push(path.clone());
                return Ok(())
            }
            // Don't recurse into any sub-packages that we have
            if !is_root && path.join("Cargo.toml").exists() { return Ok(()) }
            for dir in try!(fs::readdir(path)).iter() {
                match (is_root, dir.filename_str()) {
                    (_,    Some(".git")) |
                    (true, Some("target")) |
                    (true, Some("Cargo.lock")) => continue,
                    _ => {}
                }
                try!(walk(dir, ret, false));
            }
            return Ok(())
        }
    }
}

impl Show for PathSource {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "the paths source")
    }
}

impl Registry for PathSource {
    fn query(&mut self, dep: &Dependency) -> CargoResult<Vec<Summary>> {
        let mut summaries: Vec<Summary> = self.packages.iter()
                                              .map(|p| p.get_summary().clone())
                                              .collect();
        summaries.query(dep)
    }
}

impl Source for PathSource {
    fn update(&mut self) -> CargoResult<()> {
        if !self.updated {
            let packages = try!(self.read_packages());
            self.packages.push_all_move(packages);
            self.updated = true;
        }

        Ok(())
    }

    fn download(&self, _: &[PackageId])  -> CargoResult<()>{
        // TODO: assert! that the PackageId is contained by the source
        Ok(())
    }

    fn get(&self, ids: &[PackageId]) -> CargoResult<Vec<Package>> {
        log!(5, "getting packages; ids={}", ids);

        Ok(self.packages.iter()
           .filter(|pkg| ids.iter().any(|id| pkg.get_package_id() == id))
           .map(|pkg| pkg.clone())
           .collect())
    }

    fn fingerprint(&self, pkg: &Package) -> CargoResult<String> {
        if !self.updated {
            return Err(internal_error("BUG: source was not updated", ""));
        }

        let mut max = 0;
        for file in try!(self.list_files(pkg)).iter() {
            // An fs::stat error here is either because path is a
            // broken symlink, a permissions error, or a race
            // condition where this path was rm'ed - either way,
            // we can ignore the error and treat the path's mtime
            // as 0.
            max = cmp::max(max, file.stat().map(|s| s.modified).unwrap_or(0));
        }
        log!(5, "fingerprint {}: {}", self.path.display(), max);
        Ok(max.to_string())
    }
}
<|endoftext|>


<commit_before>//! This is a thread that processes websocket messages
//!
//! Important things about this thread:
//!
//! 1. It's fully driven by input message
//! 2. No timers here
//! 3. No time management here, only accept time value from events (*)
//!
//! This allows much better unit tests

use std::time::Instant;
use std::sync::Arc;
use std::collections::HashMap;

use rustc_serialize::json::Json;
use rustc_serialize::{Encodable, Encoder};
use tokio_core::channel::Sender;

use config;
use intern::{Topic, SessionId, SessionPoolName, Lattice};
use chat::Cid;
use chat::message::Meta;
use chat::error::MessageError;

mod main;
mod pool;
mod public;
mod session;
mod heap;
mod try_iter;  // temporary
mod connection;
mod lattice;

pub use self::public::{Processor, ProcessorPool};

pub struct Event {
    pool: SessionPoolName,
    timestamp: Instant,
    action: Action,
}

pub enum ConnectionMessage {
    /// Topic publish message:
    /// `["message", {"topic": topic}, data]`
    Publish(Topic, Arc<Json>),
    /// Auth response message:
    /// `["hello", {}, json_data]`
    Hello(Arc<Json>),
    /// Websocket call result;
    Result(Meta, Json),
    /// Lattice update message
    Lattice(Arc<Json>),
    /// Error response to websocket call
    Error(Meta, MessageError),
}

pub enum PoolMessage {
    InactiveSession {
        session_id: SessionId,
        // This is mostly for debugging for now
        connections_active: usize,
        metadata: Arc<Json>,
    },
}

pub enum Action {

    // ------ Session pool management ------
    //   For all actions session pool name is passed in event structure
    NewSessionPool {
        config: Arc<config::SessionPool>,
        channel: Sender<PoolMessage>,
    },
    StopSessionPool,

    // ------ Connection management ------
    NewConnection {
        conn_id: Cid,
        channel: Sender<ConnectionMessage>,
    },
    Associate {
        conn_id: Cid,
        session_id: SessionId,
        metadata: Arc<Json>
    },
    UpdateActivity {
        conn_id: Cid,
        // We receive duration from client, but we expect request handling
        // code to validate and normalize it for us
        timestamp: Instant,
    },
    Disconnect {
        conn_id: Cid,
    },

    // ------ Subscriptions ------
    Subscribe {
        conn_id: Cid,
        topic: Topic,
    },
    Unsubscribe {
        conn_id: Cid,
        topic: Topic,
    },
    Publish {
        topic: Topic,
        data: Arc<Json>,
    },

    // ------ Lattices ------
    Attach {
        namespace: Lattice,
        conn_id: Cid,
    },
    Lattice {
        namespace: Lattice,
        private: lattice::Values,
        public: HashMap<SessionId, lattice::Values>,
    },
    Detach {
        namespace: Lattice,
        conn_id: Cid,
    },
}

impl Encodable for ConnectionMessage {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        use self::ConnectionMessage::*;
        match *self {
            Publish(ref topic, ref json) => {
                s.emit_seq(3, |s| {
                    #[derive(RustcEncodable)]
                    struct Meta<'a> {
                        topic: &'a Topic,
                    }
                    s.emit_seq_elt(0, |s| s.emit_str("message"))?;
                    s.emit_seq_elt(1, |s| {
                        Meta { topic: topic }.encode(s)
                    })?;
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Hello(ref json) => {
                s.emit_seq(3, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("hello"))?;
                    s.emit_seq_elt(1, |s| s.emit_map(0, |_| Ok(())))?;
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Lattice(ref json) => {
                s.emit_seq(2, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("lattice"))?;
                    s.emit_seq_elt(1, |s| json.encode(s))
                })
            }
            Result(ref meta, ref json) => {
                s.emit_seq(3, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("result"))?;
                    s.emit_seq_elt(1, |s| meta.encode(s))?;
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Error(ref meta, ref err) => {
                s.emit_seq(3, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("Error"))?;
                    s.emit_seq_elt(1, |s| meta.encode(s))?;
                    s.emit_seq_elt(2, |s| err.encode(s))
                })
            }
        }
    }
}
<commit_msg>Fix serialization of lattice message<commit_after>//! This is a thread that processes websocket messages
//!
//! Important things about this thread:
//!
//! 1. It's fully driven by input message
//! 2. No timers here
//! 3. No time management here, only accept time value from events (*)
//!
//! This allows much better unit tests

use std::time::Instant;
use std::sync::Arc;
use std::collections::HashMap;

use rustc_serialize::json::Json;
use rustc_serialize::{Encodable, Encoder};
use tokio_core::channel::Sender;

use config;
use intern::{Topic, SessionId, SessionPoolName, Lattice as Namespace};
use chat::Cid;
use chat::message::Meta;
use chat::error::MessageError;

mod main;
mod pool;
mod public;
mod session;
mod heap;
mod try_iter;  // temporary
mod connection;
mod lattice;

pub use self::public::{Processor, ProcessorPool};

pub struct Event {
    pool: SessionPoolName,
    timestamp: Instant,
    action: Action,
}

pub enum ConnectionMessage {
    /// Topic publish message:
    /// `["message", {"topic": topic}, data]`
    Publish(Topic, Arc<Json>),
    /// Auth response message:
    /// `["hello", {}, json_data]`
    Hello(Arc<Json>),
    /// Websocket call result;
    Result(Meta, Json),
    /// Lattice update message
    Lattice(Namespace, Arc<Json>),
    /// Error response to websocket call
    Error(Meta, MessageError),
}

pub enum PoolMessage {
    InactiveSession {
        session_id: SessionId,
        // This is mostly for debugging for now
        connections_active: usize,
        metadata: Arc<Json>,
    },
}

pub enum Action {

    // ------ Session pool management ------
    //   For all actions session pool name is passed in event structure
    NewSessionPool {
        config: Arc<config::SessionPool>,
        channel: Sender<PoolMessage>,
    },
    StopSessionPool,

    // ------ Connection management ------
    NewConnection {
        conn_id: Cid,
        channel: Sender<ConnectionMessage>,
    },
    Associate {
        conn_id: Cid,
        session_id: SessionId,
        metadata: Arc<Json>
    },
    UpdateActivity {
        conn_id: Cid,
        // We receive duration from client, but we expect request handling
        // code to validate and normalize it for us
        timestamp: Instant,
    },
    Disconnect {
        conn_id: Cid,
    },

    // ------ Subscriptions ------
    Subscribe {
        conn_id: Cid,
        topic: Topic,
    },
    Unsubscribe {
        conn_id: Cid,
        topic: Topic,
    },
    Publish {
        topic: Topic,
        data: Arc<Json>,
    },

    // ------ Lattices ------
    Attach {
        namespace: Namespace,
        conn_id: Cid,
    },
    Lattice {
        namespace: Namespace,
        private: lattice::Values,
        public: HashMap<SessionId, lattice::Values>,
    },
    Detach {
        namespace: Namespace,
        conn_id: Cid,
    },
}

impl Encodable for ConnectionMessage {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error>
    {
        use self::ConnectionMessage::*;
        match *self {
            Publish(ref topic, ref json) => {
                s.emit_seq(3, |s| {
                    #[derive(RustcEncodable)]
                    struct Meta<'a> {
                        topic: &'a Topic,
                    }
                    s.emit_seq_elt(0, |s| s.emit_str("message"))?;
                    s.emit_seq_elt(1, |s| {
                        Meta { topic: topic }.encode(s)
                    })?;
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Hello(ref json) => {
                s.emit_seq(3, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("hello"))?;
                    s.emit_seq_elt(1, |s| s.emit_map(0, |_| Ok(())))?;
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Lattice(ref namespace, ref json) => {
                s.emit_seq(3, |s| {
                    #[derive(RustcEncodable)]
                    struct Meta<'a> {
                        namespace: &'a Namespace,
                    }
                    s.emit_seq_elt(0, |s| s.emit_str("lattice"))?;
                    s.emit_seq_elt(1, |s| {
                        Meta { namespace: namespace }.encode(s)
                    });
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Result(ref meta, ref json) => {
                s.emit_seq(3, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("result"))?;
                    s.emit_seq_elt(1, |s| meta.encode(s))?;
                    s.emit_seq_elt(2, |s| json.encode(s))
                })
            }
            Error(ref meta, ref err) => {
                s.emit_seq(3, |s| {
                    s.emit_seq_elt(0, |s| s.emit_str("Error"))?;
                    s.emit_seq_elt(1, |s| meta.encode(s))?;
                    s.emit_seq_elt(2, |s| err.encode(s))
                })
            }
        }
    }
}
<|endoftext|>


<commit_before>use hyper;
use hyper::header::Connection;
use std::io;
use std::io::Read;

pub const DEFAULT_EVENT_BODY_LIMIT_BYTES: usize = 1024 * 256;
pub const DEFAULT_BATCH_LIMIT_BYTES: usize = 1024 * 1024 * 10;
pub const LOCAL_SERVER_URL: &'static str = "http://localhost:5341";

pub struct SeqCollector<'a> {
    server_url: &'a str,
    api_key: Option<&'a str>,
    event_body_limit_bytes: usize,
    batch_limit_bytes: usize
}

impl<'a> SeqCollector<'a> {
    pub fn new<'b>(server_url: &'b str, api_key: Option<&'b str>, event_body_limit_bytes: usize, batch_limit_bytes: usize) -> SeqCollector<'b> {
        SeqCollector {
            server_url: server_url,
            api_key: api_key,
            event_body_limit_bytes: event_body_limit_bytes,
            batch_limit_bytes: batch_limit_bytes
        }
    }

    pub fn local<'b>() -> SeqCollector<'b> {
        Self::new(LOCAL_SERVER_URL, None, DEFAULT_EVENT_BODY_LIMIT_BYTES, DEFAULT_BATCH_LIMIT_BYTES)
    }
}

impl<'a> super::Collector for SeqCollector<'a> {
    type Error = io::Error;

    fn dispatch(&self, events: &[String]) -> Result<(), Self::Error> {
        for payload in events {
            let el = format!("{{\"Events\":[{}]}}", payload);

            let client = hyper::Client::new();
            let mut res = client.post(&format!("{}api/events/raw/", self.server_url))
                .body(&el)
                .header(Connection::close())
                .send().unwrap();

            let mut body = String::new();
            try!(res.read_to_string(&mut body).map(|s| ()))
        }

        Ok(())
    }
}
<commit_msg>Got rid of the static bound by letting `SeqCollector` own its members.<commit_after>use hyper;
use hyper::header::Connection;
use std::io;
use std::io::Read;

pub const DEFAULT_EVENT_BODY_LIMIT_BYTES: usize = 1024 * 256;
pub const DEFAULT_BATCH_LIMIT_BYTES: usize = 1024 * 1024 * 10;
pub const LOCAL_SERVER_URL: &'static str = "http://localhost:5341";

pub struct SeqCollector {
    server_url: String,
    api_key: Option<String>,
    event_body_limit_bytes: usize,
    batch_limit_bytes: usize
}

impl SeqCollector {
    pub fn new<'b>(server_url: &'b str, api_key: Option<&'b str>, event_body_limit_bytes: usize, batch_limit_bytes: usize) -> SeqCollector {
        SeqCollector {
            server_url: server_url.to_owned(),
            api_key: api_key.map(|k| k.to_owned()),
            event_body_limit_bytes: event_body_limit_bytes,
            batch_limit_bytes: batch_limit_bytes
        }
    }

    pub fn local() -> SeqCollector {
        Self::new(LOCAL_SERVER_URL, None, DEFAULT_EVENT_BODY_LIMIT_BYTES, DEFAULT_BATCH_LIMIT_BYTES)
    }
}

impl super::Collector for SeqCollector {
    type Error = io::Error;

    fn dispatch(&self, events: &[String]) -> Result<(), Self::Error> {
        for payload in events {
            let el = format!("{{\"Events\":[{}]}}", payload);

            let client = hyper::Client::new();
            let mut res = client.post(&format!("{}api/events/raw/", self.server_url))
                .body(&el)
                .header(Connection::close())
                .send().unwrap();

            let mut body = String::new();
            try!(res.read_to_string(&mut body).map(|s| ()))
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>
#[derive(Default, Debug)]
pub struct RegConfig {
    transfer_data_pattern: TransferDataPattern,
    endianness: Endianness,
    coherency_algorithm: CoherencyAlgorithm,
}

impl RegConfig {
    pub fn power_on_reset(&mut self) {
        self.transfer_data_pattern = TransferDataPattern::D;
        self.endianness = Endianness::BigEndian;
    }
}

impl From<u32> for RegConfig {
    fn from(data: u32) -> Self {
        RegConfig {
            transfer_data_pattern: data.into(),
            endianness: data.into(),
            coherency_algorithm: data.into(),
        }
    }
}

#[derive(Debug)]
enum TransferDataPattern {
    D,
    DxxDxx,
    RFU,
}

impl Default for TransferDataPattern {
    fn default() -> Self {
        TransferDataPattern::D
    }
}

impl From<u32> for TransferDataPattern {
    fn from(f: u32) -> Self {
        let transfer_data_patterndata = (f >> 24) & 0b1111;
        match transfer_data_patterndata {
            0 => TransferDataPattern::D,
            6 => TransferDataPattern::DxxDxx,
            _ => TransferDataPattern::RFU,
        }
    }
}

#[derive(Debug)]
enum Endianness {
    LittleEndian,
    BigEndian,
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::BigEndian
    }
}

impl From<u32> for Endianness {
    fn from(f: u32) -> Self {
        let endiannessdata = (f >> 15) & 0b1;
        if endiannessdata == 0 {
            Endianness::LittleEndian
        } else {
            Endianness::BigEndian
        }
    }
}

#[derive(Debug)]
enum CoherencyAlgorithm {
    NotUsed,
    Used,
}

impl Default for CoherencyAlgorithm {
    fn default() -> Self {
        CoherencyAlgorithm::NotUsed
    }
}

impl From<u32> for CoherencyAlgorithm {
    fn from(f: u32) -> Self {
        let coherency_algorithmdata = f & 0b111;
        match coherency_algorithmdata {
            0b010 => CoherencyAlgorithm::NotUsed,
            _ => CoherencyAlgorithm::Used,
        }
    }
}
<commit_msg>minor tweaks to config register<commit_after>
#[derive(Default, Debug)]
pub struct RegConfig {
    transfer_data_pattern: TransferDataPattern,
    endianness: Endianness,
    cu: bool,
    kseg0_coherency_algorithm: CoherencyAlgorithm,
}

impl RegConfig {
    pub fn power_on_reset(&mut self) {
        self.transfer_data_pattern = TransferDataPattern::D;
        self.endianness = Endianness::BigEndian;
    }
}

impl From<u32> for RegConfig {
    fn from(data: u32) -> Self {
        RegConfig {
            transfer_data_pattern: data.into(),
            endianness: data.into(),
            cu: (data >> 3) & 0b1 != 0,
            kseg0_coherency_algorithm: data.into(),
        }
    }
}

#[derive(Debug)]
enum TransferDataPattern {
    D,
    DxxDxx,
    RFU,
}

impl Default for TransferDataPattern {
    fn default() -> Self {
        TransferDataPattern::D
    }
}

impl From<u32> for TransferDataPattern {
    fn from(f: u32) -> Self {
        let transfer_data_patterndata = (f >> 24) & 0b1111;
        match transfer_data_patterndata {
            0 => TransferDataPattern::D,
            6 => TransferDataPattern::DxxDxx,
            _ => TransferDataPattern::RFU,
        }
    }
}

#[derive(Debug)]
enum Endianness {
    LittleEndian,
    BigEndian,
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::BigEndian
    }
}

impl From<u32> for Endianness {
    fn from(f: u32) -> Self {
        let endiannessdata = (f >> 15) & 0b1;
        match endiannessdata {
            0 => Endianness::LittleEndian,
            1 => Endianness::BigEndian,
            _ => unreachable!(),
        }
    }
}

#[derive(Debug)]
enum CoherencyAlgorithm {
    NotUsed,
    Used,
}

impl Default for CoherencyAlgorithm {
    fn default() -> Self {
        CoherencyAlgorithm::NotUsed
    }
}

impl From<u32> for CoherencyAlgorithm {
    fn from(f: u32) -> Self {
        let coherency_algorithmdata = f & 0b111;
        if coherency_algorithmdata == 0b010 {
            CoherencyAlgorithm::NotUsed
        } else {
            CoherencyAlgorithm::Used
        }

    }
}
<|endoftext|>